Сканеры
NSScanner
возразите сканирует символы NSString
объект, обычно интерпретируя символы и преобразовывая их в число и строковые значения. Вы присваиваете строку сканера на создании и прогресс сканера через символы той строки с начала до конца, поскольку Вы запрашиваете элементы.
Создание сканера
NSScanner
кластер класса с единственным общедоступным классом, NSScanner
. Обычно Вы инстанцируете объекта сканера путем вызова метод класса scannerWithString:
или localizedScannerWithString:
. Любой метод возвращает объект сканера, инициализированный со строкой, которую Вы передаете ему. Недавно создаваемый сканер запускается в начале его строки. Вы сканируете компоненты с помощью scan...
методы такой как scanInt:
, scanDouble:
, и scanString:intoString:
. При сканировании многократных строк Вы обычно создаете a while
цикл, продолжающийся, пока сканер не в конце строки, как проиллюстрировано в следующем фрагменте кода:
float aFloat; |
NSScanner *theScanner = [NSScanner scannerWithString:aString]; |
while ([theScanner isAtEnd] == NO) { |
[theScanner scanFloat:&aFloat]; |
// implementation continues... |
} |
Можно сконфигурировать сканер, чтобы рассмотреть или игнорировать регистр с помощью setCaseSensitive:
метод. По умолчанию сканер игнорирует регистр.
Используя сканер
Операции сканирования запускаются в расположении сканирования и совершенствуют сканер к только мимо последнего знака в отсканированном представлении значения (если таковые имеются). Например, после сканирования целого числа от строки “137 small cases of bananas
”, расположение сканера будет 3, указав пространство сразу после числа. Часто необходимо усовершенствовать расположение сканирования для пропуска символов, которыми Вы не интересуетесь. Можно изменить неявное местоположение сканирования с setScanLocation:
метод для пропускания определенного числа символов (можно также использовать метод, чтобы повторно отсканировать часть строки после ошибки). Как правило, однако, Вы или хотите пропустить символы от определенного набора символов, сканирования мимо определенной строки или сканирования до определенной строки.
Можно сконфигурировать сканер для пропуска ряда символов с setCharactersToBeSkipped:
метод. Сканер игнорирует символы, которые будут пропущены в начале любой работы сканирования. Как только это находит поддающийся сканированию символ, однако, это включает все символы, соответствующие запрос. Сканеры пропускают пробельные символы и символы новой строки по умолчанию. Обратите внимание на то, что случай, как всегда полагают, относительно символов пропускается. Для пропуска всех английских гласных, например, необходимо установить символы, которые будут пропущены тем в строке «AEIOUaeiou».
Если Вы хотите считать содержание из текущего расположения до определенной строки, можно использовать scanUpToString:intoString:
(можно передать NULL
как второй параметр, если Вы просто хотите пропустить прошедшие символы). Например, учитывая следующую строку:
137 small cases of bananas |
можно найти тип контейнера и число использования контейнеров scanUpToString:intoString:
как показано в следующем примере.
NSString *bananas = @"137 small cases of bananas"; |
NSString *separatorString = @" of"; |
NSScanner *aScanner = [NSScanner scannerWithString:bananas]; |
NSInteger anInteger; |
[aScanner scanInteger:&anInteger]; |
NSString *container; |
[aScanner scanUpToString:separatorString intoString:&container]; |
Важно отметить что строка поиска (separatorString
) " of"
. По умолчанию сканер игнорирует пробел, таким образом, проигнорирован пробел после целого числа. Как только сканер начинает накапливать символы, однако, все символы добавляются к выводимой строке, пока не достигнута строка поиска. Таким образом, если строка поиска "of"
(никакое пространство прежде), первое значение container
“маленькие случаи ” (включает пространство после); если строка поиска " of"
(с пространством прежде), первое значение container
“маленькие случаи” (никакое пространство после).
После сканирования до данной строки расположение сканирования является началом той строки. Если Вы хотите отсканировать мимо той строки, необходимо поэтому сначала отсканировать в строке, до которой Вы отсканировали. Следующий фрагмент кода иллюстрирует, как пропустить мимо строки поиска в предыдущем примере и определить тип продукта в контейнере. Отметьте использование substringFromIndex:
в действительности отсканировать до конца строки.
[aScanner scanString:separatorString intoString:NULL]; |
NSString *product; |
product = [[aScanner string] substringFromIndex:[aScanner scanLocation]]; |
// could also use: |
// product = [bananas substringFromIndex:[aScanner scanLocation]]; |
Пример
Предположим, что у Вас есть строка, содержащая строки, такие как:
Продукт: картофелечистка высшей точки; стоимость: 0.98 73
Продукт: ветвление пасты повара Пьера; стоимость: 0.75 19
Продукт: дуршлаг повара Пьера; стоимость: 1.27 2
Следующее использование в качестве примера, чередующее операции сканирования для извлечения названия продукта и затраты (затраты читаются как a float
для пользы простоты), пропуская ожидаемые подстроки «продукт»: и «Стоимость»: а также точка с запятой. Обратите внимание на то, что, потому что сканер пропускает пробел и новые строки по умолчанию, цикл не делает никакой специальной обработки для них (в частности нет никакой потребности сделать дополнительную пробельную обработку для получения заключительного целого числа).
NSString *string = @"Product: Acme Potato Peeler; Cost: 0.98 73\n\ |
Product: Chef Pierre Pasta Fork; Cost: 0.75 19\n\ |
Product: Chef Pierre Colander; Cost: 1.27 2\n"; |
NSCharacterSet *semicolonSet; |
NSScanner *theScanner; |
NSString *PRODUCT = @"Product:"; |
NSString *COST = @"Cost:"; |
NSString *productName; |
float productCost; |
NSInteger productSold; |
semicolonSet = [NSCharacterSet characterSetWithCharactersInString:@";"]; |
theScanner = [NSScanner scannerWithString:string]; |
while ([theScanner isAtEnd] == NO) |
{ |
if ([theScanner scanString:PRODUCT intoString:NULL] && |
[theScanner scanUpToCharactersFromSet:semicolonSet |
intoString:&productName] && |
[theScanner scanString:@";" intoString:NULL] && |
[theScanner scanString:COST intoString:NULL] && |
[theScanner scanFloat:&productCost] && |
[theScanner scanInteger:&productSold]) |
{ |
NSLog(@"Sales of %@: $%1.2f", productName, productCost * productSold); |
} |
} |
Локализация
Сканер базирует часть своего поведения сканирования на локали, указывающей язык и соглашения для представлений значения. NSScanner
использование только определение локали для десятичного разделителя (данный ключом назван NSDecimalSeparator
). Можно создать сканер с локалью пользователя при помощи localizedScannerWithString:
, или набор локаль явно с помощью setLocale:
. Если Вы используете метод, не указывающий локаль, сканер принимает значения локали по умолчанию.