scanf("%c",..)和getchar()的区别

4

在我测试之前,我一直认为scanf("%c" , &addr);等同于getchar():

#include<stdio.h>

int main()
{
    int i;
    scanf("%c",&i);
    printf("%d\n", i);
    if(i == EOF)
        printf("EOF int type and char input\n");
    i =getchar();
    printf("%d\n", i);
    if(i == EOF)
        printf("EOF int type and char input\n");
}

我使用“Ctrl + D”两次时得到了以下输出:

-1217114112

-1

EOF int 类型和 char 输入

由于 EOF 在 int 类型中的值是 -1,我尝试使用 scanf("%d",&i) 替换 scanf("%c",&i),但仍然得到相同的输出。
我感到困惑。有人可以为我解释一下吗?
----------------------------------编辑-----------------------------------------------
我想知道 scanf("%c",i) 加上 Ctrl+D 的行为,我进行了测试:
#include<stdio.h>

int main()
{
    int i;
    int j;
    j = scanf("%c",&i);
    printf("%c\n", i);
    printf("%d\n", j);
    if(i == EOF)
        printf("EOF int type and char input");
     i =getchar();
    printf("%d\n", i);
    if(i == EOF)
        printf("EOF int type and char input");
}

输出:

k                  // If the scanf set 1 byte in i , why here print 'k' ?
-1
-1
EOF int type and char input

1
输出结果中的 k 是在尝试将其作为 char 而不是它本来的类型——int 传递给 scanf() 处理之前在 i 中的随机垃圾值。当 scanf() 遇到 EOF(零个字符可读)时,它根本不会对变量进行赋值;它只会返回 EOF。如果 j 不为 1,则关于 i 中的内容没有任何有用的信息; 它的值是不确定的(但可能与函数调用之前相同 —— 但在示例代码中,这是未定义的,因为 i 没有初始化)。 - Jonathan Leffler
2个回答

3

第一个值很可能是未定义行为。除非scanf()返回1,否则您不能依赖于i有一个值。

特别地,在scanf()中,您似乎将被扫描的值(根据第一个参数中的格式说明符进行字符转换)与函数调用的返回值混淆了。

当然,在使用 getchar() 时,这种区别不存在,因为它“仅”有一个返回值。


是的,scanf 返回 -1! - Lidong Guo
当我编辑我的问题时,如果scanf返回“-1”,那么“i”的地址会发生什么事情? - Lidong Guo

3

您的比较没有完全设置i,因为它涉及到未定义行为(UB)。

int i;            // the value of i could be anything
scanf("%c",&i);   // At most, only 1 byte of i is set, the remaining bytes are still unknown.
printf("%d\n", i);// Your are printing 'i' whose value is not fully determined.

你是否尝试过?
char ch;
int y = scanf("%c",&ch);
printf("%d\n", ch);
if(ch == EOF)

即使输入未到达 EOF,您仍有可能匹配成功。如果您扫描了一个值为 255 的 char,则该 char 将采用 2s 补码的 8 位值 -1。比较将对 8 位数 -1 进行符号扩展以匹配 int 大小,从而匹配-1。
(假设:2s 补码整数,8 位字节,EOF == -1,char 是有符号的)。
正确的 EOF 测试是:
int y = scanf("%c",&ch);
if (y == EOF)

注意:函数 getchar()scanf() 返回 EOF 表示文件结束或 I/O 错误。 接下来检查 ferror(stdin) 可以区分这两种情况。

我进行了测试,结果显示 scanf 返回 -1,那么这个 -1 是由 scanf 设置的 1 字节吗? - Lidong Guo
不,1字节没有被设置。只有当scanf("%c",&i)返回1时,i中的一个字节才会被设置。当然,i的其他字节不会改变。 - chux - Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接