【问题标题】:Why is some code from K&R not working in Code:Blocks?为什么 K&R 的某些代码在 Code:Blocks 中不起作用?
【发布时间】:2015-04-20 11:23:34
【问题描述】:

当我准确键入 K&R 中的某些示例时,它们在 Code:Blocks 中不起作用。 比如这个程序:

#include <stdio.h>
main()
{
    long nc;
    nc = 0;
    while (getchar() != EOF)
        ++nc;
    printf("%ld\n", nc);
}

当我输入这段代码并运行它时,当我按下回车键时,程序要么冻结,要么不执行任何操作。

下面的程序做同样的事情(计算字符串中的字符)并且它可以工作。

#include <stdio.h>
int main()
{
    char s[1000];
    int i;
    scanf("%s",s);
    for(i=0; s[i]!='\0'; ++i);
    printf("Length of string: %d",i);
    return 0;
}

我在这里遗漏了什么吗?自 K&R 第 2 版以来 C 是否已更改,还是我做错了什么?

【问题讨论】:

  • 您需要按 CTRL+D (Unix) 或 CTRL+Z (Windows) 才能接收EOF,看看End-of-file
  • 那行得通。谢谢,我怎么也想不到。
  • 除此之外,自 K&R 以来,C 已经发生了很大变化。你不应该读那本书来学习语言,我建议你找一些现代和最新的东西。例如,此代码在 C99/C11 编译器上无法编译,因为 main() 的声明不正确。
  • 你有什么推荐的? C Primer Plus by Stephen Prata好吗?
  • @Lundin 今天 K&R 中的哪些材料不正确?它仍然是我所知道的对 ISO 9899 的最佳描述之一。

标签: c kernighan-and-ritchie


【解决方案1】:

当您按下回车键时,您将\n 发送到标准输入流中(并将其他数据刷新到stdin,如果有的话)。这个字符(\n)与EOF相同。要发送EOF,请按以下组合键:

  • CTRL Z 然后在 Windows 中 Enter
  • CTRL D 在 Unix/Linux/OSX 中

【讨论】:

  • 在 Windows 上,Ctrl-Z 必须后跟 Enter(虽然这只会发送 EOF,而不是 \n)。
  • @AasmundEldhuset,对。 CTRL+D 呢?一键进入Unix?我目前没有 Unix 系统来测试这个。
  • EOF 不是信号。
  • 这是一个条件:不等于任何有效字符代码
  • 在 linux 上,Ctrl-D 仅在缓冲区已经为空时才有效,否则只会刷新它。因此,除非他在没有任何字符的情况下按下回车,否则他将不得不按两次 Ctrl-D。
【解决方案2】:

自从那本书写完以来,C 已经发生了变化,但即使在任何版本的标准下,代码都不是定义明确/有效的 C。

如果您使用当前的 C 标准 (C11) 或以前的 (C99) 进行编译,则严格遵循的编译器(例如 gcc -std=c11 -pedantic-errors)会报错:main must return int。 C99 中删除了旧的“隐式 int”功能。

如果您使用旧的 C90 标准进行编译,代码会调用未定义的行为,因为没有返回语句。这在 C90 中是允许的,但它不安全,它可能导致程序崩溃等。调用未定义的行为始终是一个错误,因此是非常糟糕的做法。

(在 C99 中,返回值的函数必须具有 return 语句,但 main() 除外,其中 return 可以安全地省略。因此,如果编译为 C99,则可以省略 main() 的 return 语句。)

只需像您已经完成的那样更正代码,它将在任何版本的标准中编译,而不会调用未定义的行为。

【讨论】:

  • 你说的都是真的,但没有一个回答问题。
  • @Peter 问题是“我在这里遗漏了什么吗?自 K&R 第 2 版以来 C 是否已更改,还是我做错了什么?”它怎么不回答这个问题? (标题中的问题没有任何意义,因为 Codeblocks 是一个 IDE)这个答案可以很好地解释程序冻结的原因,因为 K&R 代码调用了未定义的行为。尽管 OP 根本不知道如何将 EOF 提供给控制台确实看起来确实更有可能。 Cool Guy 的答案很好,应该很可能被选为正确的答案。我刚刚提到了代码本身的其他问题。
  • @Lundin 我同意。谢谢。
猜你喜欢
  • 2010-09-15
  • 2021-06-30
  • 1970-01-01
  • 2020-10-19
  • 2016-04-18
  • 2021-09-19
  • 1970-01-01
  • 2014-12-19
  • 1970-01-01
相关资源
最近更新 更多