Search code examples
objective-ccsvnsstringnsarraynsscanner

Using NSScanner to separate string into NSArray by comma


Does anyone know how i can use NSScanner to separate a string by comma into an array EXCEPT when a comma is embedded within quotes?

Before i had been using:

  NSArray *arrData = [strData componentsSeparatedByString:@","];

However i have quotes inside the string that have commas inside them, i want these not to be separated. I have never worked with NSScanner before and i am struggling to come to terms with the documentation. Has anyone done a similar thing before?


Solution

  • If you absolutely have to use an NSScanner you could do something like this.

            NSScanner *scanner = [[NSScanner alloc] initWithString:@"\"Foo, Inc\",0.00,1.00,\"+1.5%\",\"+0.2%\",\"Foo"];
            NSCharacterSet *characters = [NSCharacterSet characterSetWithCharactersInString:@"\","];
            [scanner setCharactersToBeSkipped:nil];
            NSMutableArray *words = [[NSMutableArray alloc]init];
            NSMutableString *word = [[NSMutableString alloc] init];
            BOOL inQuotes = NO;
            while(scanner.isAtEnd == NO)
            {
                NSString *subString;
                [scanner scanUpToCharactersFromSet:characters intoString:&subString];
                NSUInteger currentLocation = [scanner scanLocation];
                if(currentLocation >= scanner.string.length)
                {
                    if(subString.length > 0)
                        [words addObject:subString];
                    break;
                }
                if([scanner.string characterAtIndex:currentLocation] == '"')
                {
                    inQuotes = !inQuotes;
                    if(subString == nil)
                    {
                        [scanner setScanLocation:currentLocation + 1];
                        continue;
                    }
                    [word appendFormat:@"%@",subString];
                    if(word.length > 0)
                       [words addObject:word.copy];
                    [word deleteCharactersInRange:NSMakeRange(0, word.length)];
                }
                if([scanner.string characterAtIndex:currentLocation] == ',')
                {
                    if(subString == nil)
                    {
                        [scanner setScanLocation:currentLocation + 1];
                        continue;
                    }
                    if(inQuotes == NO)
                        [words addObject:subString];
                    else
                        [word appendFormat:@"%@,",subString];
                }
                [scanner setScanLocation:currentLocation + 1];
            }
    

    EDIT: This gives the following output:

    Foo, Inc

    0.00

    1.00

    +1.5%

    +0.2%

    Foo

    Hope this is what you want

    As you can see it gets complicated and very error prone, I would recommend using Regex for this.