views:

122

answers:

7

I have a string and I want to check that it only consists of digits. I don't really want to (or need to) parse it or anything, I just want to know that it does not contain anything but digits (and no floating point separator either, just digits).

PHP has this nice function called ctype_digit. Is there anything similar for C# anywhere in the .Net Framework? Or do I need to use a regular expression or something like that?

Creating a regex for this would of course be pretty simple, but I would like to not use it if there are better ways :p

+8  A: 

You could use int.TryParse. It will return true if the supplied string represents a valid number, false otherwise. Don't forget to use NumerStyles.None to disallow blank spaces and the plus/minus sign.

UPDATE: As empi says, this will not work for very large strings. If you have arbitrarily large strings, maybe a regex is your only option. You could do something like Regex.IsMatch(theString,"^[0-9]+$")

Konamiman
This will allow +/- chars aswell...
astander
I was editing the answer to comment about NumberStyles while you were typing.
Konamiman
This function also checks if the number fits in int or long. For example it will say that 1234567890123456789012345678901234567890123456789012345678901234567890 is not a valid number.
empi
what I don't like about TryParse is that you have to create that `int` for the `out`ing. But yes... maybe I'll make an extension method or something :p
Svish
you dont iirc, you can just say int.TryParse("123", new int);
Pondidum
@Andy - Unfortunately this will not work as `out` parameters require that you pass an assignable variable.
Andrew Hare
Ah, well it works in vb.net :D
Pondidum
+1  A: 

Yes, you can use

bool Int32.TryParse(string s, out int result);

Code sample:

string myString = "1265";
int myInt;

if (Int32.TryParse(myString,myInt) // Returns true if mystring contains only digits
{
...
}

Other option is to use Regex:

    public static bool IsDigit(string myString)
    {
        string pattern = @"^\d*$";

        if (Regex.IsMatch(myString, pattern))
            return true;
        else
            return false;
    }

You can change the pattern as per your requirement.

Rashmi Pandit
A: 

There is no built-in method. Int32.TryParse or Int64.TryParse won't work for very long strings containing just numbers (they may also allow other chars used to represent integer numbers).

empi
+3  A: 
bool onlyDigits = "1234".All(c => char.IsDigit(c));
bruno conde
I just have had a "How is that I did not think on that before??" moment :-)
Konamiman
Anyway I would change the FirtsOrDefault to: All(c => char.IsDigit(c))
Konamiman
@konamiman: Just added an answer using that. And pretty much that exact sentence, "Can't believe I didn't think of it before..." -- haha.
Svish
@Konamiman, nice one. I always forget these methods (All and Any) ;)
bruno conde
@bruno conde, as you can see in my answer you can even skip the `ToCharArray()` and the `c => ... (c)` parts :)
Svish
+1 From me. Just a side note, your solution could be simplified to this: `"1234".All(Char.IsDigit)` since `System.String` already implements `IEnumerable<Char>` so you don't need to explicitly create a character array. As for the lambda expression, you don't need it (for more info on this please see http://togaroga.com/blog/2009/11/you-dont-always-need-a-lambda-expression/).
Andrew Hare
Fixed. Interesting, my Visual Studio 2008 doesn't show me the extension methods of IEnumerable<> for string. I wonder if it's just me...
bruno conde
@bruno: No, that affects everybody's Visual Studio and isn't customisable (as far as I'm aware). I suppose MS assumed that we wouldn't want our intellisense "polluted" by all the LINQ extension methods when dealing with plain strings.
LukeH
Hm... ReSharper must have done something to my intellisense then, cause I see all the extension methods in my pop-up :)
Svish
+1  A: 

Methinks, you'd be better to use regex to do the job for you... "\d+" should do it...ok, you said you do not want to use it... but it is foolproof way of ensuring the string contains only numbers, then if the regexp passes, then you can use int.Parse(...) straightaway.

tommieb75
+5  A: 

The answer of @bruno conde made me think of this :D

if(subject.All(char.IsDigit))
    // Do something

Can't believe I didn't think of it before...

Svish
This should be the accepted answer IMHO.
Konamiman
Yeah, I kinda think so too, although I don't like to give it to myself :p (can't mark it until 48 hours... but will do :p)
Svish
A: 

As other people have said, you can use the int.TryParse method, although unless your number is really really EXTREMELY big, you could use the TryParse method of other types, that have a bigger range than int32's. (of course using the NumberStyles.None option, to avoid signs and punctuation).

Here's the break down:

  1. int -2,147,483,648 .. 2,147,483,647
  2. uint 0 .. 4,294,967,295
  3. long -9,223,372,036,854,775,808 .. 9,223,372,036,854,775,807
  4. ulong 0 .. 18,446,744,073,709,551,615
  5. float -3.402823e38 .. 3.402823e38
  6. double -1.79769313486232e308 .. 1.79769313486232e308
  7. decimal -79228162514264337593543950335 .. 79228162514264337593543950335

The one that can parse the biggest numbers is Double. If you need to use the number , you will lose some precision, but it can parse really long numbers (although you say you dont need to use it so it shouldnt be a problem). In a quick test I did, it managed to successfully parse the following string:

79228162514264337593543950335792281625142643375935439503357922816251426433759354395033579228162514264337593543950335792281625142643375935439503357922816251426433759354395033579228162514264337593543950335792281625142643375935439503357922816251426433759354395033579228162514264337593543950335234234234234243423

(thats 308 characters, it would fail with one more number)

Still, if you are not going to use the number, it might be an overkill, so I would go for the Regex, or even better the loop checking that each character is a digit.

If you then wanna go a little crazy you could split that into several smaller strings, and use the Task library to check it in a parallel way :P

(I know its a little offtopic now, but if you DO want to do that, you should check parallel.for and the Partition Ranger, check out this C9 10min clip: Parallel For Partition Ranger )

Francisco Noriega