第1章-导言-习题1.13-1.17
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 14 #define OUT 05 #define MAXSIZE 106 #define MAXHIST 157 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 14 #define OUT 05 #define MAXSIZE 106 #define MAXHIST 157 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 1285 #define MAXHIST 156 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?
1-16
①開始思路是將某行的長度與該輸入行放在同一數組line[]里面,然后再接下一行的長度和內容,
1 #include<stdio.h> 2 #define MAXLINE 1000 3 4 int getline(char line[], int maxline,int pos); 5 6 /* 16/06/09 程序的思路是將某行的長度與該行放在一起,后接下一行,存在很大缺陷,輸入某個行的長度不能超過9 */ 7 main() 8 { 9 int c,len; 10 char line[MAXLINE]; 11 int position=0; 12 13 while((c=getchar())!=EOF){ 14 line[position + 2] = c; 15 len = getline(line, MAXLINE, position+3); 16 line[position] = (len-position-3)+'0'; 17 line[position+1] = ' '; 18 position = len; 19 } 20 line[position] = '\0'; 21 printf("%s", line); 22 } 23 24 int getline(char s[], int lim, int pos) 25 { 26 int c, i; 27 for (i = pos; i < lim - 1 && (c = getchar()) != EOF&&c != '\n'; ++i) 28 s[i] = c; 29 if (c == '\n') 30 s[i++] = c; 31 return i; 32 } 1-16.c但是單個輸入行的長度不要超過9,否則該輸入行長度顯示會出錯,原因在于10以上的數字無法用單個ASCII字符表示。
②看來只能將長度與數據分開存放了,運行結果如下,重要的地方已在程序注釋。
1 #include<stdio.h> 2 #define MAXLINE 1000 3 4 int getline(char line[], int maxline, int pos); 5 6 /* 16/06/09 程序的思路是將某行的長度與該行內容分開存放在不同數組line_num與line_dat */ 7 main() 8 { 9 int c, len; 10 int i = 0, j = 0; 11 char line_dat[MAXLINE]; 12 char line_num[MAXLINE]; 13 int position = 0; 14 15 /* 下面的代碼段將輸入文本的內容保存在同一個數組line_dat里面,回車用\n取代 */ 16 while ((c = getchar()) != EOF) { 17 line_dat[position] = c; //這一句是有必要的,否則頭字母丟失 18 len = getline(line_dat, MAXLINE, position + 1); //從該行的第二個字母開始判斷 19 line_num[i++] = len-position-1; //保存該行的長度 20 position = len; 21 } 22 line_dat[position] = '\0'; //整個文本輸入完畢后,在保存數據的字組line_dat末尾加入\0表征字符串的結尾 23 i = 0; 24 /* 下面的代碼段先輸出某行的長度,再輸出該行的內容 */ 25 while( i < MAXLINE&&line_dat[i] != '\0') { 26 printf("%d\t", line_num[j++]); 27 for (; line_dat[i] != '\n'; i++) { 28 putchar(line_dat[i]); 29 } 30 putchar(line_dat[i++]); 31 } 32 } 33 34 int getline(char s[], int lim, int pos) 35 { 36 int c, i; 37 for (i = pos; i < lim - 1 && (c = getchar()) != EOF&&c != '\n'; ++i) 38 s[i] = c; 39 if (c == '\n') 40 s[i++] = c; 41 return i; 42 } 1-16-2.c③前面兩個程序均是在主函數main()內部借助c = getchar()) != EOF來判斷是否達到文本流結尾,其實完全可以直接借助getline函數來判斷(如果到達文本流結尾就返回-1),這樣會使程序簡化一些。
1 #include<stdio.h> 2 #define MAXLINE 1000 3 4 int getline(char line[], int maxline, int pos); 5 6 /* 16/06/10 寫完1-18-2,回頭改寫了1-16-2,運行正常 */ 7 main() 8 { 9 int len; 10 int i = 0, j = 0; 11 char line_dat[MAXLINE]; 12 char line_num[MAXLINE]; 13 int position = 0; 14 15 /* 下面的代碼段將輸入文本的內容保存在同一個數組line_dat里面,回車用\n取代 */ 16 while ((len = getline(line_dat, MAXLINE, position)) >0) { 17 line_num[i++] = len - position - 1; //保存該行的長度 18 position = len; 19 } 20 line_dat[position] = '\0'; //整個文本輸入完畢后,在保存數據的字組line_dat末尾加入\0表征字符串的結尾 21 i = 0; 22 /* 下面的代碼段先輸出某行的長度,再輸出該行的內容 */ 23 while (i < MAXLINE&&line_dat[i] != '\0') { 24 printf("%d\t", line_num[j++]); 25 for (; line_dat[i] != '\n'; i++) { 26 putchar(line_dat[i]); 27 } 28 putchar(line_dat[i++]); 29 } 30 } 31 32 int getline(char s[], int lim, int pos) 33 { 34 int c, i; 35 for (i = pos; i < lim - 1 && (c = getchar()) != EOF&&c != '\n'; ++i) 36 s[i] = c; 37 if (c == EOF) return -1; 38 if (c == '\n') 39 s[i++] = c; 40 return i; 41 } 1-16-3.c答案主要在教材【P21】的例程基礎上對函數getline進行了修改,刪除了i<lim-1,并加入if(i<lim-2)條件判斷。答案是以每個輸入行為單位一行一行地輸出,無法像我的程序那樣處理多行。
1 #include<stdio.h> 2 #define MAXLINE 1000 3 4 int getline(char s[], int lim); 5 6 /* 16/06/15 是以每個輸入行為單位一行一行地輸出,無法像我的程序那樣處理多行 */ 7 main() 8 { 9 int len; 10 int i = 0, j = 0; 11 char line_dat[MAXLINE]; 12 13 /* 下面的代碼段將輸入文本的內容保存在同一個數組line_dat里面,回車用\n取代 */ 14 while ((len = getline(line_dat, MAXLINE)) >0) { 15 printf("%d, %s", len, line_dat); 16 } 17 return 0; 18 } 19 20 int getline(char s[], int lim) 21 { 22 int c, i; 23 24 for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) { 25 if (i < lim - 2) { 26 s[i] = c; 27 } 28 } 29 if (c == '\n') { 30 s[i] = c; 31 i++; 32 } 33 s[i] = '\0'; 34 return i; 35 } 1-16-a.c答案運行結果如下
注意對于超過1000的輸入,運行結果如下(一行為120個字符,共10行),可以看出能輸出正確數目,但是不會輸出完整的尾部內容。
?
?1-17
在1-16-2.c基礎上稍作修改即可,這里是設定打印長度大于10個字符的所有輸入行。
1 #include<stdio.h> 2 #define MAXLINE 1000 3 4 int getline(char line[], int maxline, int pos); 5 6 /* 16/06/09 打印長度大于10個字符的所有輸入行,在1-16-2.c基礎上修改 */ 7 main() 8 { 9 int c, len; 10 int i = 0, j = 0; 11 char line_dat[MAXLINE]; 12 char line_num[MAXLINE]; 13 int position = 0; 14 15 while ((c = getchar()) != EOF) { 16 line_dat[position] = c; 17 len = getline(line_dat, MAXLINE, position + 1); 18 line_num[i++] = len - position - 1; 19 position = len; 20 } 21 line_dat[position] = '\0'; 22 i = 0; 23 /* 下面是修改部分 */ 24 while (i < MAXLINE&&line_dat[i] != '\0') { 25 if (line_num[j]>10) { 26 printf("%d\t", line_num[j++]); 27 for (; line_dat[i] != '\n'; i++) { 28 putchar(line_dat[i]); 29 } 30 putchar(line_dat[i++]); 31 } 32 else { 33 j++; 34 while (line_dat[i++] != '\n'); 35 } 36 } 37 } 38 39 int getline(char s[], int lim, int pos) 40 { 41 int c, i; 42 for (i = pos; i < lim - 1 && (c = getchar()) != EOF&&c != '\n'; ++i) 43 s[i] = c; 44 if (c == '\n') 45 s[i++] = c; 46 return i; 47 } 1-17.c答案是在1-16-a.c的基礎上加入長度條件判斷if(len>LONGLINE)即可。
1 #define LONGLIEN 80 2 ... 3 main(){ 4 ... 5 while ((len = getline(line_dat, MAXLINE)) >0) { 6 if(len>LONGLINE) 7 printf("%d, %s", len, line_dat); 8 } 9 }?
轉載于:https://www.cnblogs.com/custalex/p/5722699.html
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的第1章-导言-习题1.13-1.17的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用PHP实现单向链表
- 下一篇: UIButton中的三个UIEdgeIn