假设我有一个带签名的方法:
+ (NSString *) myFormattedString:(NSString *)format, ...;
我希望它前置我选择的字符串(例如@“Foo:”)。我想最好的方法是使用[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()可以接受(char *)的原因是因为我在manual page of STDARG(3)上看到的例子。如果我完全错误的话,请随意完全重写该方法。
击>
答案 0 :(得分: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.h
va_
*宏,由“...
”指定。 va_start()
用于查找可变数量的参数开始的起点。因此,它需要知道函数/方法的最后一个参数(就在“...
”之前的那个),以便确定变量数量的参数开始的位置。这是一个稍微简化的解释,因为在引擎盖下实际发生的是非常ABI /编译器特定的。最重要的一点是,va_start()
的第二个参数始终是“...
”之前的变量名称。
va_end()
应该被“调用”(它实际上是一个宏,而不是一个函数),以实现最大的可移植性。同样,这整个变量论证的事情是深刻的,深黑魔法。根据编译器和ABI的具体情况,va_end()
可能根本不做任何事情。另一方面,未能使用va_end()
可能会导致程序在达到return
语句时崩溃,因为堆栈帧(如果有的话)不再正确设置为实际执行返回。
答案 1 :(得分: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];
}
那应该做你想要的。