当我终于意识到问题是从多个线程调用sscanf时,我只是花了整整一天调试一个随机错误。
我通过运行以下代码确认,它在Snow Leopard上按预期工作,但在我的iphone上使用os 3.1.2会产生非常奇怪的结果。它在模拟器中也可以正常工作。
在iPhone上,解析后的数字将是字符串中使用的数字的随机组合。
如果有人能够检查这是一般问题还是我的错误,那将会非常有帮助。
- (void)testIt
{
[NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
[NSThread detachNewThreadSelector:@selector(scanfTest) toTarget:self withObject:nil];
}
- (void)scanfTest
{
while (true)
{
float value = 0.0f;
sscanf("456", "%f", &value);
sscanf( "1.63", "%f", &value);
if (value != 1.63f)
NSLog(@"strange value is %f", value);
}
}
我做了一些进一步的检查,看起来只有浮点数是一个问题 此代码有效
- (void)scanfTest4
{
while (true)
{
int year = 0;
int month = 0;
int day = 0;
sscanf("20090131", "%4d%2d%2d", &year, &month, &day);
sscanf("19840715", "%4d%2d%2d", &year, &month, &day);
if (year != 1984 || month != 7 || day != 15)
NSLog(@"bla");
}
}
此代码失败并出现相同的随机数字问题
- (void)scanfTest4
{
while (true)
{
int year = 0;
int month = 0;
float day = 0.0f;
sscanf("20090131", "%4d%2d%2f", &year, &month, &day);
sscanf("19840715", "%4d%2d%2f", &year, &month, &day);
if (year != 1984 || month != 7 || day != 15.0f)
NSLog(@"bla");
}
}
答案 0 :(得分:2)
SUSv2说(Threads):
由此定义的所有接口 规范将是线程安全的, 除了以下接口 不必是线程安全的
sscanf()
不在不需要线程安全的接口列表中。
这并不是说iPhone符合SUSv2标准,但我认为至少它解释了为什么你的代码应该适用于Snow Leopard。此外,我手边没有更新的POSIX规范,所以假设自1997年以来没有改变,我冒了一点风险。
答案 1 :(得分:0)
sscanf不是线程安全的PERIOD。它是在线程存在之前编写的,其设计要求它使用内部静态临时变量。 sprintf也是如此。
我是你的情况,无论如何,sscanf都是矫枉过正的。只需使用atof
。
答案 2 :(得分:0)
谢谢John和Stephen!
我可以确认atof和strtof在这种情况下都可以安全使用。
答案 3 :(得分:0)
如果我可能会问,为什么在使用NSString数字转换时需要使用sscanf / atof?