Использование NSScanner для разбора строки - PullRequest
6 голосов
/ 22 марта 2011

У меня есть строка с тегами форматирования, например There are {adults} adults, and {children} children. У меня есть словарь, в котором ключами являются «взрослые» и «дети», и мне нужно найти значение и заменить макросы на это значение. Это полностью динамично; ключи могут быть любыми (поэтому я не могу жестко кодировать stringByReplacingString).

Раньше я делал подобные вещи раньше, просто просматривая изменчивую строку и ища символы; удаляя то, что я уже искал из исходной строки, как я иду. Похоже, это именно то, для чего предназначен NSScanner, поэтому я попробовал это:

NSScanner *scanner = [NSScanner scannerWithString:format];
NSString *foundString;
scanner.charactersToBeSkipped = nil;

NSMutableString *formatedResponse = [NSMutableString string];

while ([scanner scanUpToString:@"{" intoString:&foundString]) {
    [formatedResponse appendString:[foundString stringByReplacingOccurrencesOfString:@"{" withString:@""]]; //Formatted string contains everything up to the {

    [scanner scanUpToString:@"}" intoString:&foundString];

    NSString *key = [foundString stringByReplacingOccurrencesOfString:@"}" withString:@""];

    [formatedResponse appendString:[data objectForKey:key]];

}

NSRange range = [format rangeOfString:@"}" options:NSBackwardsSearch];

if (range.location != NSNotFound) {
    [formatedResponse appendString:[format substringFromIndex:range.location + 1]];
}

Проблема в том, что когда моя строка начинается с "{", сканер возвращает НЕТ вместо ДА. (Что и должно быть в документации) Так я неправильно использую NSScanner? Тот факт, что scanUpToString не включает строку, которую искали как часть ее вывода, кажется, делает ее почти бесполезной ...

Может ли это быть легко изменено, чтобы делать то, что я хочу, или мне нужно переписать, используя изменяемую строку и поиск символов вручную?

1 Ответ

12 голосов
/ 22 марта 2011

Используйте isAtEnd, чтобы определить, когда остановиться. Кроме того, { и } не включены в результат scanUpToString:, поэтому они будут в начале следующей строки, но добавление после цикла не требуется, так как сканер будет возвращать отсканированное содержимое даже если строка поиска не найдена.

// Prevent scanner from ignoring whitespace between formats. For example, without this, "{a} {b}" and "{a}{b}" and "{a}     
//{b}" are all equivalent
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@""]];
while(![scanner isAtEnd]) {
    if([scanner scanUpToString:@"{" intoString:&foundString]) {
        [formattedResponse appendString:foundString];
    }
    if(![scanner isAtEnd]) {
        [scanner scanString:@"{" intoString:nil];
        foundString = @""; // scanUpToString doesn't modify foundString if no characters are scanned
        [scanner scanUpToString:@"}" intoString:&foundString];
        [formattedResponse appendString:[data objectForKey:foundString];
        [scanner scanString:@"}"];
    }
}
...