user3351548
user3351548

Reputation: 71

Int32.TryParse with multiple group separators

I'm trying to create a method that can handle and validate integers as on ok input. The issue is our requirements which states the following numbers as an ok input regardless of chosen language:

1500, 1.500, 1,500, 1 500
-1500, -1.500, -1,500, -1 500
1500000, 1.500.500, 1,500,500 1 500 500
-1500000, -1.500.500, -1,500,500 -1 500 500

and so on.

My method now looks like this:

private bool TryParseInteger(string controlValue, out int controlInt)
{
      int number;
      NumberStyles styles = NumberStyles.Integer | NumberStyles.AllowThousands;

      bool result = Int32.TryParse(controlValue, styles,
            CultureInfo.InvariantCulture, out number);
      controlInt = number;

      return result;
}

This does not work as I want it to. 1.500 and 1.500.500 is not validated as a correct input.

Is there another way to approach this?

Thanks for all the help. As it turns out 1.500,50 (and so on) should not pass validation which makes the suggested solutions not work. Any other ideas?

Upvotes: 7

Views: 839

Answers (4)

bubbinator
bubbinator

Reputation: 495

I think the issue here is that 1.500 is understood differently per country. For instance, in the US that is equal to 1 and a half with some pointless zeroes where in Germany (I if memory serves) it is understood to be one thousand, five hundred.

In harmony with that, you should add a line at the beginning of the method like this:

controlValue = new string(controlValue.Where(c => !char.IsPunctuation(c) && c != ' ' || c == '-'));

This will remove all commas, periods and spaces which will work given that you only want integers. If you wanted to get a decimal, then we'd be in trouble...

Upvotes: 3

Stephan Zaria
Stephan Zaria

Reputation: 496

You can create your own custom culture, and alter the NumberGroupSeparator as needed.

    private static bool TryParseInteger(string controlValue, out int controlInt)
    {
        String[] groupSeparators = { ",", ".", " "};
        CultureInfo customCulture = CultureInfo.InvariantCulture.Clone() as CultureInfo;
        customCulture.NumberFormat.NumberDecimalSeparator = "SomeUnlikelyString";

        NumberStyles styles = NumberStyles.Integer | NumberStyles.AllowThousands;

        bool success = false;
        controlInt = 0;
        foreach (var separator in groupSeparators)
        {
            customCulture.NumberFormat.NumberGroupSeparator = separator;
            success = Int32.TryParse(controlValue, styles, customCulture, out controlInt);

            if (success)
            {
                break;
            }
        }

        return success;
    }

Upvotes: 0

crates_barrels
crates_barrels

Reputation: 1028

If you don't want to match 1,500.500 or 1.500,500, you can replace all .'s to ,'s and try to parse it again. Something like this:

private bool TryParseInteger(string controlValue, out int controlInt)
{
      int number;
      NumberStyles styles = NumberStyles.Integer | NumberStyles.AllowThousands;

      bool result = Int32.TryParse(controlValue, styles,
            CultureInfo.InvariantCulture, out number);

      if (!result)
      {
            controlValue = controlValue.Replace('.', ',');
            result = Int32.TryParse(controlValue, styles,
                  CultureInfo.InvariantCulture, out number);
      }
      controlInt = number;

      return result;
}

Upvotes: 3

astef
astef

Reputation: 9508

Just replace all those signs!

This code:

string[] arr = new[] { "1500", "1.500", "1,500", "1 500", "-1500", "-1.500", "-1,500", "-1 500",
                                "1500000", "1.500.500", "1,500,500","1 500 500",
                                "-1500000", "-1.500.500", "-1,500,500","-1 500 500"};

foreach (var s in arr)
{
    int i = int.Parse(s.Replace(" ", "").Replace(",", "").Replace(".", ""));

    Console.WriteLine(i);
}

Produces:

1500

1500

1500

1500

-1500

-1500

-1500

-1500

1500000

1500500

1500500

1500500

-1500000

-1500500

-1500500

-1500500

Upvotes: 3

Related Questions