2014-04-25 26 views
0

我想了解sscanf行为,因为我已经执行了两个程序。C sscanf行为

void main() 
{ 
     char *a = "225.311"; 
     int x = 0, y = 0; 
     sscanf(a, "%d.3%d", &x, &y); 
     printf("x is %d, y is %d\n", x, y); 
} 

输出

x is 255, y is 11 

下面程序工作不按我的期望。

void main() 
{ 
     char *a = "225.311"; 
     int x = 0, y = 0; 
     sscanf(a, "%d5.3%d", &x, &y); 
     printf("x is %d, y is %d\n", x, y); 
} 

我期待25,11,但输出

x is 255, y is 0 

我期待sscanf行为应该完全一样在相反的方式sprintf的。但它没有在我的第二个程序中工作。如果格式指定为%d5.3%d,则必须将5视为分隔符。但它不考虑和读取x的所有数字,然后点与5.3%d不匹配,因此它在那里退出。

有人可以解释一下。

+1

总是检查'[s] scanf'的返回值。如果它不等于你使用的占位符的数量,那么你会意识到发生了一些错误。 – Crozin

+0

阅读'scanf'的文档或手册页,不要假设...这个文本解析函数族具有很大的权力,但我会说权力比责任更重要,更不用说默认值了从用户的角度来看可能是不直观的。用标准的C'fgets'或者GNU/POSIX2008'getline'读一行,然后用'sscanf'解析通常会更好。 – hyde

回答

4

这是因为%d转换说明符意味着sscanf将继续读取由a指向的缓冲区,直到它在缓冲区中遇到一个非数字字符。这意味着%d将在第二个示例中的字符串文字"225.311"中消耗至225

如果指定的格式是%d5.3%d,那么它必须考虑5为 分度。

不,这是不正确的。格式字符串中的5表示sscanf将在它读取的缓冲区中完全匹配(在读取int后)。如果它不匹配,则sscanf将返回并且值y保持不变。您可以通过存储sscanf的结果来检查。返回值等于成功匹配和分配的输入项目的数量。

char *a = "225.311"; 
int x = 0, y = 0; 
int retval = sscanf(a, "%d5.3%d", &x, &y); 
printf("%d\n", retval); // prints 1 

但是,请注意,如果数字字符在缓冲区中的顺序是太长为int,则行为是因为有符号整数溢出的不确定。

1

建议使用不同的格式并检查sscanf()的结果。还要区分“0.001”和“0.1”等分数,请注意位置。

const char *a = "225.0311"; 
int ipart = 0; 
unsigned fractionpart; 
int n1, n2; 
if (sscanf(a, "%d.%n%u%n", &ipart, &n1, &fractionpart, &n2) != 2) { 
    Handle_BadInput(); 
} 

printf("ipart is %d, fractionpart is %0*u\n", ipart, n2 - n1, fractionpart); 
// ipart is 225, fractionpart is 0311 

由于@ajay讨论,"%d5.3%d"寻找一个int,然后"5.3"然后又int