skwear skwear - 2 months ago 6
C++ Question

Separating number and unit in a string in C#

I have to write an equivalent of this in C++ in C#,

string val_in;
float val;
char unit[100];

val_in = NoSpace(val_in);

int nscan = sscanf(val_in.c_str(), "%f%s", &val, &unit);

if (nscan < 2) {
return val_in; //do nothing if scan fail
}


where the
NoSpace()
method trims and removes all spaces in
val_in
.

I have looked around here on SO and most of the similar questions involves strings that contain delimiters such as spaces or commas, but don't apply to this case. So I turned to RegEx.

So far, I have this,

string val_in;
float val;
char[] unit = new char[100];

string[] val_arr;

val_in = NoSpace(val_in);

val_arr = Regex.Split(val_in, @"([-]?\d*\.?\d+)([a-zA-Z]+)");
val = Single.Parse(val_arr[1]);

if (val_arr.Length < 2) {
return val_in; //do nothing if scan fail
}


It works so far, but I was wondering if there is another way to do this? I a bit wary of RegEx, because according the accepted answer on this question, having
([-]?\d*\.?\d+)
instead of
([-]?(\d*\.)?\d+)
is potentially dangerous because of evil RegEx. But if I include those extra parenthesis, then I have an extra group. This causes
Split()
to split something like
123.456miles
into an array with the elements,

{emptystr, 123.456, 123., miles}


This way, I can't be sure that the unit,
miles
in this case, will be in
val_arr[2]
, which is a problem.

I tested this on this .NET RegEx tester. I also tried to break my RegEx pattern,
([-]?\d*\.?\d+)
, but it seems to be fine and "evil RegEx safe". So I'm not sure if I should stick to what I've done so far, or find a more elegant solution, if one exist.

Answer

Not very elegant, but can't you just look for the first letter in the string to know where your unit starts?

  static void SplitValAndUnit(string unsplitData)
  {
     for (int x = 0; x < unsplitData.Length; x++)
     {
        if (Char.IsLetter(unsplitData[x]))
        {
           string value = unsplitData.Substring(0, x);
           // TryParse value to whatever data type
           string unit  = unsplitData.Substring(x, unsplitData.Length - x);
        }
     }
  }