tags:

views:

286

answers:

9

If I have a string like:

"26 things"

I want to convert it to 26. I just want the integer at the beginning of the string.

If I was using C, I'd just use the atoi function. But I can't seem to find anything equivalent in .NET.

What's the easiest way to grab the integer from the beginning of a string?

Edit: I'm sorry I was ambiguous. The answers that look for a space character in the string will work in many circumstances (perhaps even mine). I was hoping for an atoi-equivalent in .NET. The answer should also work with a string like "26things". Thanks.

A: 

The direct equivalent is int.Parse(string) but I'm not entirely sure if that will take just the starting number.

Elliot Hughes
I think you might have to write a specific function yourself to grab the number part, perhaps using the .NET String.Substring() function..?
Phill
It throws an exception on non-numeric data.
Jeremy Stein
Yeah - that's what I suspected.
Elliot Hughes
@Jeremy Stein: use int.TryParse() instead
Jasper Bekkers
@Jasper Bekkers: TryParse would give me 0.
Jeremy Stein
A: 

I can think just in something like this:

 public static string Filter(string input, string validChars) {
  int i;
  string result = "";
  for (i = 0; i < input.Length; i++) {
   if (validChars.IndexOf(input.Substring(i, 1)) >= 0) {
    result += input.Substring(i, 1);
   } else break;
  }
  return result ;
 }

And call it :

Filter("26 things", "0123456789");
Jhonny D. Cano -Leftware-
I would argue if you're going to take that path then you should just use regular expressions.
Nazadus
Well, you maybe right... but anyway my solution is better than the ones using .IndexOf(" ")
Jhonny D. Cano -Leftware-
As Timbo shows, why not just use char.IsDigit(c).
Erich Mirabal
+1  A: 

You could use Int32.Parse(stringVal.Substring(0, stringVal.indexOf(" "))

Charles Bretana
That would work for me. I was wondering if there was a more atoi-like answer that didn't require the number to be followed by a space.
Jeremy Stein
+7  A: 

This should work (edited to ignore white-space at the begining of the string)

int i = int.Parse(Regex.Match("26 things", @"^\s*(\d+)").Groups[1].Value);

If you are worried about checking if there is a value you could do the following to give you a -1 value if there is no integer at the begining of the string.

Match oMatch = Regex.Match("26 things", @"^\s*(\d+)");
int i = oMatch.Success ? int.Parse(oMatch.Groups[1].Value) : -1;
Stevo3000
Oh please, no regex for such a trivial task.
Noldorin
@Noldorin - Why not, it's a perfectly valid use of regex. I'm not sure why this needs a down-vote just because you would do it differently?
Stevo3000
@Stevo: It's simply overkill when you can use string splitting/simple text manipulation. (And a lot more efficient, though this may or may not matter.) Down vote removed however, since you are right - it is still a valid solution.
Noldorin
@Noldorin: Why not? For simple tasks like these, the regex is actually easily readable. To be honest, I find it clearer than your solution.
jalf
@Noldorin - Simple text manipulation will not work as efficiently nor as simply as a regular expression in this case. I agree that regular expressions can be abused, but this is a great case for using one.
Stevo3000
Wondering why I've still got a down-vote for an answer that answers the question and is easily readable?
Stevo3000
I was torn. I posted this question to see how I could do it without a regex. But your answer is concise and readable. I upvoted Noldorin's "please no regex" comment, but this is still the best answer. It does seem ironic that the trivial and fast atoi function is best emulated with the complex regex engine.
Jeremy Stein
To match atoi, the regex should be ^\s*\d+
Jeremy Stein
If "26 things" or "26things" is a variable passed into this, then you can potentially get some exceptiosn. If the input string is null you'll get a NullReferenceException. If there are no digits or any non-digit character(s) (like whitespace or '-') at the start of the string you'll get a FormatException because the regex returns an empty string. You can even an OverflowException if the number extracted is greater than int.MaxValue or less than int.MinValue.
Brian Reiter
@Brian Reiter - The code is obviously not error trapped, it is just a quick example.
Stevo3000
By default, int.Parse will ignore whitespace, so you don't need to use the regex group.
Jeremy Stein
@Stevo300. My point was really that atoi() wouldn't throw an excpetion it would just return 0 if there was no number in the string. I think it would also just wrap the integer around if it overflowed but not sure on that one.
Brian Reiter
@Brian Reiter - If a 0 value is required as default then my second code example could have the -1 changed to 0.
Stevo3000
@Jeremy Stein - I realise the group could be discarded, but using it makes what the code is doing much clearer (readability is especially important where using regex) and removes the possiblity of hard to find bugs if the default parse behaviour changes.
Stevo3000
+1  A: 

one way would be

    string sample = "26 things";
    int x = int.Parse(sample.Substring(0, sample.IndexOf(" ")));
schar
doesn't work with "26things" which would be no problem for atoi
Christopher
Lame excuse but let me try: That was not the requirement.
schar
A: 

You've got to split the string and then parse it:

var str = "26 things";
var count = int.Parse(str.Split(' ')[0]);
Noldorin
what for a string like 26things?
Jhonny D. Cano -Leftware-
Such a format was not specified in the question. If it is possible, the question needs to be clarified.
Noldorin
This is not in the requirement first of all.. with ATOI the guy whould have to specify the pointer length too. This is a valid option.
Daok
@Noldorin - Not true, he asked 'What's the easiest way to grab the integer from the beginning of a string?', and 26things fits this criteria. Thre is no mention of a format other than integer at begining of string!
Stevo3000
Also, reason for down vote please?
Noldorin
Well, I did say equivalent to atoi in the title. I'll clarify.
Jeremy Stein
@Noldorin - I didn't down vote.
Stevo3000
+10  A: 

This looks sooo beautiful:

string str = "26 things";
int x = int.Parse(str.TakeWhile(ch => char.IsDigit(ch)).Aggregate("", (s, ch) => s + ch));

And, the boring solution for anyone who really wants atoi:

[System.Runtime.InteropServices.DllImport("msvcrt.dll")]
private static extern int atoi(string str);
Timbo
+1 beat me to it. Regex works too but I was going with this for practice. Also meets the OPs clarified requirements.
Ahmad Mageed
I love this answer. It matches the spirit of atoi. I just think it's a little hard to read, at least for me, so I accepted the regex.
Jeremy Stein
+1. I prefer the LINQ over Regex. You can also improve on this by adding a SkipWhile to ignore any text before the number (in case of "There are 26 things") and it would be even more robust.
Erich Mirabal
Also, I would split the steps so you have see the string to be parsed instead of cramming it all in one line.
Erich Mirabal
To completely match the atoi functionality, you should first trim the string.
Jeremy Stein
int.Parse(new string(str.TakeWhile(ch => char.IsDigit(ch)).ToArray())); works too and is shorter. I would suspect it's also faster, but I couldn't say without benchmarking
Jimmy
Yes, that should be faster. Aggregate will create count-of-chars temporary string objects. Anyone looking for speed can take approach #2 :-)
Timbo
A: 

Try this:

int i = int.Parse("26 things".Split(new Char[] {' '})[0]);
mkoeller
A: 

You can call Val in the Microsoft.VisualBasic.Conversion namespace. In your scenario it should print "26". I don't know if it's 100% compatible in toher scenarios though. Here's a link to the specification.

http://msdn.microsoft.com/en-us/library/k7beh1x9%28VS.71%29.aspx

Jacob Adams
It returns 26123 for the string "26 123" which is not what atoi would do.
Timbo