C、K&R练习1-6,卡住,困惑

C, K&R Exercise 1-6, stuck, confused

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

    c = getchar() != EOF

相当于

    c = (getchar() != EOF)

哪个"has the undesired effect of setting c to 0 or 1, depending on whether or not the call of getchar encountered end of file"

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

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

#include <stdio.h>

main()
{
    int c;

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

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

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

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

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

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

putchar('0');
        ^ ^

断言

c = getchar() != EOF;

等同于

c = (getchar() != EOF);

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

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

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

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

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

你还说 c=0c=1 它应该打印 01。然后试试这个简单的代码

int c= 68;
putchar(c);

检查输出,您就会知道当我们尝试打印时会发生什么。打印的是ascii码为68的字符,而不是68.

的值

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

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