欢迎访问我的新博客:
原文地址:
题目要求
该题摘自Kernighan的《C程序设计语言》第17页练习1-13。
编写一个程序,打印输入中单词长度的的直方图。水平方向的直方图比较容易绘制,垂直方向的直方图则要困难些。
经过这本C语言圣经第一章的调教,发现getchar()原来那么强大。
多种实现
方案一:
声明state变量,用来记录程序当前是否正位于一个单词之中,这样便于理解。
# include# define MAX 20# define OUT 0# define IN 1int main(void){ int length[MAX]; int c; int vocl; int state = OUT; int i; for(vocl = 0; vocl < MAX; vocl++){ length[vocl] = 0; } while((c = getchar()) != EOF){ if(c != ' ' && c != '\t' && c != '\n'){ if(state == OUT){ vocl = 1; } else{ vocl++; } state = IN; } else{ length[vocl]++; vocl = 0; } } for(vocl = 0; vocl < MAX; vocl++){ if(length[vocl] != 0){ printf("%2d ", vocl); for(i = 1; i <= length[vocl]; i++){ putchar('*'); } putchar('\n'); } }}
方案二:
将state省掉,原理同方案一,代码简单的同时也降低了可读性。
# include# define MAX 20# define OUT 0# define IN 1int main(void){ int length[MAX]; int c; int vocl; int state = OUT; int i; for(vocl = 0; vocl < MAX; vocl++){ length[vocl] = 0; } vocl = 0; //vocl别忘了初始化 while((c = getchar()) != EOF){ if(c != ' ' && c != '\t' && c != '\n'){ vocl++; } else{ length[vocl]++; vocl = 0; } } for(vocl = 0; vocl < MAX; vocl++){ if(length[vocl] != 0){ printf("%2d ", vocl); for(i = 1; i <= length[vocl]; i++){ putchar('*'); } putchar('\n'); } }}
方案三:
一种新的思路,用该字符是否为字母或连字符判断是否为一个单词,是程序更简单、更容易理解。
# include# define MAX 20# define OUT 0# define IN 1int main(void){ int length[MAX]; int c; int vocl = 0; int state = OUT; int i; for(vocl = 0; vocl < MAX; vocl++){ length[vocl] = 0; } vocl = 0; while((c = getchar()) != EOF){ if(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '-'){ vocl++; } else{ length[vocl]++; vocl = 0; } } for(vocl = 0; vocl < MAX; vocl++){ if(length[vocl] != 0){ printf("%2d ", vocl); for(i = 1; i <= length[vocl]; i++){ putchar('*'); } putchar('\n'); } }}
方案四:
对应的参考书提供的一种解法,也使用了state确定程序状态。只是打印直方图的代码更加完善,但不管该长度的单词有无均打印一行,像我一样加个判断语句也是不错的选择。
# include# define MAX 20# define MAXLENGTH 20# define MAXHIST 15int main(void){ int length[MAX]; //存放某一单词长度单词个数的数组 int c; //c=getchar() int vocl = 0; //记录某一单词的长度 int maxvalue; int len = 0; for(vocl = 0; vocl < MAX; vocl++){ length[vocl] = 0; } vocl = 0; while((c = getchar()) != EOF){ if(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '-'){ vocl++; } else{ length[vocl]++; vocl = 0; } } maxvalue = 0; for(vocl = 1; vocl < MAX; ++vocl){ if(length[vocl] > maxvalue){ maxvalue = length[vocl]; } } for(vocl = 1; vocl < MAX; ++vocl){ printf("%5d - %5d : ", vocl, length[vocl]); if(length[vocl] > 0){ if((len = length[vocl] * MAXHIST / maxvalue) <= 0){ len = 1; } } else{ len = 0; } while(len > 0){ putchar('*'); --len; } putchar('\n'); }}
垂直方向直方图
其实,打印垂直方向的直方图没有题目说的那么可怕,也许是我的思维过于简单。
# include# define MAX 20# define MAXLENGTH 20int main(void){ int length[MAX]; int c; int vocl = 0; int i; int r; for(vocl = 0; vocl < MAX; vocl++){ length[vocl] = 0; } vocl = 0; while((c = getchar()) != EOF){ if(c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c == '-'){ vocl++; } else{ length[vocl]++; vocl = 0; } } printf("0 1 2 3 4 5 6 7 8 9 10\n"); for(r = 1; r < MAXLENGTH; r++){ for(vocl = 0; vocl < MAX; vocl++){ if(r <= length[vocl]){ printf("* "); } else{ printf(" "); } } putchar('\n'); }}