"The C Programming Language", 2nd edition, Kernighan and Ritchie

目      录
译者序

第1版序
前言
第1章   基本概念 
1.1   入门 
1.2   变量与算术表达式 
1.3   for语句 
1.4   符号常量 
1.5   字符输入输出 
1.5.1   文件复制 
1.5.2   字符计数 
1.5.3   行计数 
1.5.4   单词计数 
1.6   数组 
1.7   函数 
1.8   变元—按值调用 
1.9   字符数组 
1.10   外部变量与作用域 
第2章   类型、运算符与表达式 
2.1   变量名 
2.2   数据类型与大小 
2.3   常量 
2.4   说明 
2.5   算术运算符 
2.6   关系运算符与逻辑运算符  
2.7   类型转换 
2.8   加一与减一运算符 
2.9   按位运算符 
2.10   赋值运算符与赋值表达式 
2.11   条件表达式 
2.12   运算符优先级与表达式求值次序 
第3章   控制流 
3.1   语句与分程序 
3.2    if-else语句 
3.3   else-if语句 
3.4   switch语句 
3.5   while与for循环语句 
3.6   do-while循环语句 
3.7   break语句与continue语句 
3.8   goto语句与标号 
第4章   函数与程序结构 
4.1   函数的基本知识 
4.2   返回非整数值的函数 
4.3   外部变量 
4.4   作用域规则 
4.5   头文件 
4.6   静态变量 
4.7   寄存器变量 
4.8   分程序结构 
4.9   初始化 
4.10   递归 
4.11   C预处理程序 
4.11.1   文件包含 
4.11.2   宏替换 
4.11.3   条件包含 
第5章   指针与数组 
5.1   指针与地址 
5.2   指针与函数变元 
5.3   指针与数组 
5.4   地址算术运算 
5.5   字符指针与函数 
5.6   指针数组与指向指针的指针 
5.7   多维数组 
5.8   指针数组的初始化 
5.9   指针与多维数组 
5.10   命令行变元 
5.11   指向函数的指针 
5.12   复杂说明 
第6章   结构 
6.1   结构的基本知识 
6.2   结构与函数 
6.3   结构数组 
6.4   结构指针 
6.5   自引用结构 
6.6   查找表 
6.7   类型定义 
6.8   联合 
6.9   位字段 
第7章   输入与输出 
7.1   标准输入输出 
7.2   格式输出—printf函数 
7.3   变长变元表 
7.4   格式输入—scanf函数 
7.5   文件访问 
7.6   错误处理—stderr和exit函数 
7.7   行输入输出 
7.8   其他函数 
7.8.1   字符串处理函数 
7.8.2   字符类测试和转换函数 
7.8.3   ungetc函数 
7.8.4   命令执行函数 
7.8.5   存储管理函数 
7.8.6   数学函数 
7.8.7   随机数发生器函数 
第8章   UNIX系统界面 
8.1   文件描述符 
8.2   低级I/O—read和write系统调用 
8.3   open、creat、close和unlink系统调用 
8.4   随机访问—lseek系统调用 
8.5   实例—fopen和getc函数的一种实现
方法 
8.6   实例—目录显示 
8.7   实例—存储分配程序 
附录A   参考手册 
A.1   引言 
A.2   词法规则 
A.3   语法符号 
A.4   标识符的含义 
A.5   对象和左值 
A.6   转换 
A.7   表达式 
A.8   说明 
A.9   语句 
A.10   外部说明 
A.11   作用域与连接 
A.12      预处理 
A.13   语法 
附录B   标准库 
B.1   输入与输出:<stdio.h> 
B.2   字符类测试:<ctype.h> 
B.3   字符串函数:<string.h> 
B.4   数学函数:<math.h> 
B.5   实用函数:<stdlib.h> 
B.6   诊断:<assert.h> 
B.7   变量变元表:<stdarg.h> 
B.8   非局部跳转:<setjmp.h> 
B.9   信号处理:<signal.h> 
B.10   日期与时间函数:<time.h> 
B.11   由实现定义的限制:<limits.h>和
<float.h> 
附录C   变更小结 

  1. getchar() and putchar()
  2. #include <stdio.h>
  3. /* 用于将输入复制到输出的程序;第2个版本*/
  4. main ( )
  5. {
  6. int c;
  7. while ( (c = getchar ( ) ) != EOF )//End Of File,文件结束< stdio.h>库定义的整数
  8. putchar ( c );
  9. }
  10. 在这一程序中,w h i l e循环语句先读一个字符并将其赋给c,然后测试该字符是否为文件结束标记。如果该字符不是文件结束标记,那么就执行w h i l e语句体,把该字符打印出来。再重复执行该w h i l e语句。当最后到达输入结束位置时, w h i l e循环语句终止执行,从而整个m a i n程序执行结束。之所以不把c说明成c h a r类型,是因为c必须大到除了能存储任何可能的字符外还要能存储文件结束符E O F。因此,把c说明成i n t类型的。

