【问题标题】:C, K&R Exercise 1-6, stuck, confused [duplicate]C,K&R 练习 1-6,卡住,困惑 [重复]
【发布时间】:2018-05-09 15:40:06
【问题描述】:

我是一个自学用 C 编程的菜鸟,使用 C 编程语言,第二版(作者 K&R)。在第 1 章的 1.5.1 文件复制节中,作者非常简要地谈到了比较值时的操作优先级,强调了在这种情况下使用括号的重要性,以确保对在评估比较之前的变量“c”。他们断言:

    c = getchar() != EOF

等价于

    c = (getchar() != EOF)

哪个“具有将c设置为0或1的不良影响,具体取决于getchar的调用是否遇到文件结尾”

然后作者提出练习 1-6 - 验证表达式 getchar () != EOF 是 0 还是 1

根据作者之前的断言,这似乎是微不足道的,所以我创建了以下代码:

#include <stdio.h>

main()
{
    int c;

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

不幸的是,当我运行程序时,如果遇到 EOF,它只会输出我在命令窗口中键入的任何字符,而不是预期的字符串 1 或 0。

虽然我是个菜鸟,但我想我明白作者试图教授的逻辑,但我无法演示这个简单的任务。在这种情况下,变量 c 是否应该采用比较表达式计算的值,而不是 getchar() 碰巧获取的任何字符,特别是因为括号的位置?如果c 确实具有比较值,putchar() 应该只输出 0 或 1,但按照公式,它会输出我在命令窗口中键入的内容。我究竟做错了什么?我不明白什么?会不会是我的编译器?我在 x64 架构的 Windows 10 上的 Visual Studio 2017 社区版中进行编码。我有 Tiny C 编译器,但尚未尝试使用 TCC 从命令提示符执行。

【问题讨论】:

  • 整数值01 在任何编码中都不是真正可打印的字符。使用例如printf("%d\n", i) 代替。
  • 也许 OP 看到了 OP 给出的任何输入......是的,这些都不是什么可怕的
  • 可能是((c = getchar()) != EOF)??
  • 伙计们。我对你的评论速度感到惊讶。
  • 不,这不是你的编译器。确保您正在使用 VS 开发人员控制台并在命令行中使用cl (cl.exe) 以及最小选项cl /nologo /Wall /Ox /Feyourexe /Tc yoursource.c(您可以添加/Fo,例如/Foobjfile 来命名目标文件)拥有objbin 子目录有助于保持您的源文件目录干净,并使用/Foobj/thename /Febin/thename /Tc thename.c 将目标文件放在obj 子目录中,将可执行文件放在bin 子目录中。祝你好运。 (使用/wd#### 禁止个别警告)

标签: c getchar putchar


【解决方案1】:

当您运行程序时,您看到的字符并非来自您的程序。它是控制台(或终端)的echo 函数,它显示您输入的任何字符(您甚至可以在按 Enter 之前擦除它们)。您的程序只输出 ASCII 码 0 或 1 的字符,这两个字符都是不可见的。

如果您将putchar(c) 更改为printf("%d", c),您将能够看到1s 的序列。不会出现零,因为当c 变为零时,循环停止并且不会被打印。

字符 '0''1' 的 ASCII 码分别为 48 和 49,尽管您的终端可能使用其他编码。如果要输出文字数字 0,请使用字符表示法。您也可以尝试putchar(48),但不要使用太多(稍后您会发现it's highly discouraged 在您的程序中使用magic numbers)。

putchar('0');
        ^ ^

断言

c = getchar() != EOF;

等价于

c = (getchar() != EOF);

是因为operator precedence。运算符!=(不等式)比=(赋值)具有更高的优先级,因此在赋值之前对其进行评估。

最后,非常很少有人写出这样的东西。正确的意图是这样写:

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

【讨论】:

  • 很好的解释,又学到了一些以前不知道的回声功能,谢谢!
  • @H3G3moKnight 我为 echo 添加了一个链接。
  • 我不同意Despite not being always, character...。 ASCII 始终是 ASCII,即使操作系统/终端使用不同的代码页,ASCII 的前 7 位也会给出相同的值。然而,编码确实可以不同。
  • @MatanShahar 重新措辞。
【解决方案2】:

事情是c = (getchar() != EOF) 它会得到一个输入字符然后比较。如果不是 EOF,结果将为 1。然后被分配。赋值语句的值是被赋值的值。它进入循环。打印具有 ascii 值 1 的字符。但是那个字符是不可打印的,所以你什么都看不到。

一旦它得到EOF,它将脱离循环。因此,除了 ascii 值为1 的字符之外,您永远看不到任何其他内容。(即使您也看不到它,因为它是不可打印的)。这些被称为ascii-control 字符。 (不属于可打印类)。

您还说c=0c=1 它应该打印01。那就试试这个简单的代码

int c= 68;
putchar(c);

检查输出,您将了解当我们尝试打印时会发生什么。打印的是ascii码为68的字符,而不是值68

正确的做法是((c = getchar()) != EOF)

最初我提到在某些机器上它会打印一些有趣的字符。不可打印字符的表示取决于使用的字符集。可能是一些非标准编码(非 unicode)分配给 ascii 代码 1 一些表示。(打破了不可打印的想法)

【讨论】:

  • ?????...??
  • 是的,我刚刚查看了 ASCII 字符表,可以看到“值 0 到 31 和 127,代表不可打印的控制字符。”这可以解释很多。
  • 至少你能看到 ASCII 10 (\n),对吧?
  • @iBug.: 是的....
猜你喜欢
  • 2020-06-25
  • 2013-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多