2009-07-30 56 views
7

假設我有簽名的方法:什麼是正確的方式來包裝[NSString stringWithFormat:]?

+ (NSString *) myFormattedString:(NSString *)format, ...; 

而且我希望它前面加上我的選擇(例如@「富」)的字符串。我想最好的方法是使用[myString initWithFormat:arguments:],但是你將如何實現這個方法?


我試着做以下,但我得到的警告,在註釋規定:

+ (NSString *) myFormattedString:(NSString *)format, ... { 
    char *buffer; 
    [format getCString:buffer maxLength:[format length] encoding:NSASCIIStringEncoding]; 

    va_list args; 
    va_start(args, buffer); // WARNING: second parameter of 'va_start' not last named argument 

    NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; 
    [str autorelease]; 

    return [NSString stringWithFormat:@"Foo: %@.", str]; 
} 

我假設的va_start(原因)可以在一個(字符*)是因爲我在 manual page of STDARG(3)上看到的例子。如果我完全錯了,隨意徹底重寫該方法。

回答

15

我想你想的是一樣的東西:

+ (NSString *) myFormattedString:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 
    NSString *str = [[[NSString alloc] initWithFormat:format arguments:args] autorelease]; 
    va_end(args); 
    return [NSString stringWithFormat:@"Foo: %@.", str]; 
} 

stdarg.hva_ *宏用於當一個函數(或者,在這種情況下,法)採用可變數量的參數,如規定「 ...「。 va_start()用於查找可變數量參數開始的起點。因此,它需要知道函數/方法的最後一個參數(即「...」之前的那個),以確定變量的參數開始位置。這是一個有點簡單的解釋,因爲實際發生的情況非常符合ABI /編譯器特定的要求。最重要的一點是,va_start()的第二個參數始終是「...」之前的變量名稱。

va_end()應該是「調用」(它實際上是一個宏,而不是函數),以實現最大的可移植性。再次,這整個可變的論證事物是深沉的,黑暗的魔法。根據編譯器和ABI的具體情況,va_end()可能根本不會做任何事情。另一方面,如果使用va_end()失敗,則可能會導致程序在達到return語句時崩潰,因爲堆棧幀(如果有的話)不再適當地設置爲實際執行返回。

+0

Woops,我誤解了va_start()的工作原理。我想http://numbergrinder.com/node/35沒有足夠清楚地解釋它。我認爲va_start()的第二個參數是有多少個參數發送給函數的實際計數;並且它有一個'重載',它接受了一個格式字符串,該格式字符串根據格式字符串中有多少未轉義的%確定了計數。哇,這使得它更容易,您不必確定你自己數。感謝您的解釋。 – Senseful 2009-07-30 22:04:23

8

你已經差不多了;只是一些調整:

+ (NSString *) myFormattedString:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 

    NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; 
    [str autorelease]; 

    va_end(args); 

    return [NSString stringWithFormat:@"Foo: %@.", str]; 
} 

這應該做你想要的。

相關問題