11.Scanners

扫描仪
相关链接:
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Strings/Articles/Scanners.html#//apple_ref/doc/uid/20000147-BCIEFGHC

An NSScanner object scans the characters of an NSString object, typically interpreting the characters and converting them into number and string values. You assign the scanner’s string on creation, and the scanner progresses through the characters of that string from beginning to end as you request items.

  • “NSScanner”对象扫描“NSString”对象的字符,通常解释字符并将它们转换为数字和字符串值。 您在创建时分配扫描仪的字符串,并且当您请求项目时,扫描程序将从头到尾逐步显示该字符串的字符。

Creating a Scanner

NSScanner is a class cluster with a single public class, NSScanner. Generally, you instantiate a scanner object by invoking the class method scannerWithString: or localizedScannerWithString:. Either method returns a scanner object initialized with the string you pass to it. The newly created scanner starts at the beginning of its string. You scan components using the scan... methods such as scanInt:, scanDouble:, and scanString:intoString:. If you are scanning multiple lines, you typically create a while loop that continues until the scanner is at the end of the string, as illustrated in the following code fragment:

  • NSScanner是一个具有单个公共类NSScanner的类集群。 通常,您通过调用类方法scannerWithString:或localizedScannerWithString:来实例化扫描程序对象。 这两种方法都返回一个扫描程序对象,该对象是使用传递给它的字符串初始化 新创建的扫描程序从其字符串的开头开始。 您可以使用scan ...方法扫描组件,例如scanInt:,scanDouble:和scanString:intoString:。 如果要扫描多行,通常会创建一个while循环,直到扫描程序位于字符串的末尾,如下面的代码片段所示:
float aFloat;
NSScanner *theScanner = [NSScanner scannerWithString:aString];
while ([theScanner isAtEnd] == NO) {
 
    [theScanner scanFloat:&aFloat];
    // implementation continues...
}

You can configure a scanner to consider or ignore case using the setCaseSensitive: method. By default a scanner ignores case.

  • 您可以使用setCaseSensitive:方法将扫描程序配置为考虑或忽略大小写。 默认情况下,扫描程序忽略大小写。

Using a Scanner

Scan operations start at the scan location and advance the scanner to just past the last character in the scanned value representation (if any). For example, after scanning an integer from the string “137 small cases of bananas”, a scanner’s location will be 3, indicating the space immediately after the number. Often you need to advance the scan location to skip characters in which you are not interested. You can change the implicit scan location with the setScanLocation: method to skip ahead a certain number of characters (you can also use the method to rescan a portion of the string after an error). Typically, however, you either want to skip characters from a particular character set, scan past a specific string, or scan up to a specific string.

  • 扫描操作从扫描位置开始,并使扫描仪前进到扫描值表示中的最后一个字符(如果有)。 例如,在扫描字符串“137个小香蕉盒”中的整数后,扫描仪的位置将为3,表示该数字后面的空格。 通常,您需要提前扫描位置以跳过您不感兴趣的字符。 您可以使用setScanLocation:方法更改隐式扫描位置以向前跳过一定数量的字符(您也可以使用该方法在发生错误后重新扫描字符串的一部分)。 但是,通常,您要么跳过特定字符集中的字符,扫描特定字符串,要么扫描到特定字符串。

You can configure a scanner to skip a set of characters with the setCharactersToBeSkipped: method. A scanner ignores characters to be skipped at the beginning of any scan operation. Once it finds a scannable character, however, it includes all characters matching the request. Scanners skip whitespace and newline characters by default. Note that case is always considered with regard to characters to be skipped. To skip all English vowels, for example, you must set the characters to be skipped to those in the string “AEIOUaeiou”.

  • 您可以使用setCharactersToBeSkipped:方法将扫描程序配置为跳过一组字符。 扫描程序忽略在任何扫描操作开始时要跳过的字符。 但是,一旦找到可扫描的字符,它就会包含与请求匹配的所有字符。 默认情况下,扫描程序会跳过空格和换行符。 请注意,始终考虑关于要跳过的字符的大小写。 例如,要跳过所有英语元音,必须将要跳过的字符设置为字符串“AEIOUaeiou”中的字符。

