Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The C programming language book example: maybe out of date?

Tags:

c

I started learning C and a friend of mine (older than me) suggested The C Programming Language by Brian Kernighan and Dennis Ritchie.

How ever, while trying some of the examples, they act differently than expected, and not as written in the book.

For example, this one, that doesn't seem to work (prints nothing):

#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;
}

Do you think I should keep reading this book, maybe there are only a few mistakes, and it's worth reading? Or there is a better book for C starters.

EDIT: My assumption was that sending the input with the ENTER key, will simulate EOF, which is not. CTRL+Z does.

Thank you for helping.

like image 357
Novak Avatar asked Dec 04 '22 15:12

Novak


2 Answers

It works for me.

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

The program reads text from standard input until it reached end-of-file. I suspect you just haven't signaled the end-of-file condition properly when reading from the keyboard. On Linux and other Unix-like systems, type Ctrl-D on a line by itself. On Windows, type Ctrl-Z.

If you launch the program from an IDE, it might run the program in a newly launched terminal window that closes when the program finishes; in that case, the window might disappear before you can see the output. If your IDE doesn't provide a way to override this misbehavior, you can either run it directly from a terminal window running a shell, or you can add a line such as:

getchar();

to the end of the program, before the return 0;. This causes it to read (and ignore) a character of input before terminating; you can type Enter after seeing the output. Note that this kind of thing can make running your program more awkward when you execute it from a shell, so do this only if necessary.

"The C Programming Language" by Kernighan and Ritchie, commonly referred to as K&R, is an excellent C book; Ritchie, after all, largely invented the language, though it does tend to assume some existing programming knowledge. Be sure you have the second edition; the first describes an earlier version of the language. (There have been two new ISO C standards since K&R2 was published, but they don't add anything that's critical for an introductory test.)

For a list of other C online tutorials and books, see questions 18.9 and 18.10 of the comp.lang.c FAQ.

like image 52
Keith Thompson Avatar answered Mar 25 '23 07:03

Keith Thompson


K&R has received a lot of "bandwagon hype" because of nostalgia and because it was written by Dennis Ritchie. And it is without doubt the most famous programming book ever written. Yet, in my opinion it is not a good book for beginners.

The main reason is that the book was written before good programming style was invented. Most examples are written in what most modern C programmers would find to be a rather messy coding style. What is good and bad coding style is certainly a subjective topic. But take your example. It could be rewritten as this:

#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;
}

I find the above style more readable and correct. Changes are:

  • Sane variable names.
  • Readable variable declaration lists.
  • No mysterious state variable. Use bool type instead.
  • Always use {} for every statement to prevent numerous classic bugs.
  • No multiple check against '\n' (faster code).
  • Counter increment at the end of a while loop (common coding style).
  • Correct way to end main() as per C99.
  • Nitpick about main(), declared as void rather than empty parenthesis.

They are no big changes, no major issues, but it all quickly piles up...

This code was also written using features from the latest C99/C11 standards, something you won't find in K&R, since the book is also not up to date with the latest C standards.

Furthermore there are a few cases in K&R where the book is just incorrect, or where it preaches blatantly dangerous practice. One perfect example of such is: typecasting the result of malloc. More examples with valid criticism of the book can be found in this article.

As there are numerous bugs, errors and typos, so make sure to always have the errata within reach when reading K&R.

like image 38
Lundin Avatar answered Mar 25 '23 05:03

Lundin