#include <stdio.h> #define MAX_LEN 10 //单词的最大长度 #define IN 1 #define OUT 0 int main(void) { int len; //每个单词的长度 int wc[MAX_LEN+1] = {0}; //每个长度对应的单词数 int c, i, j; int state; int maxnum=0; //wc[]中的最大数 len = c = i = 0; state = OUT; while((c = getchar()) != EOF) { if(c == ' ' || c == '\t' || c == '\n') { if(state == IN) { //或者 if(len > 0) if(len >= MAX_LEN) { wc[MAX_LEN]++; len = MAX_LEN; //单词长度大于MAX_LEN } else { wc[len]++; } if(maxnum < wc[len]) maxnum = wc[len]; len = 0; state = OUT; } } else if(state == OUT) { state = IN; len = 0; //单词真实的长度为len+1 } else len++; } putchar('\n'); for(i = maxnum; i > 0; i--) { printf("%3d|", i); for(j = 0; j <= MAX_LEN; j++) { if(wc[j] >= i) printf(" * "); else printf(" "); } putchar('\n'); } printf(" +"); for(i = 0; i <= MAX_LEN; i++) printf("___"); printf("\n "); for(i = 0; i < MAX_LEN; i++) { printf("%3d", i+1); } printf(" >10"); putchar('\n'); return 0; }
效果图
EOF释疑(转自这里)
首先要明白一点,EOF并不是标志结尾的特殊字符,而是文字流(stream,标准输入或者文件)达到结尾时返回的一个信号量,在stdio.h中定义为常量,其值常常为-1,只在文本文件中存在,二进制文件中不存在。
1.如果是从标准输入中读取stream,如下程序
int c;//定义为int类型,因为返回值EOF(-1)是int类型的 while((c=getchar()) != EOF) putchar(c);由于标准输入中无法事先判断长度,无法判断是否是End Of File,所以需要手动输入一个字符表示达到EOF。
Windows中,在新的一行开头中按下Ctrl+Z,表示达到EOF(因为Windows输入是阻塞式的,所以在敲下换行键之前不会检测Ctrl+Z);
Linux中,在新的一行开头,按下Ctrl-D,表示达到EOF(或者在一行的中间按两次Ctrl-D,因为在一行的中间按下Ctrl-D,表示输出"标准输入"的缓存区);
2.如果是从文件中读取stream,一般写成如下形式
int c; while ((c = fgetc(fp)) != EOF){ c = fgetc(fp); do something; }这样写有一个问题。fgetc()不仅是遇到文件结尾时返回EOF,而且当发生错误时,也会返回EOF。因此,C语言又提供了feof()函数,用来保证确实是到了文件结尾。上面的代码feof()版本的写法就是:
int c; while (!feof(fp)) { c = fgetc(fp); do something; }但是,这样写也有问题。fgetc()读取文件的最后一个字符以后,C语言的feof()函数依然返回0,表明没有到达文件结尾;只有当fgetc()向后再读取一个字符(即越过最后一个字符),feof()才会返回一个非零值,表示到达文件结尾。
所以,按照上面这样写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次。所以,最保险的写法是像下面这样:
int c = fgetc(fp); while (c != EOF) { do something; c = fgetc(fp); } if (feof(fp)) { printf("\n End of file reached."); } else { printf("\n Something went wrong."); }
这样在读取stream时,如果c = fgetc(fp) 读到的是二进制的-1,怎么区分读到的c(-1)跟信号值(-1)呢?
一种解释(不一定对,欢迎讨论):
在文本文件中,数据以字符的ASCII码值的形式存放。ASCII码值的范围是0~255,不可能出现-1,-1实际上是‘-’ 和‘1’,而fgetc是文本视图处理文件的,因此可以用EOF作为文件结束标志输入的。
注意:EOF只存在文本视图中,二进制视图是通过比较文件长度来判断是否达到文件结尾。