【问题标题】:putchar and printf not behaving as expectedputchar 和 printf 的行为不符合预期
【发布时间】:2017-07-03 21:39:57
【问题描述】:

我正在完成 K&R 中的一些练习。练习 1-6 要求验证表达式 getchar() != EOF 是 0 还是 1。我理解它的原因,但我编写的代码证明它没有按预期工作。我写了以下两个sn-ps:

版本 1:

int main(void)
{
    int c;

    while (c = getchar() != EOF)
    {
        putchar(c);
    }

    printf("%d at EOF\n", c);

    return 0;
}

版本 2:

int main(void)
{
    int c;

    while (c = getchar() != EOF)
    {
         printf("%d\n", c);
    }

    printf("%d at EOF\n", c);

    return 0;
}

我的问题:

  1. 当我输入一个字符并使用版本一按 Enter 时,为什么我在屏幕上看不到 0 或 1?相反,我的光标移动到下一行的第一个位置,否则为空。我虽然putchar 会将c 发送到stdout

  2. 1234563 )。为什么?

非常感谢您的想法。如果有您认为有帮助的参考资料,请发送链接。

澄清:

我知道我正在为 c 分配 0 或 1 的值。这就是我想要做的,也是练习想要的。这也是我在c = getchar() 周围没有括号的原因。我的问题更多地涉及理解为什么输出不是我所期望的。如有任何混淆,请见谅。

【问题讨论】:

  • 你应该启用警告-Wall -Wextra
  • 我其实是用gcc编译了代码。我正在使用课程(CS50)提供的IDE,当我尝试使用make和clang进行编译时,我做不到。这些警告不会阻止我的代码编译吗?
  • "每个非 EOF 字符 1" --> 所有字符都是非 EOF。 End-of_file 是一个条件,而不是一个字符。
  • 在编译中添加警告选项的全部目的是防止错误代码编译。编译器比你更了解 C。编译器仅在您告诉它,或者当它确信您编写的内容不是您要编写的内容时才会产生警告。我不运行不能使用 gcc -Wall -Wextra -Werror -O3 -g -Wstrict-prototypes -Wold-style-declarations -Wold-style-definitions -Wmissing-prototypes 编译的代码(或者本地 GCC 支持的尽可能多的代码)。我的时间比寻找编译器可以为我发现的错误更好。

标签: c printf putchar


【解决方案1】:

赋值运算符=的优先级低于不等运算符!=

所以这个:

while (c = getchar() != EOF)

被解析为:

while (c = (getchar() != EOF))

因此,如果getchar 不是EOF,则为c 分配布尔值1,如果返回EOF,则为0。

因此,第一个程序打印 ASCII 码 1 的字符,这是一个不可打印的字符。这就是为什么你什么都看不到。第二个程序使用 %d 格式说明符到 printf,将数字 1 转换为其字符串表示形式。

您需要括号将getchar 的结果分配给c

while ((c = getchar()) != EOF)

编辑:

为了进一步阐明您得到的输出,在这两个程序中,变量 c 在每个 while 循环内的值都为 1。这里的区别在于putchar 打印的是ASCII 值为1 的字符(不可打印的字符),而printf%d 打印的是值1 的文本表示,即1

如果您将 printf 调用更改为:

printf("%c", c);

您将获得与使用 putchar 相同的输出。

至于每个字符打印两次 1,那是因为您实际上输入了两个字符:您按下的键,加上回车键。从控制台读取时,getchar 函数在按下回车键之前不会返回。

【讨论】:

  • 您没有回答问题的一部分“它为每个非 EOF 字符重复 1,为什么?” (我猜这是因为 OP 忘记了他按 Enter 键)
  • @dbush,您能否解释一下为什么我输入的每个非 EOF 字符都会出现两次值 1?
  • @BruceM 查看我的编辑。额外的打印用于输入键的换行符。
猜你喜欢
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 2017-01-27
  • 2022-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多