1.5.1 文件复制

Verify that the expression getchar() != EOF is 0 or 1.

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.   printf("Press a key. ENTER would be nice :-)/n/n");
  5.   printf("The expression getchar() != EOF evaluates to %d/n", getchar() != EOF);
  6.   return 0;
  7. }

Write a program to print the value of EOF .

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.   printf("The value of EOF is %d/n/n", EOF);
  5.   
  6.   return 0;
  7. }
1.5.2 字符计数
  1. #include <stdio.h>
  2. /* 统计输入的字符数; 第2个版本*/
  3. main ( )
  4. {
  5. double nc;
  6. for ( nc = 0; getchar ( ) != EOF; ++nc )
  7. ;
  8. printf("%.0f/n", nc);
  9. }
  1. #include <stdio.h>
  2. /* 统计输入的行数*/
  3. main ( )
  4. {
  5. long c, nl;
  6. nl = 0;
  7. while ( (c = getchar ( ) ) != EOF )
  8. if ( c =='/n' )
  9. ++nl;
  10. printf("%d/n", nl);
  11. }

编写一个用于统计空格、制表符与换行符个数的程序

Write a program to count blanks, tabs, and newlines

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.   int blanks, tabs, newlines;
  5.   int c;
  6.   int done = 0;
  7.   int lastchar = 0;
  8.   blanks = 0;
  9.   tabs = 0;
  10.   newlines = 0;
  11.   while(done == 0)
  12.   {
  13.     c = getchar();
  14.     if(c == ' ')
  15.       ++blanks;
  16.     if(c == '/t')
  17.       ++tabs;
  18.     if(c == '/n')
  19.       ++newlines;
  20.     if(c == EOF)
  21.     {
  22.       if(lastchar != '/n')
  23.       {
  24.         ++newlines; /* this is a bit of a semantic stretch, but it copes
  25.                      * with implementations where a text file might not
  26.                      * end with a newline. Thanks to Jim Stad for pointing
  27.                      * this out.
  28.                      */
  29.       }
  30.       done = 1;
  31.     }
  32.     lastchar = c;
  33.   }
  34.   printf("Blanks: %d/nTabs: %d/nLines: %d/n", blanks, tabs, newlines);
  35.   return 0;
  36. }

编写一个程序,把它的输入复制到输出,并在此过程中将相连的多个空格用一个
空格代替。

