由於第3章第一題網上有很多種非常優秀的解法,我就不貼出來了,大家不妨自己探索。 練習3-2 編寫一個函數escape(s,t),將字元串t複製到字元串s中,併在複製過程中將換行符、製表符等不可見字元分別轉換成'\n'、'\t'等相應的可見的轉義字元序列。要求使用switch語句。再編寫一個具有相反功 ...
由於第3章第一題網上有很多種非常優秀的解法,我就不貼出來了,大家不妨自己探索。
練習3-2 編寫一個函數escape(s,t),將字元串t複製到字元串s中,併在複製過程中將換行符、製表符等不可見字元分別轉換成'\n'、'\t'等相應的可見的轉義字元序列。要求使用switch語句。再編寫一個具有相反功能的函數,在複製過程將轉義字元序列轉換成實際字元。
先解釋一下兩個run函數和兩個escape分別實現上述兩個功能:
1 #include <stdio.h> 2 3 void escape(char s[], char t[]); 4 void escape2(char s[], char t[]); 5 6 void runEscape() { 7 char testT[100] = "Hello,\ni am a\nGOOD\tBOY\t!!!!\n"; 8 char testS[100] = "Bye,\t littal Max!\n"; 9 10 printf("T:%sS:%s", testT, testS); 11 escape(testS, testT); 12 printf("Now,"); 13 printf("T:%sS:%s", testT, testS); 14 } 15 void runEscape2() { 16 char testS[100] = "Hello,\ni am a\nGOOD\tBOY\t!!!!\n"; 17 char testT[100] = "Bye,\t littal Max!\n"; 18 19 printf("T:%sS:%s", testT, testS); 20 escape2(testS, testT); 21 printf("Now,"); 22 printf("T:%sS:%s", testT, testS); 23 } 24 void escape(char s[], char t[]) { 25 int i = 0; 26 int j = 0; 27 28 while (t[i] != '\0') { 29 switch (t[i]) 30 { 31 case '\t': 32 s[j++] = '\\';s[j++] = 't'; 33 break; 34 case '\n': 35 s[j++] = '\\'; s[j++] = 'n'; 36 break; 37 default: 38 s[j++] = t[i]; 39 break; 40 } 41 42 i++; 43 } 44 s[j] = '\0'; 45 } 46 void escape2(char s[], char t[]) { 47 int i = 0; 48 int j = 0; 49 50 while (t[i] != '\0') { 51 if (t[i]=='\\') 52 { 53 switch (t[i+1]) 54 { 55 case 't': 56 s[j++] = '\t'; i++; 57 break; 58 case 'n': 59 s[j++] = '\n'; i++; 60 break; 61 default: 62 s[j++] = t[i]; 63 break; 64 } 65 } 66 else 67 s[j++] = t[i]; 68 i++; 69 } 70 s[j] = '\0'; 71 }
練習3-3 編寫函數expand(s1,s2),將字元串s1中類似於a-z一類的速記符號在字元串s2中擴展為等價多的完整列表abc...xyz。該函數可以處理大小寫字母和數字,並可以處理a-b-c、a-z0-9與-a-z等類似情況。作為前導和尾隨的-字元原樣排印。
1 #include <stdio.h> 2 3 void expand(char s1[], char s2[]); 4 5 void runExpand() { 6 char testS[100] = "0-9\na-z\nA-Z\na-b-c\na-a\na-Z\n"; 7 char testT[100] = "Bye, littal Tester!\n"; 8 9 printf("T:%sS:%s", testT, testS); 10 expand(testS, testT); 11 printf("\nNow,\n"); 12 printf("T:%sS:%s", testT, testS); 13 } 14 15 16 void expand(char s1[], char s2[]) { 17 int i = 0; 18 int j = 0; 19 20 while (s1[i] != '\0') { 21 if (s1[i] == '-'&&s1[i + 1] != '\0' && i > 0) { 22 char head = s1[i - 1]; 23 char tail = s1[i + 1]; 24 25 if ('a' <= head&&head <= 'z'&&head < tail 26 &&'a' <= tail&&tail <= 'z') { 27 for (; head + 1 <= tail;) { 28 s2[j++] = head + 1; 29 head++; 30 } 31 } 32 else if ('A' <= head&&head <= 'Z'&&head < tail 33 &&'A' <= tail&&tail <= 'Z') { 34 for (; head + 1 < tail;) { 35 s2[j++] = head + 1; 36 head++; 37 } 38 } 39 else if ('0' <= head&&head <= '9'&&head < tail 40 &&'0' <= tail&&tail <= '9') { 41 for (; head + 1 < tail;) { 42 s2[j++] = head + 1; 43 head++; 44 } 45 } 46 else 47 s2[j++] = '-'; 48 } 49 else 50 s2[j++] = s1[i]; 51 52 i++; 53 } 54 }
練習3-4 在數的對二補碼表示中,我們編寫的itoa函數不能處理最大的負數,即n等於-2字長-1的情況。請解釋原因。修改該函數,使它在任何機器上運行時都能列印出正確的值。
解釋的原因我寫在註釋代碼裡面了~~
#include <stdio.h> void reverse(char s[]); void itoa(int n, char s[]); void runItoa() { int testn = -1987654321; char test[100]; itoa(testn, test); printf("test:%s", test); } /*不能正確處理最大負數的原因在於其二進位數形式為10000...如果 對其進行n=-n運算,n將變成0,這顯然是不符合我們期望的。因此我 們可以進行檢測,如果它是這個特殊的最大負數則將其變為無符號數。*/ void itoa(int n, char s[]) { int i, sign; sign = n; if (((unsigned)sign << 1) == 0) n = (unsigned)n; else if (sign < 0) n = -n; i = 0; do { s[i++] = n % 10 + '0'; } while ((n /= 10) > 0); if (sign < 0) s[i++] = '-'; s[i] = '\0'; reverse(s); } void reverse(char s[]) { int i = 0; int j = 0; char c[1000]; while (s[i] != '\0') c[i] = s[i++]; while (i > 0) s[j++] = c[--i]; s[j] = '\0'; }
練習3-5 編寫函數itob(n,s,b)將整數n轉換為以b為底的數。 並將轉換結果以字元的形式保存到字元串s中。
#include <stdio.h> void reverse(char s[]); void itob(int n, char s[], int); void runItob() { int testn = 1987654321; char test[100]; itob(testn, test, 10); printf("test:%s", test); } void itob(int n, char s[], int b) { int i = 0; do { s[i++] = n % b + '0'; } while ((n /= b) > 0); s[i] = '\0'; reverse(s); }
練習3-6 修改itoa函數,使得該函數可以接收三個參數。第三個參數為最小欄位寬度。為了保證轉換後結果至少具有第三個參數指定的最小寬度,必要時在結果左邊填充一定的空格。
1 #include <stdio.h> 2 3 void reverse(char s[]); 4 void itoa2(int n, char s[], int width); 5 6 void runItoa2() { 7 int testn = -1987654321; 8 char test[100]; 9 10 itoa2(testn, test,20); 11 printf("test:%send\n", test); 12 } 13 14 void itoa2(int n, char s[], int width) { 15 int i, sign; 16 sign = n; 17 18 if (((unsigned)sign << 1) == 0) 19 n = (unsigned)n; 20 else if (sign < 0) 21 n = -n; 22 i = 0; 23 do { 24 s[i++] = n % 10 + '0'; 25 } while ((n /= 10) > 0); 26 if (sign < 0) 27 s[i++] = '-'; 28 while (width - i > 0) { 29 s[i++] = ' '; 30 } 31 s[i] = '\0'; 32 reverse(s); 33 }