由于第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,这显然是不符合我们期望的。因此我