【问题标题】:C Programming Exercise from the K&R BookK&R 书中的 C 编程练习
【发布时间】:2008-12-05 01:20:35
【问题描述】:

知道为什么下面的代码不打印输入中的字符数量吗? 我直接从 K&R 书中得到了这个。目前正在学习 C,这真的很令人困惑,在我看来,我永远不会达到 EOF。如果是这样,那为什么要拿这个来做例子呢?

#include <stdio.h>

main()
{
    double nc;

    for (nc = 0; getchar() != EOF; ++nc)
        ;
    printf("%d\n", nc);
}

【问题讨论】:

    标签: c kernighan-and-ritchie


    【解决方案1】:

    程序看起来正确,您的问题是您必须在输入后将EOF(文件结尾)发送到命令行,因为标准输入被视为文件。我认为在 linux 终端中您可以按 Ctrl+D 发送EOF...我不确定如何在其他操作系统中执行此操作。要测试此程序,您可能需要将 EOF 更改为 '\n',这将导致它在您按 Enter 时停止。

    【讨论】:

    • FWIW,我没有对你投反对票。但是,没有 EOF 字符这样的东西,所以这可能就是原因。当用户在终端上按下 ^D(或其他)时,它会在进程的 stdin 上导致 EOF 条件(它被 shell 关闭),不涉及任何字符。
    • 哦,我一直认为 EOF 是控制字符之一...感谢您提供的信息。
    • 实际上现在我意识到 EOF 字符没有意义,因为二进制文件通常包含字符代码。
    • CTRL-D 实际上是 EOT(传输结束)字符,从终端发送时会导致 EOF 条件。
    • ctrl Z 是一些早期复古机器中的 eof 字符。
    【解决方案2】:

    程序一直从stdin 读取数据,直到收到EOF,这是通过在 Unix 控制台上的行首按 Ctrl-D 或在 Windows 的行首按 Ctrl-Z 来完成的安慰。以这种方式发送EOF 信号后,将执行printf 函数,显示读取的字符数。

    【讨论】:

      【解决方案3】:

      您的 nc 是双精度 - 使用 printf("%lf", nc) 打印双精度。

      试试这个

      #include <stdio.h>
      
      int main(void)
      {
          int nc;
      
          for (nc = 0; getchar() != EOF; ++nc)
              ;
          printf("%d\n", nc);
      
          return 0;
      }
      

      【讨论】:

      • 虽然略有错误,但 %f 用于双打。由于对可变参数函数的提升,它也可以用于浮点数。
      • 谢谢,但我会坚持使用 %lf,就像这本好书说的那样 #include int main(void) { long float x = 3.14159265358979;浮动 y = 3.14159265358979f; printf("%15.10f\n", y); /* 3.1415927410 / printf("%15.10lf\n", x); / 3.1415926536 */ 返回 0; }
      • 如果你愿意,你可以坚持使用 %lf,但它仍然是错误的。 %f 用于双打。顺便说一句,ISO/IEC 9899:1999(俗称 C99,许多实现不支持)将 %lf 视为 %f,但在 ISO/IEC 9899:1990(俗称 ANSI C 或 C89 或 C90)中,%lf 是未定义的行为。
      • 另外,您的评论示例是错误的,没有长浮点数之类的东西。您对浮点数和双精度数都使用 %f,因为浮点数在传递给变量参数函数时会提升为双精度数。
      • @EvilTeach,请不要提倡使用 %lf,这在 C99 中是合法的,以与 scanf 协调,但在以前的版本中是不合法的。由于不可能将浮点数传递给 printf(或任何可变参数函数),因此 %f 用于表示双精度数(无论是否从浮点数提升)。
      【解决方案4】:

      我想澄清到目前为止给出的答案,因为它们似乎使用“发送 EOF”、“收到 EOF”、“EOF 字符”等短语。根据 cmets(感谢)这个答案,“发送EOF”和“received EOF”是合法的术语,但请不要认为它是一个字符。

      EOF 根本不是一个字符。如果流位于“文件末尾”或发生读取错误,则它是 getchar()(或 fgetc/getc)返回的值。它只是 getchar() 将返回的字符值范围之外的特殊值,指示错误或文件结束的条件

      C 标准将其定义为负数,而 getchar 将字符作为转换为 int 的无符号字符返回。

      编辑:在做一些我应该在我写的段落之前做的研究时,我意识到我的一些假设是完全错误的。感谢评论者指出这一点。

      一旦流(例如标准输入)处于文件结束状态,可以使用 clearerr() 再次清除这种情况,并且 getchar() 可以从标准输入读取更多数据。

      【讨论】:

      • 哇,这里有很多需要纠正的地方:1)没有人称 EOF 为字符,2)“发送/接收 EOF”是完全合法的短语,3)控制终端不会关闭你的文件, 4) getchar返回EOF时stdin没有关闭,收到EOF后可以继续从stdin读取...
      • 1) 实际上 Jeremy Ruten 做到了,我纠正了他,他编辑了他的答案;查看修订历史。 2) 好的 3) 我应该说 shell 4) 当然,你可以继续从标准输入读取,但你只会继续得到 EOF。如果您不同意,请提供说明。
      • 抱歉,根据我自己的研究,您似乎也是对的 4。谢谢。
      • 1) 好的,我没看到这个,我承认这一点。 3)这仍然是错误的,shell不会关闭你的文件,这在子进程启动后甚至是不可能的。 4) stdin 没有关闭,如果你无法读取它,如果添加更多数据,你可以在 EOF 之后读取更多数据。
      • 这是#4 的示例程序: #include int main (void) { while (getchar() != EOF); puts("第一个 EOF");而(getchar()!= EOF); puts("第二个 EOF");返回0; }
      【解决方案5】:

      此代码从标准输入读取字符。当你正常运行这个程序时,标准输入来自用户。在这种情况下,没有办法向程序发送 EOF。

      如果您将文件重定向到 (./myprogram

      【讨论】:

      • 当没有办法(以当前的预期形式)访问 printf 函数时,为什么它被用作当前形式的示例?
      • 您确定他们不希望您使用重定向吗?此外,如果您完全按照示例显示的方式键入它,那么这本书看起来很老了,也许它曾经可以工作,或者可以在特定平台上工作(可能不再存在,比如 DOS)。
      • 尤其是 main() 的定义,它没有给出返回类型,而 for 循环使用 double 让我质疑这本书的年代和实用性。
      • K&R “The C Programming Language”是第一本教 C 的书。它很老了。
      • 第二版来自 1988 年,仍然被认为是最好的 C 书籍之一,只是遗漏了 C99 标准中的一些内容。
      【解决方案6】:

      首先,如前所述,您需要 %lf 而不是 %d 来显示双精度数,否则它将一直显示为零(d 是有符号整数)。然后,如果您想在基于 Windows 的操作系统上手动测试,输入某些字符,请按 Enter,然后在下一行单独按 CtrlZ(这将模拟 EOF)。打印结果将比字符数多一(包括 CtrlZ)。同样,正如 SoapBox 在寻找 EOF 时所指出的那样,当时的想法通常是 Unix,您可以通过标准输入将文件通过管道传输到程序中,这也可以。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-25
        • 2020-06-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多