String analysis in C #

What is the most efficient way to parse a C # string in a form

"(params (abc 1.3)(sdc 2.0)(www 3.05)....)"

into the structure in the form

struct Params
{
  double abc,sdc,www....;
}

thank

EDIT A structure always has the same parameters (the same names, only doubles known at compile time), but no order is provided .. only one structure at a time.

+5
source share
8 answers

Depending on your full grammar, you have several options: if it is a very simple grammar and you do not need to check for errors in it, you can just go with below (which will be fast)

var input = "(params (abc 1.3)(sdc 2.0)(www 3.05)....)";
var tokens = input.Split('(');
var typeName = tokens[0];
//you'll need more than the type name (assembly/namespace) so I'll leave that to you
Type t = getStructFromType(typeName);
var obj = TypeDescriptor.CreateInstance(null, t, null, null);
for(var i = 1;i<tokens.Length;i++)
{
    var innerTokens = tokens[i].Trim(' ', ')').Split(' ');
    var fieldName = innerTokens[0];
    var value = Convert.ToDouble(innerTokens[1]);
    var field = t.GetField(fieldName);
    field.SetValue(obj, value);
}

, , .

, , nested(), .

regEx, , , , - . Irony , # ( BNF , ).

+2
using System;

namespace ConsoleApplication1
{
    class Program
    {
        struct Params
        {
            public double abc, sdc;
        };

        static void Main(string[] args)
        {
            string s = "(params (abc 1.3)(sdc 2.0))";
            Params p = new Params();
            object pbox = (object)p; // structs must be boxed for SetValue() to work

            string[] arr = s.Substring(8).Replace(")", "").Split(new char[] { ' ', '(', }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < arr.Length; i+=2)
                typeof(Params).GetField(arr[i]).SetValue(pbox, double.Parse(arr[i + 1]));
            p = (Params)pbox;
            Console.WriteLine("p.abc={0} p.sdc={1}", p.abc, p.sdc);
        }
    }
}

: , / .

+3

? , ; ?

.

, :

private static readonly Regex regParser = new Regex(@"^\(params\s(\((?<name>[a-zA-Z]+)\s(?<value>[\d\.]+)\))+\)$", RegexOptions.Compiled);

"" "". Captures .

, .

, Reflection, ; .

?

+2

:

public Dictionary<string, double> ParseString(string input){
    var dict = new Dictionary<string, double>();
    try
    {
        var re = new Regex(@"(?:\(params\s)?(?:\((?<n>[^\s]+)\s(?<v>[^\)]+)\))");
        foreach (Match m in re.Matches(input))
            dict.Add(m.Groups["n"].Value, double.Parse(m.Groups["v"].Value));
    }
    catch
    {
        throw new Exception("Invalid format!");
    }
    return dict;
}

:

string str = "(params (abc 1.3)(sdc 2.0)(www 3.05))";
var parsed = ParseString(str);

// parsed["abc"] would now return 1.3

, . , .

, , , .

+2

, , , NDesk.Options, Params. , .

public Params Parse(string input)
{
    var @params = new Params();
    var argv = ConvertToArgv(input);
    new NDesk.Options.OptionSet
        {
            {"abc=", v => Double.TryParse(v, out @params.abc)},
            {"sdc=", v => Double.TryParse(v, out @params.sdc)},
            {"www=", v => Double.TryParse(v, out @params.www)}
        }
        .Parse(argv);

    return @params;
}

private string[] ConvertToArgv(string input)
{
    return input
        .Replace('(', '-')
        .Split(new[] {')', ' '});
}
+1

?

, RegEx, Lexer. SO ,

"" , #

0

. , , .

0

: convert() {} [SPACE] ":", System.Web.Script.Serialization.JavaScriptSerializer.Deserialize

string s = "(params (abc 1.3)(sdc 2.0))"
  .Replace(" ", ":")
  .Replace("(", "{")
  .Replace(")","}"); 

return new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize(s);
0

All Articles