10

When I need to stringify some values by joining them with commas, I do, for example:

string.Format("{0},{1},{3}", item.Id, item.Name, item.Count);

And have, for example, "12,Apple,20".
Then I want to do opposite operation, get values from given string. Something like:

parseFromString(str, out item.Id, out item.Name, out item.Count);

I know, it is possible in C. But I don't know such function in C#.

Sergey Metlov
  • 25,747
  • 28
  • 93
  • 153

4 Answers4

19

Yes, this is easy enough. You just use the String.Split method to split the string on every comma.

For example:

string myString = "12,Apple,20";
string[] subStrings = myString.Split(',');

foreach (string str in subStrings)
{
    Console.WriteLine(str);
}
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • So, then I should do: `item.Id = long.Parce(subStrings[0]); item.Name = subStrings[1]; item.Count = int.Parce(subStrings[2]);`... Is there any "faster" operation, like `scanf()` in C ? – Sergey Metlov Jul 22 '11 at 16:17
  • @DotNETNinja: Yes, to assign the sub-strings to a numeric type, you'll need to use the `Parse` method. And no, there's no "faster" operation. There's absolutely nothing "slow" about this method. If this is the bottleneck in your application, you have a **serious** problem. And in 99% of cases where you'll have to do this, it'll be to accept user input, and users are *always* the slowest point of any app. – Cody Gray - on strike Jul 22 '11 at 16:19
  • @DotNETNinja, If this is too slow, perhaps `string`s are the wrong type to use. Why not `Marshal` your structure? Wait, don't answer that ... – Jodrell Jul 22 '11 at 16:24
  • @Jodrell: What would you `Marshal` it to? I assume you're suggesting that he write a C++/CLI DLL that called `scanf` natively, and marshal data back and forth between that DLL and his C# application? If so, that's seriously misguided... The overhead of marshaling will **vastly** outweigh any performance benefits that the native code *might* offer. (I'm not even convinced that `scanf` will be faster in a head-to-head benchmark.) Not to mention the security and other well-known issues with `scanf` that you're avoiding by sticking with purely managed code. – Cody Gray - on strike Jul 22 '11 at 16:26
  • 1
    @Cody Gray, I meant "faster" = "less code" :) So, I understood your explanation, big thanks! – Sergey Metlov Jul 22 '11 at 16:35
  • @Cody Gary, sorry to mislead I wasn't attempting to make a serious suggestion. It was in fact failed humour. Everything you say in your response is probably right but I wouldn't commit without benchmarking. If this really is a performance problem .Net is the wrong platform. – Jodrell Jul 22 '11 at 16:35
  • @DotNETNinja: Right, well, that relationship doesn't always hold like it seems it would. There is hardly ever any truth to the principle that less code will run any faster, particularly in managed languages. Assuming such is the case before you carefully profile (with optimizations enabled!) is foolish. – Cody Gray - on strike Jul 22 '11 at 16:36
  • @Jodrell: Not necessarily; it depends on what you're doing. Many things written in C# are just as fast, if not faster, as the equivalent code written in C++. But yeah, sorry, I missed that that was supposed to be humour. It's quite a common mistake, thinking that C++ is *necessarily* faster than C#, and that it will *still* be faster if you call that code from a .NET app. Most people forget that there's a *huge* overhead in marshaling because it's so simple to implement in the .NET world (big thanks to the responsible programmers). – Cody Gray - on strike Jul 22 '11 at 16:38
  • @Cody Gary, There are lower levels that C++ but, once again not worth the effort. – Jodrell Jul 22 '11 at 16:47
11

Possible implementations would use String.Split or Regex.Match

example.

public void parseFromString(string input, out int id, out string name, out int count)
{
    var split = input.Split(',');
    if(split.length == 3) // perhaps more validation here
    {
        id = int.Parse(split[0]);
        name = split[1];
        count = int.Parse(split[2]);     
    }
}

or

public void parseFromString(string input, out int id, out string name, out int count)
{
    var r = new Regex(@"(\d+),(\w+),(\d+)", RegexOptions.IgnoreCase);
    var match = r.Match(input);
    if(match.Success)
    {
        id = int.Parse(match.Groups[1].Value);
        name = match.Groups[2].Value;
        count = int.Parse(match.Groups[3].Value);     
    }
}

Edit: Finally, SO has a bunch of thread on scanf implementation in C#
Looking for C# equivalent of scanf
how do I do sscanf in c#

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
Jamiec
  • 133,658
  • 13
  • 134
  • 193
3

If you can assume the strings format, especially that item.Name does not contain a ,

void parseFromString(string str, out int id, out string name, out int count)
{
    string[] parts = str.split(',');
    id = int.Parse(parts[0]);
    name = parts[1];
    count = int.Parse(parts[2]);
}

This will simply do what you want but I would suggest you add some error checking. Better still consider serializing/deserializing to XML or JSON.

Jodrell
  • 34,946
  • 5
  • 87
  • 124
2

Use Split function

var result = "12,Apple,20".Split(',');
Vlad Bezden
  • 83,883
  • 25
  • 248
  • 179