C编程语言书的例子:可能已经过时了?

时间:2012-08-08 03:11:41

标签: c

我开始学习C,我的一个朋友(比我大)建议{strong> Brian Kernighan 和 Dennis Ritchie 提出The C Programming Language

然而,在尝试一些例子时,他们的行为与预期不同,而不是书中所写。

例如,这个,似乎不起作用(什么都不打印):

#include <stdio.h>

#define IN 1
#define OUT 0

/* count lines, words, and characters in input */

int main()
{
   int c, nl, nw, nc, state;
   state = OUT;
   nl = nw = nc = 0;

   while ((c = getchar()) != EOF) {
      ++nc;
      if (c == '\n')
         ++nl;
      if (c == ' ' || c == '\n' || c == '\t')
         state = OUT;
      else if (state == OUT) {
         state = IN;
         ++nw;
      }
   }
   printf("%d %d %d\n", nl, nw, nc);
   return 0;
}

你认为我应该继续读这本书,也许只有一些错误,值得一读吗?或者有一本更好的C语言初学者书。

编辑:我的假设是使用ENTER键发送输入,将模拟EOF,而不是。 CTRL+Z确实如此。

感谢您的帮助。

7 个答案:

答案 0 :(得分:9)

它对我有用。

$ gcc c.c -o c
$ echo hello world | ./c
1 2 12
$ 

程序从标准输入读取文本,直到它到达文件结尾。我怀疑你从键盘上读取时没有正确发出文件结束状态的信号。在Linux和其他类Unix系统上,单独在一行上键入 Ctrl-D 。在Windows上,键入 Ctrl-Z

如果从IDE启动程序,它可能会在新启动的终端窗口中运行程序,该窗口在程序完成时关闭;在这种情况下,窗口可能会在您看到输出之前消失。如果您的IDE没有提供覆盖此错误行为的方法,您可以直接从运行shell的终端窗口运行它,也可以添加如下行:

getchar();

到程序结束时,return 0;之前。这使它在终止之前读取(并忽略)输入字符;您可以在看到输出后键入 Enter 。请注意,当您从shell执行程序时,这种事情可能会使您的程序运行起来更加笨拙,所以只在必要时才这样做。

Kernighan和Ritchie的“C编程语言”,通常被称为K&amp; R,是一本优秀的C书;毕竟,Ritchie在很大程度上发明了这种语言,尽管它确实倾向于假设一些现有的编程知识。确保你有第二版;第一个描述了该语言的早期版本。 (自K&amp; R2发布以来,已经有两个新的ISO C标准,但它们没有添加任何对介绍性测试至关重要的标准。)

有关其他C在线教程和书籍的列表,请参阅comp.lang.c FAQ的问题18.9和18.10。

答案 1 :(得分:4)

由于怀旧并且由丹尼斯·里奇(Dennis Ritchie)撰写,K&amp; R收到了很多“潮流炒作”。毫无疑问,它是有史以来最着名的编程书籍。然而,在我看来,这对初学者来说不是一本好书。

主要原因是这本书是在良好的编程风格被发明之前编写的。大多数示例都是用大多数现代C程序员发现的相当混乱的编码风格编写的。什么是好的和坏的编码风格肯定是一个主观的话题。但举个例子吧。它可以改写为:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

/* count lines, words, and characters in input */

int main (void)
{
   int  ch;
   int  linefeeds_n = 0;
   int  words_n     = 0;
   int  chars_n     = 0;
   bool new_word    = true;


   while ((ch = getchar()) != EOF) 
   {
     if (ch == '\n')
     {
       new_word = true;       
       linefeeds_n++;
     }
     else if (ch == ' ' || ch == '\t')
     {
       new_word = true;
     }
     else if (new_word)
     {
       new_word = false;
       words_n++;
     }

     chars_n++;
   }

   printf("%d %d %d\n", 
          linefeeds_n, 
          words_n, 
          chars_n);

   return EXIT_SUCCESS;
}

我发现上述风格更具可读性和正确性。变化是:

  • Sane变量名称。
  • 可读变量声明列表。
  • 没有神秘的状态变量。改为使用bool类型。
  • 始终对每个语句使用{}以防止出现许多经典错误。
  • 不对'\ n'进行多重检查(更快的代码)。
  • while循环结束时的计数器增量(通用编码样式)。
  • 根据C99正确结束main()的方法。
  • 关于main()的Nitpick,声明为void而不是空括号。

它们没有大的变化,没有重大问题,但它们很快就会堆积起来......

此代码也是使用最新C99 / C11标准的功能编写的,这些功能在K&amp; R中找不到,因为该书也没有最新的C标准。

此外,在K&amp; R中有一些案例,这本书是不正确的,或者它宣扬了公然危险的做法。一个完美的例子是:类型化malloc的结果。有关该书的有效批评的更多例子可以在this article中找到。

由于存在大量错误,错误和拼写错误,因此请务必在阅读K&amp; R时始终拥有errata

答案 2 :(得分:3)

该程序运行正常。请注意,它在打印之前需要一些输入;它计算输入中的行数,单词和字符数。因此,如果您将代码编译为example并运行:

echo this has four words | example

你会看到输出:

1 4 20

(即1行,4个字,20个字符)。

答案 3 :(得分:2)

所以,你的程序可能只打印任何东西,但在你按Ctrl + C或类似的东西之前不会给你提示,对吧?这意味着您永远不会退出while循环,这意味着您的输入中没有EOF。

该书基于较旧的架构,可能对构成EOF的内容有不同的约定。我对这本书的建议是继续使用它,保持灵活的思维,以便你可以解释错误并解决它们。从书本中学习很棒,但是在你开始玩它并自己调试之前,你不会真正地集成它。例如,如果我不知道这个程序中发生了什么,我可能会在while循环中放入一个printf来获得有关循环行为的一些反馈。我也可以尝试将EOF改为其他东西(可能是-1,。,//)。想象一下,如果你是一个小孩子只是玩弄东西,你可能会学得更快。这至少是我的经验。

至于其他可以借鉴的书籍,我强烈推荐Jon Erickson撰写的“黑客,剥削艺术”一书。它不需要以前的编程经验,第二章是对C的一个非常全面的介绍。我从私立大学的三个学期的计算机编程课程中学到了更多关于计算机如何真正起作用的能力。它以非常清晰但密集的方式解释了如何使用GNU调试器,编译器如何解释您编写的代码,内存如何工作(堆栈,bss等),最重要的是,它解释了如何查看生活中的其他内容作为程序(法律,生物学等)。如果你有坚持不懈的努力,本书的其余部分将教你大量有用的信息。

祝你好运和快乐的黑客攻击!

答案 4 :(得分:0)

对我来说很好。它确实不应该过时,因为语言在很长一段时间内没有太大变化。互联网和书籍中存在的一些示例可以是特定于操作系统的。一个典型的例子是system("PAUSE");,它只适用于Windows,但可以转换为一个哨兵循环,不断询问你是想再次运行它还是有一个选项菜单。我运行了这个例子并点击了ctrl-d并输出了5 3 14。以下是我的意见。最后两行是空行。

bla
blah
2

我通常通过在{nix

上重定向./a.out < a.in等输入来运行这样的程序

答案 5 :(得分:0)

“C程序设计语言”对你来说是一本非常好的书,相信你的朋友。 你没有看到的原因是,你没有结束你的意见。 在Unix中,您可以输入 Ctrl + D 来结束输入。 程序还可以,我测试一下。

答案 6 :(得分:-2)

C编程语言是Dennis Ritchie写的一本好书。但是,如果您对此感到不满意,可以使用另一本书:
让我们C-by Yashwant Kanetkar 完成本书后,你想知道你真正知道多少C(也就是说,你对它的语法及其怪癖了解多少),你可以试试这个:
测试你的C技能 - 由Yashwant Kanetkar