当逗号嵌入到引号中时,是否有人知道如何使用NSScanner将字符串用逗号分隔成数组?
在我使用之前:
NSArray *arrData = [strData componentsSeparatedByString:@","];
但是我在字符串里面有引号,里面有逗号,我希望这些不要分开。我之前从未与NSScanner合作过,而且我正在努力与文档达成协议。有没有人以前做过类似的事情?
答案 0 :(得分:1)
如果你必须使用NSScanner,你可以做这样的事情。
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];
}
修改强> 这给出了以下输出:
Foo,Inc
0.00
1.00
1.5%
+ 0.2%
富
希望这是你想要的
正如您所看到的那样复杂且非常容易出错,我建议您使用正则表达式。
答案 1 :(得分:1)
这与lead_the_zeppelin's answer的一般程序相同,但我认为它更直截了当。我们使用NSMutableString
,accum
来构建每个评论内部分,其中可能包含任意数量的引用部分。
每次迭代,我们扫描到逗号,引号或字符串的结尾,以先到者为准。如果我们找到一个逗号,那么到目前为止积累的任何内容都应该保存。对于引用,我们选取所有内容直至结束引号 - 这是避免将引号内的逗号解释为分割点的关键。请注意,如果报价并非总是平衡,则此不会起作用。如果它们都不是,我们已经到达字符串的末尾,所以我们保存累积的字符串并退出。
// Demo data
NSArray * commaStrings = @[@"This, here, \"has\" no quoted, commas.",
@"This \"has, no\" unquoted \"commas,\"",
@"This, has,no,quotes",
@"This has no commas",
@"This has, \"a quoted\" \"phrase, followed\", by a, quoted phrase",
@"\"This\", one, \"went,\", to, \"mar,ket\"",
@"This has neither commas nor quotes",
@"This ends with a comma,"];
NSCharacterSet * commaQuoteSet = [NSCharacterSet characterSetWithCharactersInString:@",\""];
for( NSString * commaString in commaStrings ){
NSScanner * scanner = [NSScanner scannerWithString:commaString];
// Scanner ignores whitespace by default; turn that off.
[scanner setCharactersToBeSkipped:nil];
NSMutableArray * splitStrings = [NSMutableArray new];
NSMutableString * accum = [NSMutableString new];
while( YES ){
// Set to an empty string for the case where the scanner is
// at the end of the string and won't scan anything;
// appendString: will die if its argument is nil.
NSString * currScan = @"";
// Scan up to a comma or a quote; this will go all the way to
// the end of the string if neither of those exists.
[scanner scanUpToCharactersFromSet:commaQuoteSet
intoString:&currScan];
// Add the just-scanned material to whatever we've already got.
[accum appendString:currScan];
if( [scanner scanString:@"," intoString:NULL] ){
// If it's a comma, save the accumulated string,
[splitStrings addObject:accum];
// clear it out,
accum = [NSMutableString new];
// and keep scanning.
continue;
}
else if( [scanner scanString:@"\"" intoString:NULL] ) {
// If a quote, append the quoted segment to the accumulation,
[scanner scanUpToString:@"\""
intoString:&currScan];
[accum appendFormat:@"\"%@\"", currScan];
// and continue, appending until the next comma.
[scanner scanString:@"\"" intoString:NULL];
continue;
}
else {
//Otherwise, there's nothing else to split;
// just save the remainder of the string
[splitStrings addObject:accum];
break;
}
}
NSLog(@"%@", splitStrings);
}
另外,as Chuck suggested,您可能只想获得一个CSV解析器。