C: scanf("%d", ...) 仅输入一个减号

问题描述 投票:0回答:1

我尝试了以下代码(在 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
时,
.
也会发生同样的情况。

c scanf
1个回答
0
投票

该符号是否被视为整数的开头?如果是这样,为什么这个输入被视为失败?如果不是,为什么会被消耗?或者这是完全未定义的行为?

以下内容适用于

fscanf()

从流中读取输入项,...。输入项被定义为不超过任何指定字段宽度的最长输入字符序列,并且是匹配输入序列或其前缀。348 输入项之后的第一个字符(如果有)保持未读状态。 如果输入项的长度为零,则指令执行失败;这种情况是匹配失败....
C23dr § 7.23.6.2 9

348

fscanf
最多将一个输入字符推回输入流。因此,一些序列可以被接受
strtod
strtol
等,
fscanf
无法接受。

当我读到这篇文章时,随着OP输入

"-*"
,直到读取到
'*'
scanf()
才意识到输入匹配失败,并将
'*'
放回输入
stdin
一些系统也会成功放回
'-'
(请注意,脚注本身不是规范。),但OP的系统没有。

故事的寓意:如果输入错误,

(f)scanf()
很难使用。对于 line 输入,请使用
fgets()
读取该行,然后解析它。


请注意,较长的输入序列(例如

"-.*"
)会导致麻烦。

© www.soinside.com 2019 - 2024. All rights reserved.