为什么当我运行这段代码时:
#include <stdio.h>
int main () {
int a, b;
if (scanf("%d %d", &a, &b) == 2)
printf("%d %d", a, b);
else
printf("Something went wrong");
return 0;
}
并输入例如:
1 1.5
输出为:
1 1
为什么 scanf 会读取“.”之前的两个数字并忽略“.5”?如何检查最后一个数字不是浮点数并且字符串结束?
操作系统:MacOS/linux 编译器:gcc
我只想运行上面的代码
输入:
1 1.5234
(一些浮点数)
输出:
Something went wrong
fgets:读取整行输入,确保捕获用户输入的所有内容,直到他们按 Enter。这避免了 scanf 在第一个不匹配字符处停止的限制。
sscanf:解析input中存储的输入。它尝试读取两个整数 (%d %d)。之后,它尝试再读取一个字符 (%c),该字符应该是空格(如空格或换行符)。
验证:
if (sscanf(input, "%d %d %c", &a, &b, &leftover) == 2)
isspace(leftover)
:检查第二个整数后面的字符是否为空格(确保没有小数点等其他字符)。
输出:如果输入格式匹配(scanf 成功读取两个整数后跟空格),则打印整数。否则,它会打印一条错误消息。
简短的回答是,你无法真正弄清楚 scanf 发生了什么。它的手册页毫无帮助地指出:
正确使用这些函数非常困难,最好使用 fgets(3) 或 getline(3) 读取整行,然后使用 sscanf(3) 或更专业的函数(例如 strtol(3))解析它们。
scanf(和fscanf)很容易与输入不同步。我使用 fgets 和 sscanf。有了这些,我可以大大改进您的输入验证,如下所示:
#include <stdio.h>
#include <stdlib.h>
int main () {
char iline[80];
int a, b;
char extra[2];
int result;
if (fgets(iline, sizeof(iline), stdin) == NULL) {
printf("Need an input line.\n"); exit(1);
}
result = sscanf(iline, "%d %d%1s", &a, &b, extra);
if (result == 2) {
printf("%d %d\n", a, b); // Success!
} else if (result == 3) {
printf("Extra stuff starting at '%s'\n", extra);
} else if (result < 2) {
printf("Could not find two integers\n");
}
return 0;
}
以下是一些测试运行:
$ gcc x.c
$ echo "1" | ./a.out
Could not find two integers
$ echo "1 2" | ./a.out
1 2
$ echo "1 2.5" | ./a.out
Extra stuff starting at '.'
$ echo "1.5 2" | ./a.out
Could not find two integers
$ echo "1 2 5" | ./a.out
Extra stuff starting at '5'
通过与扫描分开读取该行,您可以添加“额外”字符串来测试扫描是否在该行被消耗之前提前结束。如果我在上面的代码中使用 scanf,它将拒绝返回,直到它真正找到需要扫描的额外内容。