有谁知道为什么以下代码会引发访问冲突写入异常?
void squeeze_c(char s[], int c)
{
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
{
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
}
我将该函数调用如下:
squeeze_c("Test", 's');
答案 0 :(得分:1)
该代码没有任何内在错误,因此它归结为两种可能性(可能更多,但这些是我经验中最常见的)。
您传递的是非字符串,但未以\0
字符终止。
您正在传递一个字符串 literal,您不允许修改的内容。
既然您已经明确表示您使用
squeeze_c("Test", 's');
进行了调用,则上面的第二点是正确的。
前者是你做的事情:
char str[] = {'n','o',' ','n','u','l',' ','h','e','r','e'};
你可以通过简单地确定最后一个\0
来解决这个问题。
后者是你做的事情之一:
squeeze_c("this is a literal", 'l');
或:
char *xyzzy = "another literal";
squeeze_c(xyzzy, 'l');
您可以通过确保您拥有文字的可写副本来修复 ,例如:
char xyzzy[] = "another literal";
squeeze_c(xyzzy, 'l');
你真的没有想要在内循环中添加\0
,因为它可能会损坏你的源代码串。
考虑您是否使用:
char xyzzy[] = "paxdiablo";
squeeze_c (xyzzy, 'd');
第一次循环播放时,您将用自己覆盖p
,然后用a
覆盖\0
。然后你&# 39; ll退出循环,因为在索引i
找到的下一个字符将是你刚写入字符串的\0
。
所以它不会删除所有d
个字符,因为将整个字符串截断为一个长度。
void squeeze_c(char *s, int c) {
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0'; // moved outside the loop
}
这会将字符串转换为如下(|
代表\0
):
paxdiablo| original string
paxdiablo| copy p over p
paxdiablo| copy a over a
paxdiablo| copy x over x
paxdiablo| no copy, j now one less than i
paxiiablo| copy i over d
paxiaablo| copy a over i
paxiabblo| copy b over a
paxiabllo| copy l over b
paxiabloo| copy o over l
paxiablo|| final placement of \0