使用 NSScanner 查找字符串中的所有数字
find all numbers in a string with a NSScanner
我使用下面的代码从 inputString
中使用 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;
}
}
我的预期输出是
7
183
145
15
10
100
但我得到的输出是
7
183
145
10
它只是从每个单词中提取第一次出现的数字。例如:如果它的 Dho7ni89 它只检测到 7 而没有检测到 89。如果有人能帮我想出解决这个问题的方法,我会很高兴。
你的错误很简单:你一开始就做出了错误的假设。你人为地将字符串分成单词:
NSArray *elements = [inputString componentsSeparatedByString:@" "];
for (int i=0; i<[elements count];i++) {
// scan for one number
}
因此,这正是发生的事情。每个 word 被扫描为 one 号码,once。如果一个单词包含两个数字,则永远不会扫描第二个数字 - 因为这不是您所说的。
解决办法是停止做出错误的假设。根本不要将字符串分成单词!继续重复这个过程:
* scan up to a number
* scan the number
...直到到达扫描仪字符串的末尾 (isAtEnd
)。
Matt 的速度稍快一些。
为什么要在开头拆分字符串?
稍微重新安排一下代码就会产生所需的结果:
NSScanner *scanner = [NSScanner scannerWithString:@"Dhoni7 notout at183*runs in 145andhehit15four's and10sixers100"];
NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"1234567890"];
while (true) {
// Throw away characters before a number
[scanner scanUpToCharactersFromSet:numbers intoString:NULL];
// Read the number
NSString *numberString;
if ([scanner scanCharactersFromSet:numbers intoString:&numberString]) {
long number = [numberString integerValue];
NSLog(@"%ld\n",number);
} else {
break;
}
}
正在输出
7
183
145
15
10
100
注意
您也可以使用
NSCharacterSet *numbers = [NSCharacterSet decimalDigitCharacterSet];
过滤掉数字。我发现这比列出字符要简洁一些。但是,它将包括例如印度文字和阿拉伯文字的十进制数字。
我使用下面的代码从 inputString
中使用 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;
}
}
我的预期输出是 7 183 145 15 10 100
但我得到的输出是 7 183 145 10
它只是从每个单词中提取第一次出现的数字。例如:如果它的 Dho7ni89 它只检测到 7 而没有检测到 89。如果有人能帮我想出解决这个问题的方法,我会很高兴。
你的错误很简单:你一开始就做出了错误的假设。你人为地将字符串分成单词:
NSArray *elements = [inputString componentsSeparatedByString:@" "];
for (int i=0; i<[elements count];i++) {
// scan for one number
}
因此,这正是发生的事情。每个 word 被扫描为 one 号码,once。如果一个单词包含两个数字,则永远不会扫描第二个数字 - 因为这不是您所说的。
解决办法是停止做出错误的假设。根本不要将字符串分成单词!继续重复这个过程:
* scan up to a number
* scan the number
...直到到达扫描仪字符串的末尾 (isAtEnd
)。
Matt 的速度稍快一些。
为什么要在开头拆分字符串?
稍微重新安排一下代码就会产生所需的结果:
NSScanner *scanner = [NSScanner scannerWithString:@"Dhoni7 notout at183*runs in 145andhehit15four's and10sixers100"];
NSCharacterSet *numbers = [NSCharacterSet characterSetWithCharactersInString:@"1234567890"];
while (true) {
// Throw away characters before a number
[scanner scanUpToCharactersFromSet:numbers intoString:NULL];
// Read the number
NSString *numberString;
if ([scanner scanCharactersFromSet:numbers intoString:&numberString]) {
long number = [numberString integerValue];
NSLog(@"%ld\n",number);
} else {
break;
}
}
正在输出
7 183 145 15 10 100
注意
您也可以使用
NSCharacterSet *numbers = [NSCharacterSet decimalDigitCharacterSet];
过滤掉数字。我发现这比列出字符要简洁一些。但是,它将包括例如印度文字和阿拉伯文字的十进制数字。