练习1-13 编写一个程序,打印输入中单词长度的直方图。水平方向的直方图比较容易绘制,垂直方向的直方图则要困难些。
ChapterOneExerciseThirteenOne.cpp
cpp
#include <stdio.h>
#define MAXHIST 15 /* max length of histogram */
#define MAXWORD 11 /* max length of a word */
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* print horizontal histogram */
main()
{
int c, i, nc, state;
int len; /* length of each bar */
int maxvalue; /* maximum value for wl[] */
int ovflow; /* number of overflow words */
int wl[MAXWORD]; /* word length counters */
state = OUT;
nc = 0; /* number of chars in a word */
ovflow = 0; /* number of words >= MAXWORD */
for(i = 0; i < MAXWORD; ++i)
wl[i] = 0;
while((c = getchar()) != EOF){
if(c == ' ' || c == '\n' || c == '\t'){
state = OUT;
if(nc > 0)
if(nc < MAXWORD)
++wl[nc];
else
++ovflow;
nc = 0;
}else if(state == OUT){
state = IN;
nc = 1; /* begining of a new word */
}else
++nc; /* inside a wrod */
}
maxvalue = 0;
for(i = 1; i < MAXWORD; ++i)
if(wl[i] > maxvalue)
maxvalue = wl[i];
for(i = 1; i < MAXWORD; ++i){
printf("%5d - %5d : ", i, wl[i]);
if(wl[i] > 0){
if((len = wl[i] * MAXHIST / maxvalue) <= 0)
len = 1;
} else
len = 0;
while(len > 0){
putchar('*');
--len;
}
putchar('\n');
}
if(ovflow > 0)
printf("There are %d words >= %d\n", ovflow, MAXWORD);
}
空格、换行符或制表符标志着单词的结束。如果有一个单词(nc>0)且它的长度小于允许单词最大长度(nc<MAXWORD),这个程序将对相应的单词长度计数器加1(++wl[nc])。如果单词的长度超出了允许的单词最大长度(nc>=MAXWORD),这个程序将对变量ovflow加1以记录长度大于或等于MAXWORD的单词的个数。
在读入全部单词之后,我们的程序将找出数字wl中的最大值(maxvalue)。
变量len是根据MAXHIST和maxvalue的值计算得出的wl[i]所对应的直方图长度。如果wl[i]大于零,就至少要打印出一个星号。
ChapterOneExerciseThirteenTwo.cpp
cpp
#include <stdio.h>
#define MAXHIST 15 /* max length of histogram */
#define MAXWORD 11 /* max lenth of a word */
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* print vertical histogram */
main()
{
int c, i, j, nc, state;
int maxvalue; /* maximum value for wl[] */
int ovflow; /* number of overflow words */
int wl[MAXWORD]; /* word length counters */
state = OUT;
nc = 0; /* number of chars in a word */
ovflow = 0; /* number of words >= MAXWORD */
for(i = 0; i < MAXWORD; ++i)
wl[i] = 0;
while((c = getchar()) != EOF){
if(c == ' ' || c == '\n' || c == '\t'){
state = OUT;
if(nc > 0)
if(nc < MAXWORD)
++wl[nc];
else
++ovflow;
nc = 0;
}else if(state == OUT){
state = IN;
nc = 1; /* beginning of a new word */
}else
++nc; /* inside a word */
}
maxvalue = 0;
for(i = 1; i < MAXWORD; ++i)
if(wl[i] > maxvalue)
maxvalue = wl[i];
for(i = MAXHIST; i > 0; --i){
for(j = 1; j < MAXWORD; ++j){
if(wl[j] * MAXHIST / maxvalue >= i)
printf(" * ");
else
printf(" ");
}
putchar('\n');
}
for(i = 1; i < MAXWORD; ++i)
printf("%4d ", i);
putchar('\n');
for(i = 1; i < MAXWORD; ++i)
printf("%4d ", wl[i]);
putchar('\n');
if(ovflow > 0)
printf("There are %d words >= %d\n", ovflow, MAXWORD);
}
这个实现方法将输出一个垂直方向的直方图。这个程序从开始直到求值maxvalue的过程与前一个程序完全相同。然后,这个程序需要计算数组wl中的每一个元素并判断是否需要在数组元素的对应位置上打印一个星号。这一判断过程必不可少,因为垂直方向直方图的所有直方图是同步打印的。最后的两个for循环用来输出数组wl各元素的下标和取值。