objective-cstringnumber-formattingnsnumbernsscanner

find all numbers in a string with a NSScanner


I used the below code to extract numbers from inputString using NSScanner

NSString *inputString = @"Dhoni7 notout at183*runs in 145andhehit15four's and10sixers100";
NSString *numberString;
NSArray *elements = [inputString componentsSeparatedByString:@" "];
for (int i=0; i<[elements count];i++)
{
    NSScanner *scanner = [NSScanner scannerWithString:[elements objectAtIndex:i]];
    NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"1234567890"];

    // Throw away characters before the first number.
    [scanner scanUpToCharactersFromSet:numbers intoString:NULL];

    // Collect numbers.
    [scanner scanCharactersFromSet:numbers intoString:&numberString];

    // Result.
    int number = [numberString integerValue];
    if (number != 0)
    {
        NSLog(@"%d\n",number);
        numberString = nil;
    }
}

My expected output is 7 183 145 15 10 100

but the output I am getting is 7 183 145 10

It just extracts first occurrence of a number from each word. Eg: if its Dho7ni89 it just detects the 7 and doesn't detect 89. I would be really happy if someone helps me figure out a way to fix this.


Solution

  • Your mistake is simple: you have started by making a false assumption. You artificially separate the string into words:

    NSArray *elements = [inputString componentsSeparatedByString:@" "];
    for (int i=0; i<[elements count];i++) {
        // scan for one number
    }
    

    Thus, that is exactly what happens. Each word is scanned for one number, once. If a word contains two numbers, the second number is never scanned - because that is not what you said to do.

    The solution is to stop making that false assumption. Don't separate the string into words at all! Just keep repeating the process:

    * scan up to a number
    * scan the number
    

    ...until you reach the end of the scanner's string (isAtEnd).