1-13
先放上自己写的程序,不论是打印水平方向的直方图还是垂直方向的直方图,前提都是先得到单词的长度,然后将该长度在数组nlenth[]对应的元素加1,也就说统计不同长度出现的次数。
1 #include<stdio.h> 2 3 #define IN 1 4 #define OUT 0 5 #define MAXSIZE 10 6 7 /* 16/06/09 打印输入中单词长度的直方图 */ 8 main() 9 { 10 char state = OUT; 11 char c,i; 12 int nlength[MAXSIZE]; 13 char nword = 0; 14 15 for (i = 0; i < MAXSIZE; i++) { 16 nlength[i] = 0; 17 } 18 while ((c = getchar()) != EOF) { 19 if (c == ‘ ‘ || c == ‘\t‘ || c == ‘\n‘) { 20 state = OUT; 21 } 22 else if (state == OUT) { 23 state = IN; 24 } 25 while (state == IN) { 26 nword++; 27 c = getchar(); 28 if (c == ‘ ‘ || c == ‘\t‘ || c == ‘\n‘) { 29 state = OUT; 30 nlength[nword]++; 31 nword = 0; 32 } 33 } 34 } 35 /* 绘制水平方向直方图 */ 36 /* 37 for (i = 0; i < MAXSIZE; i++) { 38 printf("%d ", i); 39 for (j = 0; j < nlength[i]; j++) { 40 putchar(‘*‘); 41 } 42 putchar(‘\n‘); 43 } 44 */ 45 /* 绘制垂直方向直方图,思路仍是一行行输出 */ 46 int ncopy[MAXSIZE]; 47 int ln, k, kmax; 48 /* 下面这一段代码是求数组nlength[]中的最大值 */ 49 for (ln = sizeof(nlength) / sizeof(int), k = kmax = 0; k < ln; k++) { 50 if (nlength[kmax] < nlength[k]) 51 kmax = k; 52 } 53 for (i = 0; i < MAXSIZE; i++) { 54 ncopy[i] = nlength[i]; 55 printf("%d ", i); 56 } 57 putchar(‘\n‘); 58 for (k = 0; k < kmax; k++) { 59 for (i = 0; i < MAXSIZE; i++) { 60 if (ncopy[i] > 0) { 61 putchar(‘*‘); 62 putchar(‘ ‘); 63 ncopy[i]--; 64 } 65 else { 66 putchar(‘ ‘); 67 putchar(‘ ‘); 68 } 69 } 70 putchar(‘\n‘); 71 } 72 73 }
1-13.c
打印水平方向的直方图容易点,运行结果如下(注意输入完毕后先Enter再Ctrl+Z)
接下来是绘制垂直方向的直方图,写的稍微费事了一些,思路是先找到数组nlength[]中的最大值,在一次性输出0-9的过程中将数组nlength复制到另一个数组ncopy(否则后面的自减会丢失),然后根据相应数目输出*。
答案的前提和我的相同,也需要统计不同长度出现的次数,不过引入了overflow来统计超出允许最大长度的单词个数。
对于水平直方图(程序为1-13-a1.c),答案额外写了一段代码来找到统计到的长度数值中的最大值,以此来计算wl[i]对应的直方图长度(我的是有多少就输出多少*),计算公式是len=wl[i]*MAXHIST/maxvalue,我觉得采取这个公式只是起到计算的作用,没有特殊意义。
1 #include<stdio.h> 2 3 #define IN 1 4 #define OUT 0 5 #define MAXSIZE 10 6 #define MAXHIST 15 7 8 /* 16/06/15 打印输入单词长度的水平直方图 */ 9 main() 10 { 11 char state = OUT; 12 char c, i; 13 int nlength[MAXSIZE]; 14 int len; 15 int nc, overflow; 16 int maxvalue; 17 18 nc = 0; 19 overflow = 0; 20 for (i = 0; i < MAXSIZE; i++) { 21 nlength[i] = 0; 22 } 23 while ((c = getchar()) != EOF) { 24 if (c == ‘ ‘ || c == ‘\t‘ || c == ‘\n‘) { 25 state = OUT; 26 if (nc > 0) { 27 if (nc<MAXSIZE) 28 ++nlength[nc]; 29 else ++overflow; 30 } 31 nc = 0; 32 } 33 else if (state == OUT) { 34 state = IN; 35 nc = 1; 36 } 37 else nc++; 38 } 39 /* 绘制水平方向直方图 */ 40 maxvalue = 0; 41 for (i = 1; i < MAXSIZE; i++) { 42 if (maxvalue < nlength[i]) 43 maxvalue = nlength[i]; 44 } 45 for (i = 1; i < MAXSIZE; i++) { 46 printf("%d - %d : ", i, nlength[i]); 47 if (nlength[i] > 0) { 48 if ((len = nlength[i] * MAXHIST / maxvalue) <= 0) 49 len = 1; 50 } 51 else len = 0; 52 while (len--) 53 putchar(‘*‘); 54 putchar(‘\n‘); 55 } 56 if (overflow > 0) 57 printf("There are %d words >= %d\n", overflow, MAXSIZE); 58 59 }
1-13-a1.c
运行效果如下:
1-13-a2是绘制垂直直方图,
1 #include<stdio.h> 2 3 #define IN 1 4 #define OUT 0 5 #define MAXSIZE 10 6 #define MAXHIST 15 7 8 /* 16/06/15 打印输入单词长度的垂直直方图 */ 9 main() 10 { 11 char state = OUT; 12 char c, i, j; 13 int nlength[MAXSIZE]; 14 int nc, overflow; 15 int maxvalue; 16 17 nc = 0; 18 overflow = 0; 19 for (i = 0; i < MAXSIZE; i++) { 20 nlength[i] = 0; 21 } 22 while ((c = getchar()) != EOF) { 23 if (c == ‘ ‘ || c == ‘\t‘ || c == ‘\n‘) { 24 state = OUT; 25 if (nc > 0) { 26 if (nc<MAXSIZE) 27 ++nlength[nc]; 28 else ++overflow; 29 } 30 nc = 0; 31 } 32 else if (state == OUT) { 33 state = IN; 34 nc = 1; 35 } 36 else nc++; 37 } 38 /* 绘制水平方向直方图 */ 39 maxvalue = 0; 40 for (i = 1; i < MAXSIZE; i++) { 41 if (maxvalue < nlength[i]) 42 maxvalue = nlength[i]; 43 } 44 for (i = MAXHIST; i > 0; i--) { //之所以是从MAXHIST开始是为了从底部开始显示*,看一下运行结果就知道了 45 for (j = 1; j < MAXSIZE; j++) { 46 if ((nlength[j] * MAXHIST / maxvalue) >= i) 47 printf(" * "); 48 else 49 printf(" "); 50 51 } 52 putchar(‘\n‘); //注意这一句是必须写的 53 } 54 for (i = 1; i < MAXSIZE; i++) 55 printf(" %d ", i); 56 putchar(‘\n‘); 57 for (i = 1; i < MAXSIZE; i++) 58 printf(" %d ", nlength[i]); 59 putchar(‘\n‘); 60 if (overflow > 0) 61 printf("There are %d words >= %d\n", overflow, MAXSIZE); 62 63 }
1-13-a2.c
运行效果如下,
1-14
我仅仅是在教材P15例程基础上稍作改动,根据统计到的ndigit[i]、nwhite、nother打印相应数目的*,
1 #include<stdio.h> 2 3 /* 16/06/09 打印输入中各个字符出现频度的直方图 */ 4 main() 5 { 6 char c, i, j,nwhite, nother; 7 int ndigit[10]; 8 9 nwhite = nother = 0; 10 for (i = 0; i < 10; i++) { 11 ndigit[i] = 0; 12 } 13 while ((c = getchar()) != EOF) { 14 if (c >= ‘0‘&&c <= ‘9‘) 15 ++ndigit[c - ‘0‘]; 16 else if (c == ‘ ‘ || c == ‘\t‘ || c == ‘\n‘) 17 ++nwhite; 18 else ++nother; 19 } 20 /* 绘制水平方向直方图 */ 21 for (i = 0; i < 10; i++) { 22 printf("%d ", i); 23 for (j = 0; j < ndigit[i]; j++) { 24 putchar(‘*‘); 25 } 26 putchar(‘\n‘); 27 } 28 29 printf("white "); 30 for (i = 0; i < nwhite; i++) putchar(‘*‘); 31 putchar(‘\n‘); 32 33 printf("other "); 34 for (i = 0; i < nother; i++) putchar(‘*‘); 35 putchar(‘\n‘); 36 37 }
1-14.c
答案能够处理的字符是ASCII字符集范围内的字符,因而设置了#define MAXCHAR 128,在这个宏定义的范围内,++cc[c]。
1 #include<stdio.h> 2 #include<ctype.h> 3 4 #define MAXCHAR 128 5 #define MAXHIST 15 6 7 /* 16/06/15 打印输入中各个字符出现频度的直方图 */ 8 main() 9 { 10 int c, i; 11 int len; 12 int maxvalue; 13 int cc[MAXCHAR]; 14 15 for (i = 1; i < MAXCHAR; i++) { 16 cc[i] = 0; 17 } 18 while ((c = getchar()) != EOF) { 19 if (c < MAXCHAR) { 20 ++cc[c]; 21 } 22 } 23 /* 绘制水平方向直方图 */ 24 maxvalue = 0; 25 for (i = 1; i < MAXCHAR; i++) { 26 if (maxvalue < cc[i]) 27 maxvalue = cc[i]; 28 } 29 for (i = 1; i < MAXCHAR; i++) { 30 if (isprint(i)) 31 printf("%5d - %c - %5d : ", i, i, cc[i]); 32 else 33 printf("%5d - - %5d : ", i, cc[i]); 34 len = cc[i]; //还是直接让len=cc[i],好理解一些,下面的代码也只是输出cc[i]的倍数而已 35 /* 36 if (cc[i] > 0) { 37 if ((len = cc[i] * MAXCHAR / maxvalue) <= 0) 38 len = 1; 39 } 40 else len = 0; 41 */ 42 while (len > 0) { 43 putchar(‘*‘); 44 --len; 45 } 46 putchar(‘\n‘); 47 } 48 49 }
1-14-a.c
注意后面的输出格式设置,如果是ASCII字符集范围内的字符就显示出来,否则打印空白,
1 if (isprint(i)) 2 printf("%5d - %c - %5d : ", i, i, cc[i]); 3 else 4 printf("%5d - - %5d : ", i, cc[i]);
运行结果如下
1-15
比较简单,但是我的程序比较糟糕的一点是在函数Fahr_to_Cel内使用了printf,感觉独立性差了点,
1 #include<stdio.h> 2 3 #define LOWER 0 4 #define UPPER 300 5 #define STEP 20 6 7 void Fahr_to_Cel(int lower, int upper, int step); 8 9 /* 16/06/09 温度转换程序 */ 10 main() 11 { 12 Fahr_to_Cel(LOWER, UPPER, STEP); 13 } 14 15 void Fahr_to_Cel(int lower, int upper, int step) 16 { 17 int fahr, celsius; 18 19 for (fahr = lower; fahr <= upper; fahr += step) { 20 celsius = 5 * (fahr - 32) / 9; 21 printf("%d\t%d\n", fahr, celsius); 22 } 23 }
1-15.c
下面给出参考答案程序,
1 #include<stdio.h> 2 3 #define LOWER 0 4 #define UPPER 300 5 #define STEP 20 6 7 float Fahr_to_Cel(float fahr); 8 9 /* 16/06/15 温度转换程序 */ 10 main() 11 { 12 float fahr; 13 for (fahr = LOWER; fahr < UPPER; fahr += STEP) { 14 printf("%3.0f %6.1f\n",fahr,Fahr_to_Cel(fahr)); 15 } 16 } 17 18 float Fahr_to_Cel(float fahr) 19 { 20 return (5.0 / 9.0)*(fahr - 32.0); 21 }
1-15-a.c