关于Run-Time Check Failure #2

     这个问题源自《The C Programming Language》P49 p3-2习题中,当输入一系列字符串后,再键入Ctrl - Z时,出现了。

   代码:   

main.c
1 #include <stdio.h>
2
3 #define MAXLINE 100
4
5 int getLen(char s[], int lim);
6 char* escape(char t[], char s[]);
7 char* unescape(char t[], char s[]);
8
9 int main()
10 {
11
12 int len = 0;
13 char line[MAXLINE] = {'\0'};
14 char str[MAXLINE] = {'\0'};
15
16 while((len = getLen(line, MAXLINE)) > 0)
17 {
18 printf("%s\n", escape(str, line));
19 printf("%s", unescape(line, str));
20 }
21
22 return 0;
23 }
24
25 int getLen(char s[], int lim) //从终端读入字符存在在s中,返回其长度
26 {
27 int i, c;
28
29 for(i = 0; i < lim-1 && (c = getchar()) != EOF && c != '\n'; ++i)
30 s[i] = c;
31 if(c == '\n')
32 {
33 s[i] = c;
34 ++i;
35 }
36 s[i] = '\0';
37
38 return i;
39 }
40
41 char* escape(char t[], char s[]) //将'\t','\n'转换成可见的转义字符序列
42 {
43
44 int c, i, j;
45
46 i = j = 0;
47 while((c = s[j]) != '\0') //不要写成while((c = s[j]) != EOF)
48 {
49 switch(c)
50 {
51 case '\n':
52 t[i++] = '\\';
53 t[i] = 'n';
54 break;
55
56 case '\t':
57 t[i++] = '\\';
58 t[i] = 't';
59 break;
60
61 default:
62 t[i] = s[j];
63 break;
64 }
65 ++i;
66 ++j;
67 }
68 t[i] = '\0';
69
70 return t;
71
72 }
73
74 char* unescape(char t[], char s[])
75 {
76 int i, j, c;
77
78 i = j = 0;
79 while((c = s[j]) != '\0')
80 {
81 if(s[j] == '\\' && s[j+1] == 't')
82 {
83 t[i] = '\t';
84 ++j;
85 }
86 else if(s[j] == '\\' && s[j+1] == 'n')
87 {
88 t[i] = '\n';
89 ++j;
90 }
91 else
92 t[i] = s[j];
93 ++j;
94 ++i;
95 }
96 t[i] = '\0';
97
98 return t;
99 }
100
101 /******************************************************
102 参考代码1
103 *******************************************************
104 void unescape(char s[], char t[])
105 {
106 int i, j;
107
108 for(i = j = 0; t[i] != '\0'; ++i)
109 if(t[i] != '\\')
110 s[j++] = t[i];
111 else
112 switch(t[++i])
113 {
114 case 'n':
115 s[j++] = '\n';
116 break;
117
118 case 't':
119 s[j++] = '\t';
120 break;
121
122 default:
123 s[j++] = '\\';
124 s[j++] = t[i];
125 break;
126 }
127 s[j] = '\0';
128 }
129
130 /******************************************************
131 参考代码2
132 *******************************************************
133 void unescape(char s[], char t[])
134 {
135 int i, j;
136
137 for(i = j = 0; t[i] != '\0'; ++i)
138 switch(t[i])
139 {
140 case '\\':
141 switch(t[++i])
142 {
143 case 't':
144 s[j++] = '\t';
145 break;
146
147 case 'n':
148 s[j++] = '\n';
149 break
150
151 default:
152 s[j++] = '\\';
153 s[j++] = t[i];
154 break;
155 }
156 break;
157
158 default:
159 s[j++] = t[i];
160 break;
161 }
162 s[j] = '\0';
163 }
164
165 ******************************************************/

     当用L45的注释代替本身的while语句时,出现了上述错误,见下图:

     CRT

     分析:

     1,  这个错误一般是因为给变量分配的空间出现越界访问导致的(绝大部分是数组越界),当L45中的while中的判读条件为:

          (c = s[j]) != EOF时,就会导致这个错误的出现,修改成(c = s[j]) != '/0',则问题解决。

          原因:EOF是文件结尾符,而'/0'是字符串结尾符,例如s = "abdc/0",本来原意是当while循环执行到s[4] = '/0'时,就

          要结束函数escape了,但由于此时判断条件是eof,故当s[j] = '/0',仍然进入while的循环体继续执行里面的语句,这样

          就将s[4]之后的95个'/0'全部都赋给t字符串了,当执行到c = s[99] != EOF时,仍然进入while循环体,导致++j,

          j = 100,然后又调回到while判断条件中执行c = s[100] != EOF,此时问题来了,当执行c = s[100]时,访问字符

          s[100]时,出现了越界情况(s数组的最大访问下标为99),所以出现了上述错误。

posted on 2011-05-10 01:33  将军之盾  阅读(1573)  评论(1编辑  收藏  举报