我尝试了以下代码(在 Ubuntu 22.04 上使用 GCC 13 编译)
int x;
int ret = scanf("%d", &x);
char ch;
scanf("%c", &ch);
printf("%c, %d\n", ch, ret);
输入
-*
它打印了
*, 0
,这表明第一次输入x
失败了(返回值为0
),但是第一个减号被消耗了。当我将减号更改为 +
时也会发生这种情况,但对于其他字符则不会。
该符号是否被视为整数的开头?如果是这样,为什么这个输入被视为失败?如果不是,为什么会被消耗?或者这是完全未定义的行为?
另外,当输入为
double
时,.
也会发生同样的情况。
该符号是否被视为整数的开头?如果是这样,为什么这个输入被视为失败?如果不是,为什么会被消耗?或者这是完全未定义的行为?
以下内容适用于
fscanf()
:
从流中读取输入项,...。输入项被定义为不超过任何指定字段宽度的最长输入字符序列,并且是匹配输入序列或其前缀。348 输入项之后的第一个字符(如果有)保持未读状态。 如果输入项的长度为零,则指令执行失败;这种情况是匹配失败....
C23dr § 7.23.6.2 9
348
最多将一个输入字符推回输入流。因此,一些序列可以被接受fscanf
、strtod
等,strtol
无法接受。fscanf
当我读到这篇文章时,随着OP输入
"-*"
,直到读取到'*'
,scanf()
才意识到输入匹配失败,并将'*'
放回输入stdin
。 一些系统也会成功放回'-'
(请注意,脚注本身不是规范。),但OP的系统没有。
故事的寓意:如果输入错误,
(f)scanf()
很难使用。对于 line 输入,请使用 fgets()
读取该行,然后解析它。
请注意,较长的输入序列(例如
"-.*"
)会导致麻烦。