天天看點

NSScanner用法詳解

NSScanner類用于在字元串中掃描指定的字元,尤其是把它們翻譯/轉換為數字和别的字元串。可以在建立NSScaner時指定它的string屬性,然後scanner會按照你的要求從頭到尾地掃描這個字元串的每個字元。

建立一個Scanner

NSScanner是一個類族, NSScanner是其中公開的一類。通常,可以用scannerWithString:或localizedScannerWithString:方法初始化一個scanner。這兩個方法都傳回一個scanner對象并用你傳遞的字元串參數初始化其string屬性。剛建立時scanner對象指向字元串的開頭。scan...方法開始掃描,比如scanInt:,scanDouble:,scanString:intoString:。如果你要想掃描多遍,通常需要使用while循環,例如如下代碼所示:

float aFloat;

NSScanner *theScanner = [NSScanner scannerWithString:aString];

while ([theScanner isAtEnd] == NO) {

[theScanner scanFloat:&aFloat];

// implementation continues...

}

可以通過setCaseSensitive:方法設定是否忽略大小寫,預設是忽略。

Scanner的使用

掃描操作從上次掃描的位置開始,并且繼續往後掃描直到指定的内容出現為止(如果有的話)。以字元串“137 small cases of bananas”為例,在掃描完一個證書之後,scanner的位置将變為3,也即數字後面的空格處。通常,你會繼續掃描并跳過你不關心的字元。那麼你可以用setScanLocation:方法跳過某幾個字元(也可以用這個方法在發生某些錯誤後,重新開始掃描字元串的某部分)。如果你想跳過某種特殊的字元集中的字元時,可以使用setCharactersToBeSkipped:方法。scanner在任何掃描操作時會跳過空白字元之後才開始。但是當它找到一個可以掃描的字元時,它會用全部字元去和指定内容比對。scanner預設情況下會忽略空白字元和換行符。注意,對于忽略字元,總是大小寫敏感的。例如要忽略所有原音字母,你必須使用“AEIOUaeiou”,而不能僅僅是“AEIOU”或“aeiou”。

如果你想擷取目前位置的某個字元串的内容,可以使用scanUpToString:intoString:方法(如果你不想保留這些字元,可以傳遞一個NULL給第2個參數)。例如,以下列字元串為例:

137 small cases of bananas

下面的代碼,可以從字元串中找出包裝規格(small cases)和包裝數量(137)。

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”關系重大。預設scanner會忽略空白字元,是以在數字137後面的空格被忽略。但是當scanner從空格後面的字元開始時,所有的字元都被加到了輸出字元串中,一直到遇到搜尋字元串(“of”)。

如果搜尋字元串是“of”(前面沒空格),container的第一個值應該是“smallcases ”(後面有個空格);如果搜尋字元串是“ of”(前面有空格),則container的第1個值是“small cases”(後面無空格)。

在掃描到指定字元串(搜尋字元串)之後,scanner的位置指向了該字元串開始處。如果你想繼續掃描該字元串之後的字元,必須先掃描指定字元串(搜尋字元串)。下列代碼示範了如何跳過搜尋字串并取得産品類型。注意我們使用了substringFromIndex:,等同于繼續掃描直到整個字元串的末尾。

[aScanner scanString:separatorString intoString:NULL];

NSString *product;

product = [[aScanner string] substringFromIndex:[aScanner scanLocation]];

// could also use:

// product = [bananas substringFromIndex:[aScanner scanLocation]];

示例

假設你有如下字元串:

Product: Acme Potato Peeler; Cost: 0.98 73

Product: Chef Pierre Pasta Fork; Cost: 0.75 19

Product: Chef Pierre Colander; Cost: 1.27 2

以下代碼示範了讀取産品名稱和價格的操作(價格簡單地讀作一個float),跳過“Product:”和“Cost:"子串,以及分号。注意,因為scanner預設忽略空白字元和換行符,循環中沒有指定對它們的處理(尤其對于讀取末尾的整數而言,并不需要處理額外的空白字元)。

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);

}

}

本地化

Scanner支援本地化的掃描,可以指定語言和方言。NSScanner隻在小數點分隔符上使用locale屬性(以NSDecimalSeparator為key)。你可以用lcoalizedScannerWithString:建立指定locale的scanner,或者用setLocale:方法顯示地指定scanner的locale屬性。如果你不指定locale,scanner假定使用預設的locale。

//通過NSScanner讀取text文檔

NSString *tmp;

NSArray *lines; /*将檔案轉化為一行一行的*/

lines = [[NSString stringWithContentsOfFile:@"testFileReadLines.txt"]

componentsSeparatedByString:@”\n”];

NSEnumerator *nse = [lines objectEnumerator];//建立一個枚舉器

// 讀取<>裡的内容

while(tmp = [nse nextObject]) {

NSString *stringBetweenBrackets = nil;

NSScanner *scanner = [NSScanner scannerWithString:tmp];

[scanner scanUpToString:@"<" intoString:nil];

[scanner scanString:@"<" intoString:nil];

[scanner scanUpToString:@">" intoString:&stringBetweenBrackets];

NSLog([stringBetweenBrackets description]);

}

NSScanner用法詳解