If you want to read content from the current location up to a particular string, you can use scanUpToString:intoString: (you can pass NULL as the second argument if you simply want to skip the intervening characters). For example, given the following string:

  • 如果要从当前位置读取内容到特定字符串,可以使用scanUpToString:intoString :(如果您只想跳过插入的字符,则可以将NULL作为第二个参数传递)。 例如,给定以下字符串:
137 small cases of bananas

you can find the type of container and number of containers using scanUpToString:intoString: as shown in the following example.

  • 您可以使用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];

It is important to note that the search string (separatorString) is " of". By default a scanner ignores whitespace, so the space character after the integer is ignored. Once the scanner begins to accumulate characters, however, all characters are added to the output string until the search string is reached. Thus if the search string is "of" (no space before), the first value of container is “small cases ” (includes the space following); if the search string is " of" (with a space before), the first value of container is “small cases” (no space following).

  • 重要的是要注意搜索字符串(separatorString)是“of”。 默认情况下,扫描程序会忽略空格,因此忽略整数后的空格字符。 但是,一旦扫描程序开始累积字符,所有字符都将添加到输出字符串,直到到达搜索字符串。 因此,如果搜索字符串是“of”(之前没有空格),则容器的第一个值是“小情况”(包括后面的空格); 如果搜索字符串是“of”(前面有空格),则容器的第一个值是“small cases”(后面没有空格)。

After scanning up to a given string, the scan location is the beginning of that string. If you want to scan past that string, you must therefore first scan in the string you scanned up to. The following code fragment illustrates how to skip past the search string in the previous example and determine the type of product in the container. Note the use of substringFromIndex: to in effect scan up to the end of a string.

  • 扫描到给定字符串后,扫描位置是该字符串的开头。 如果要扫描该字符串,则必须先扫描最近扫描的字符串。 以下代码片段说明了如何跳过前一个示例中的搜索字符串并确定容器中的产品类型。 注意使用substringFromIndex:实际上扫描到字符串的结尾。
[aScanner scanString:separatorString intoString:NULL];
NSString *product;
product = [[aScanner string] substringFromIndex:[aScanner scanLocation]];
// could also use:
// product = [bananas substringFromIndex:[aScanner scanLocation]];

Example

Suppose you have a string containing lines such as:

  • 假设您有一个包含以下行的字符串:
  • Product: Acme Potato Peeler; Cost: 0.98 73

    • 产品:Acme土豆去皮机; 费用:0.98 73
  • Product: Chef Pierre Pasta Fork; Cost: 0.75 19

    • 产品:厨师Pierre Pasta Fork; 费用:0.75 19
  • Product: Chef Pierre Colander; Cost: 1.27 2

    • 产品:厨师Pierre Colander; 费用:1.27 2

The following example uses alternating scan operations to extract the product names and costs (costs are read as a float for simplicity’s sake), skipping the expected substrings “Product:” and “Cost:”, as well as the semicolon. Note that because a scanner skips whitespace and newlines by default, the loop does no special processing for them (in particular there is no need to do additional whitespace processing to retrieve the final integer).

  • 以下示例使用交替扫描操作来提取产品名称和成本(为简单起见,成本读取为浮点数),跳过预期的子串“Product:”和“Cost:”,以及分号。 请注意,由于扫描程序默认情况下会跳过空格和换行符,因此循环不对它们进行特殊处理(特别是不需要执行额外的空格处理来检索最终整数)。
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);
    }
}

Localization

A scanner bases some of its scanning behavior on a locale, which specifies a language and conventions for value representations. NSScanner uses only the locale’s definition for the decimal separator (given by the key named NSDecimalSeparator). You can create a scanner with the user’s locale by using localizedScannerWithString:, or set the locale explicitly using setLocale:. If you use a method that doesn’t specify a locale, the scanner assumes the default locale values.

  • 扫描程序将其某些扫描行为基于区域设置,该区域设置指定值表示的语言和约定。 NSScanner仅使用区域设置的小数分隔符定义(由名为NSDecimalSeparator的键给出)。 您可以使用localizedScannerWithString:创建具有用户区域设置的扫描程序,或使用setLocale:显式设置区域设置。 如果使用未指定语言环境的方法,则扫描程序将采用默认语言环境值。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容