Write a program to copy its input to its output, replacing each string of one or more blanks by a single blan

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.   int c;
  5.   int inspace;
  6.   inspace = 0;
  7.   while((c = getchar()) != EOF)
  8.   {
  9.     if(c == ' ')
  10.     {
  11.       if(inspace == 0)
  12.       {
  13.         inspace = 1;
  14.         putchar(c);
  15.       }
  16.     }
  17.     /* We haven't met 'else' yet, so we have to be a little clumsy */
  18.     if(c != ' ')
  19.     {
  20.       inspace = 0;
  21.       putchar(c);
  22.     }
  23.   }
  24.   return 0;
  25. }
  26. Chris Sidi writes: "instead of having an "inspace" boolean, you can keep track of the previous character and see if both the current character and previous character are spaces:" 
  27. #include <stdio.h>
  28. /* count lines in input */
  29. int
  30. main()
  31. {
  32.         int c, pc; /* c = character, pc = previous character */
  33.         /* set pc to a value that wouldn't match any character, in case
  34.         this program is ever modified to get rid of multiples of other
  35.         characters */
  36.         pc = EOF;
  37.         while ((c = getchar()) != EOF) {
  38.                 if (c == ' ')
  39.                         if (pc != ' ')   /* or if (pc != c) */ 
  40.                                 putchar(c);
  41.                 /* We haven't met 'else' yet, so we have to be a little clumsy */
  42.                 if (c != ' ')
  43.                         putchar(c);
  44.                 pc = c;
  45.         }
  46.         return 0;
  47. }
  48. Stig writes: "I am hiding behind the fact that break is mentioned in the introduction"
  49. #include <stdio.h>
  50. int main(void)
  51. {
  52.         int c;
  53.         while ((c = getchar()) != EOF) {
  54.                 if (c == ' ') {
  55.                        putchar(c);
  56.                        while((c = getchar()) == ' ' && c != EOF)
  57.                                ;
  58.                }
  59.                if (c == EOF)
  60.                        break/* the break keyword is mentioned
  61.                                * in the introduction... 
  62.                                * */
  63.                putchar(c);
  64.         }
  65.         return 0;

编写一个程序,把它的输入复制到输出,并在此过程中把制表符换成/ t、把回退
符换成/ b、把反斜杠换成/ /。这样可以使得制表符与回退符能以无歧义的方式可见。

Write a program to copy its input to its output, replacing each tab by /t , each backspace by /b , and each backslash by // . This makes tabs and backspaces visible in an unambiguous way. 

 

  1. Category 0 
  2. Gregory Pietsch pointed out that my solution was actually Category 1. He was quite right. Better still, he was kind enough to submit a Category 0 solution himself. Here it is
  3. /* Gregory Pietsch <[email protected]> */
  4. /*
  5.  * Here's my attempt at a Category 0 version of 1-10.
  6.  *
  7.  * Gregory Pietsch
  8.  */
  9. #include <stdio.h>
  10. int main()
  11. {
  12.     int c, d;
  13.     while ( (c=getchar()) != EOF) {
  14.         d = 0;
  15.         if (c == '//') {
  16.             putchar('//');
  17.             putchar('//');
  18.             d = 1;
  19.         }
  20.         if (c == '/t') {
  21.             putchar('//');
  22.             putchar('t');
  23.             d = 1;
  24.         }
  25.         if (c == '/b') {
  26.             putchar('//');
  27.             putchar('b');
  28.             d = 1;
  29.         }
  30.         if (d == 0)
  31.             putchar(c);        
  32.     }
  33.     return 0;
  34. }
  35. Category 1 
  36. This solution, which I wrote myself, is the sadly discredited Cat 0 answer which has found a new lease of life in Category 1. 
  37. #include <stdio.h>
  38. #define ESC_CHAR '//'
  39. int main(void)
  40. {
  41.   int c;
  42.   while((c = getchar()) != EOF)
  43.   {
  44.     switch(c)
  45.     {
  46.       case '/b':
  47.         /* The OS on which I tested this (NT) intercepts /b characters. */
  48.         putchar(ESC_CHAR);
  49.         putchar('b');
  50.         break;
  51.       case '/t':
  52.         putchar(ESC_CHAR);
  53.         putchar('t');
  54.         break;
  55.       case ESC_CHAR:
  56.         putchar(ESC_CHAR);
  57.         putchar(ESC_CHAR);
  58.         break;
  59.       default:
  60.         putchar(c);
  61.         break;
  62.     }
  63.   }
  64.   return 0;

 1.5.4 单词计数

 

  1. #include <stdio.h>
  2. #define IN 1 /* 在单词内*/
  3. #define OUT 0 /* 在单词外*/
  4. /* 统计输入的行数、单词数与字符数*/
  5. main ( )
  6. {
  7. int c, nl, nw, nc, state;
  8. state = OUT;
  9. nl = nw = nc = 0;
  10. while ( (c = getchar ( ) ) != EOF ) {
  11. ++nc;
  12. if ( c =='/n' )
  13. ++nl;
  14. if ( c == ' ' ||c == '/n' || c == '/t' )
  15. state = OUT;
  16. else if ( state == OUT ) {
  17. state = IN;
  18. ++nw;
  19. }
  20. }
  21. printf("%d %d %d/n", nl, nw, nc);
  22. }

你准备怎样测试单词计数程序?如果程序中出现任何错误,那么什么样的输入最
有利于发现这些错误?

How would you test the word count program? What kinds of input are most likely to uncover bugs if there are any?

  1. It sounds like they are really trying to get the programmers to learn how to do a unit test. I would submit the following: 
  2. 0. input file contains zero words 
  3. 1. input file contains 1 enormous word without any newlines 
  4. 2. input file contains all white space without newlines 
  5. 3. input file contains 66000 newlines 
  6. 4. input file contains word/{huge sequence of whitespace of different kinds}/word 
  7. 5. input file contains 66000 single letter words, 66 to the line 
  8. 6. input file contains 66000 words without any newlines 
  9. 7. input file is /usr/dict contents (or equivalent) 
  10. 8. input file is full collection of moby words 
  11. 9. input file is binary (e.g. its own executable) 
  12. 10. input file is /dev/nul (or equivalent) 
  13. 66000 is chosen to check for integral overflow on small integer machines. 
  14. Dann suggests a followup exercise 1-11a: write a program to generate inputs (0,1,2,3,4,5,6) 
  15. I guess it was inevitable that I'd receive a solution for this followup exercise! Here is Gregory Pietsch's program to generate Dann's suggested inputs: 
  16. #include <assert.h>
  17. #include <stdio.h>
  18. int main(void)
  19. {
  20.     FILE *f;
  21.     unsigned long i;
  22.     static char *ws = " /f/t/v";
  23.     static char *al = "abcdefghijklmnopqrstuvwxyz";
  24.     static char *i5 = "a b c d e f g h i j k l m "
  25.                       "n o p q r s t u v w x y z "
  26.                       "a b c d e f g h i j k l m "
  27.                       "n o p q r s t u v w x y z "
  28.                       "a b c d e f g h i j k l m "
  29.                       "n/n";
  30.     /* Generate the following: */
  31.     /* 0. input file contains zero words */
  32.     f = fopen("test0""w");
  33.     assert(f != NULL);
  34.     fclose(f);
  35.     /* 1. input file contains 1 enormous word without any newlines */
  36.     f = fopen("test1""w");
  37.     assert(f != NULL);
  38.     for (i = 0; i < ((66000ul / 26) + 1); i++)
  39.         fputs(al, f);
  40.     fclose(f);
  41.     /* 2. input file contains all white space without newlines */
  42.     f = fopen("test2""w");
  43.     assert(f != NULL);
  44.     for (i = 0; i < ((66000ul / 4) + 1); i++)
  45.         fputs(ws, f);
  46.     fclose(f);
  47.     /* 3. input file contains 66000 newlines */
  48.     f = fopen("test3""w");
  49.     assert(f != NULL);
  50.     for (i = 0; i < 66000; i++)
  51.         fputc('/n', f);
  52.     fclose(f);
  53.     /* 4. input file contains word/ 
  54.      *    {huge sequence of whitespace of different kinds}
  55.      *    /word 
  56.      */
  57.     f = fopen("test4""w");
  58.     assert(f != NULL);
  59.     fputs("word", f);
  60.     for (i = 0; i < ((66000ul / 26) + 1); i++)
  61.         fputs(ws, f);
  62.     fputs("word", f);
  63.     fclose(f);
  64.     /* 5. input file contains 66000 single letter words,
  65.      *    66 to the line 
  66.      */
  67.     f = fopen("test5""w");
  68.     assert(f != NULL);
  69.     for (i = 0; i < 1000; i++)
  70.         fputs(i5, f);
  71.     fclose(f);
  72.     /* 6. input file contains 66000 words without any newlines */
  73.     f = fopen("test6""w");
  74.     assert(f != NULL);
  75.     for (i = 0; i < 66000; i++)
  76.         fputs("word ", f);
  77.     fclose(f);
  78.     return 0;
  79. }

编写一个程序,以每行一个单词的形式打印输入。

Write a program that prints its input one word per line.

 

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4.   int c;
  5.   int inspace;
  6.   inspace = 0;
  7.   while((c = getchar()) != EOF)
  8.   {
  9.     if(c == ' ' || c == '/t' || c == '/n')
  10.     {
  11.       if(inspace == 0)
  12.       {
  13.         inspace = 1;
  14.         putchar('/n');
  15.       }
  16.       /* else, don't print anything */
  17.     }
  18.     else
  19.     {
  20.       inspace = 0;
  21.       putchar(c);
  22.     }
  23.   }
  24.   return 0;
  25. }

1.6 数组

  1. #include <stdio.h>
  2. /* 统计各个数字、空白字符及其他字符分别出现的次数*/
  3. main ( )
  4. {
  5. int c, i, nwhite, nother;
  6. int ndigit[10];
  7. nwhite = nother = 0;
  8. for ( i =0; i < 10; ++i )
  9. ndigit[i] = 0;
  10. while ( ( c = getchar() ) != EOF )
  11. if ( c >= '0' && c <= '9' )
  12. ++ndigit[c - '0'];
  13. else if ( c == ' ' ||c == '/n' || c == '/t' )
  14. ++nwhite;
  15. else
  16. ++nother;
  17. printf( "digits =" );
  18. for ( i =0; i < 10; ++i )
  19. printf( " %d", ndigit[i] );
  20. printf( ", white space = %d, other = %d", nwhite, nother);
  21. }
  22. 当把程序自身作为输入时,输出为:
    digits = 9 3 0 0 0 0 0 0 0 1, white space = 123, other = 345

练习1-13 编写一个程序,打印其输入的文件中单词长度的直方图。横条的直方图比较容易
绘制,竖条直方图则要困难些。

Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.

 

  1. #include <stdio.h>
  2. #define MAXWORDLEN 10
  3. int main(void)
  4. {
  5.   int c;
  6.   int inspace = 0;
  7.   long lengtharr[MAXWORDLEN + 1];
  8.   int wordlen = 0;
  9.   int firstletter = 1;
  10.   long thisval = 0;
  11.   long maxval = 0;
  12.   int thisidx = 0;
  13.   int done = 0;
  14.   for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
  15.   {
  16.     lengtharr[thisidx] = 0;
  17.   }
  18.   while(done == 0)
  19.   {
  20.     c = getchar();
  21.     if(c == ' ' || c == '/t' || c == '/n' || c == EOF)
  22.     {
  23.       if(inspace == 0)
  24.       {
  25.         firstletter = 0;
  26.         inspace = 1;
  27.         if(wordlen <= MAXWORDLEN)
  28.         {
  29.           if(wordlen > 0)
  30.           {
  31.             thisval = ++lengtharr[wordlen - 1];
  32.             if(thisval > maxval)
  33.             {
  34.               maxval = thisval;
  35.             }
  36.           }
  37.         }
  38.         else
  39.         {
  40.           thisval = ++lengtharr[MAXWORDLEN];
  41.           if(thisval > maxval)
  42.           {
  43.             maxval = thisval;
  44.           }
  45.         }
  46.       }
  47.       if(c == EOF)
  48.       {
  49.         done = 1;
  50.       }
  51.     }
  52.     else
  53.     {
  54.       if(inspace == 1 || firstletter == 1)
  55.       {
  56.         wordlen = 0;
  57.         firstletter = 0;
  58.         inspace = 0;
  59.       }
  60.       ++wordlen;
  61.     }
  62.   }
  63.   for(thisval = maxval; thisval > 0; thisval--)
  64.   {
  65.     printf("%4d  | ", thisval);
  66.     for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
  67.     {
  68.       if(lengtharr[thisidx] >= thisval)
  69.       {
  70.         printf("*  ");
  71.       }
  72.       else
  73.       {
  74.         printf("   ");
  75.       }
  76.     }
  77.     printf("/n");
  78.   }
  79.   printf("      +");
  80.   for(thisidx = 0; thisidx <= MAXWORDLEN; thisidx++)
  81.   {
  82.     printf("---");
  83.   }
  84.   printf("/n       ");
  85.   for(thisidx = 0; thisidx < MAXWORDLEN; thisidx++)
  86.   {
  87.     printf("%2d ", thisidx + 1);
  88.   }
  89.   printf(">%d/n", MAXWORDLEN);
  90.   return 0;
  91. }
  92. Here's the output of the program when given its own source as input: 
  93.  113  | *                                
  94.  112  | *                                
  95.  111  | *                                
  96.  110  | *                                
  97.  109  | *                                
  98.  108  | *                                
  99.  107  | *                                
  100.  106  | *                                
  101.  105  | *                                
  102.  104  | *                                
  103.  103  | *                                
  104.  102  | *                                
  105.  101  | *                                
  106.  100  | *                                
  107.   99  | *                                
  108.   98  | *                                
  109.   97  | *                                
  110.   96  | *                                
  111.   95  | *                                
  112.   94  | *  *                             
  113.   93  | *  *                             
  114.   92  | *  *                             
  115.   91  | *  *                             
  116.   90  | *  *                             
  117.   89  | *  *                             
  118.   88  | *  *                             
  119.   87  | *  *                             
  120.   86  | *  *                             
  121.   85  | *  *                             
  122.   84  | *  *                             
  123.   83  | *  *                             
  124.   82  | *  *                             
  125.   81  | *  *                             
  126.   80  | *  *                             
  127.   79  | *  *                             
  128.   78  | *  *                             
  129.   77  | *  *                             
  130.   76  | *  *                             
  131.   75  | *  *                             
  132.   74  | *  *                             
  133.   73  | *  *                             
  134.   72  | *  *                             
  135.   71  | *  *                             
  136.   70  | *  *                             
  137.   69  | *  *                             
  138.   68  | *  *                             
  139.   67  | *  *                             
  140.   66  | *  *                             
  141.   65  | *  *                             
  142.   64  | *  *                             
  143.   63  | *  *  *                          
  144.   62  | *  *  *                          
  145.   61  | *  *  *                          
  146.   60  | *  *  *                          
  147.   59  | *  *  *                          
  148.   58  | *  *  *                          
  149.   57  | *  *  *                          
  150.   56  | *  *  *                          
  151.   55  | *  *  *                          
  152.   54  | *  *  *                          
  153.   53  | *  *  *                          
  154.   52  | *  *  *  *                       
  155.   51  | *  *  *  *                       
  156.   50  | *  *  *  *                       
  157.   49  | *  *  *  *                       
  158.   48  | *  *  *  *                       
  159.   47  | *  *  *  *                       
  160.   46  | *  *  *  *                       
  161.   45  | *  *  *  *                       
  162.   44  | *  *  *  *                       
  163.   43  | *  *  *  *        *              
  164.   42  | *  *  *  *        *              
  165.   41  | *  *  *  *        *              
  166.   40  | *  *  *  *        *              
  167.   39  | *  *  *  *        *              
  168.   38  | *  *  *  *        *              
  169.   37  | *  *  *  *        *              
  170.   36  | *  *  *  *        *              
  171.   35  | *  *  *  *        *              
  172.   34  | *  *  *  *        *              
  173.   33  | *  *  *  *        *              
  174.   32  | *  *  *  *        *              
  175.   31  | *  *  *  *        *              
  176.   30  | *  *  *  *        *           *  
  177.   29  | *  *  *  *        *           *  
  178.   28  | *  *  *  *  *     *           *  
  179.   27  | *  *  *  *  *     *           *  
  180.   26  | *  *  *  *  *     *           *  
  181.   25  | *  *  *  *  *  *  *           *  
  182.   24  | *  *  *  *  *  *  *           *  
  183.   23  | *  *  *  *  *  *  *           *  
  184.   22  | *  *  *  *  *  *  *        *  *  
  185.   21  | *  *  *  *  *  *  *        *  *  
  186.   20  | *  *  *  *  *  *  *        *  *  
  187.   19  | *  *  *  *  *  *  *        *  *  
  188.   18  | *  *  *  *  *  *  *        *  *  
  189.   17  | *  *  *  *  *  *  *        *  *  
  190.   16  | *  *  *  *  *  *  *        *  *  
  191.   15  | *  *  *  *  *  *  *        *  *  
  192.   14  | *  *  *  *  *  *  *  *     *  *  
  193.   13  | *  *  *  *  *  *  *  *     *  *  
  194.   12  | *  *  *  *  *  *  *  *     *  *  
  195.   11  | *  *  *  *  *  *  *  *     *  *  
  196.   10  | *  *  *  *  *  *  *  *     *  *  
  197.    9  | *  *  *  *  *  *  *  *  *  *  *  
  198.    8  | *  *  *  *  *  *  *  *  *  *  *  
  199.    7  | *  *  *  *  *  *  *  *  *  *  *  
  200.    6  | *  *  *  *  *  *  *  *  *  *  *  
  201.    5  | *  *  *  *  *  *  *  *  *  *  *  
  202.    4  | *  *  *  *  *  *  *  *  *  *  *  
  203.    3  | *  *  *  *  *  *  *  *  *  *  *  
  204.    2  | *  *  *  *  *  *  *  *  *  *  *  
  205.    1  | *  *  *  *  *  *  *  *  *  *  *  
  206.       +---------------------------------
  207.         1  2  3  4  5  6  7  8  9 10 >10

 

练习1-14 编写一个程序,打印其输入的文件中各个字符出现频率的直方图。

Write a program to print a histogram of the frequencies of different characters in its input.

  1. #include <stdio.h>
  2. /* NUM_CHARS should really be CHAR_MAX but K&R haven't covered that at this stage in the book */
  3. #define NUM_CHARS 256
  4. int main(void)
  5. {
  6.   int c;
  7.   long freqarr[NUM_CHARS + 1];
  8.   long thisval = 0;
  9.   long maxval = 0;
  10.   int thisidx = 0;
  11.   for(thisidx = 0; thisidx <= NUM_CHARS; thisidx++)
  12.   {
  13.     freqarr[thisidx] = 0;
  14.   }
  15.   while((c = getchar()) != EOF)
  16.   {
  17.     if(c < NUM_CHARS)
  18.     {
  19.       thisval = ++freqarr[c];
  20.       if(thisval > maxval)
  21.       {
  22.         maxval = thisval;
  23.       }
  24.     }
  25.     else
  26.     {
  27.       thisval = ++freqarr[NUM_CHARS];
  28.       if(thisval > maxval)
  29.       {
  30.         maxval = thisval;
  31.       }
  32.     }
  33.   }
  34.   for(thisval = maxval; thisval > 0; thisval--)
  35.   {
  36.     printf("%4d  |", thisval);
  37.     for(thisidx = 0; thisidx <= NUM_CHARS; thisidx++)
  38.     {
  39.       if(freqarr[thisidx] >= thisval)
  40.       {
  41.         printf("*");
  42.       }
  43.       else if(freqarr[thisidx] > 0)
  44.       {
  45.         printf(" ");
  46.       }
  47.     }
  48.     printf("/n");
  49.   }
  50.   printf("      +");
  51.   for(thisidx = 0; thisidx <= NUM_CHARS; thisidx++)
  52.   {
  53.     if(freqarr[thisidx] > 0)
  54.     {
  55.       printf("-");
  56.     }
  57.   }
  58.   printf("/n       ");
  59.   for(thisidx = 0; thisidx < NUM_CHARS; thisidx++)
  60.   {
  61.     if(freqarr[thisidx] > 0)
  62.     {
  63.       printf("%d", thisidx / 100);
  64.     }
  65.   }
  66.   printf("/n       ");
  67.   for(thisidx = 0; thisidx < NUM_CHARS; thisidx++)
  68.   {
  69.     if(freqarr[thisidx] > 0)
  70.     {
  71.       printf("%d", (thisidx - (100 * (thisidx / 100))) / 10 );
  72.     }
  73.   }
  74.   printf("/n       ");
  75.   for(thisidx = 0; thisidx < NUM_CHARS; thisidx++)
  76.   {
  77.     if(freqarr[thisidx] > 0)
  78.     {
  79.       printf("%d", thisidx - (10 * (thisidx / 10)));
  80.     }
  81.   }
  82.   if(freqarr[NUM_CHARS] > 0)
  83.   {
  84.     printf(">%d/n", NUM_CHARS);
  85.   }
  86.   printf("/n");
  87.   return 0;
  88. }
  89. Here's the output of the program when given its own source as input: 
  90.  474  | *                                                                    
  91.  473  | *                                                                    
  92.  472  | *                                                                    
  93.  471  | *                                                                    
  94.  470  | *                                                                    
  95.  469  | *                                                                    
  96.  468  | *                                                                    
  97.  467  | *                                                                    
  98.  466  | *                                                                    
  99.  465  | *                                                                    
  100.  464  | *                                                                    
  101.  463  | *                                                                    
  102.  462  | *                                                                    
  103.  461  | *                                                                    
  104.  460  | *                                                                    
  105.  459  | *                                                                    
  106.  458  | *                                                                    
  107.  457  | *                                                                    
  108.  456  | *                                                                    
  109.  455  | *                                                                    
  110.  454  | *                                                                    
  111.  453  | *                                                                    
  112.  452  | *                                                                    
  113.  451  | *                                                                    
  114.  450  | *                                                                    
  115.  449  | *                                                                    
  116.  448  | *                                                                    
  117.  447  | *                                                                    
  118.  446  | *                                                                    
  119.  445  | *                                                                    
  120.  444  | *                                                                    
  121.  443  | *                                                                    
  122.  442  | *                                                                    
  123.  441  | *                                                                    
  124.  440  | *                                                                    
  125.  439  | *                                                                    
  126.  438  | *                                                                    
  127.  437  | *                                                                    
  128.  436  | *                                                                    
  129.  435  | *                                                                    
  130.  434  | *                                                                    
  131.  433  | *                                                                    
  132.  432  | *                                                                    
  133.  431  | *                                                                    
  134.  430  | *                                                                    
  135.  429  | *                                                                    
  136.  428  | *                                                                    
  137.  427  | *                                                                    
  138.  426  | *                                                                    
  139.  425  | *                                                                    
  140.  424  | *                                                                    
  141.  423  | *                                                                    
  142.  422  | *                                                                    
  143.  421  | *                                                                    
  144.  420  | *                                                                    
  145.  419  | *                                                                    
  146.  418  | *                                                                    
  147.  417  | *                                                                    
  148.  416  | *                                                                    
  149.  415  | *                                                                    
  150.  414  | *                                                                    
  151.  413  | *                                                                    
  152.  412  | *                                                                    
  153.  411  | *                                                                    
  154.  410  | *                                                                    
  155.  409  | *                                                                    
  156.  408  | *                                                                    
  157.  407  | *                                                                    
  158.  406  | *                                                                    
  159.  405  | *                                                                    
  160.  404  | *                                                                    
  161.  403  | *                                                                    
  162.  402  | *                                                                    
  163.  401  | *                                                                    
  164.  400  | *                                                                    
  165.  399  | *                                                                    
  166.  398  | *                                                                    
  167.  397  | *                                                                    
  168.  396  | *                                                                    </
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值