我正在尝试理解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
不匹配,因此它会退出。
有人可以解释一下。
答案 0 :(得分:4)
这是因为%d
转换说明符意味着sscanf
将继续从a
指向的缓冲区读取,直到它遇到缓冲区中的非数字字符。这意味着在您的第二个示例中,%d
将耗尽字符串文字225
中的"225.311"
。
如果指定的格式为
%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 :(得分: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
。