我正在读K& RC,主要是为了刷我的C技能,并且在尝试编写一个程序来反转给定的字符串时,我有一个困扰的错误,其中,最糟糕的是,我是无法调试 - 也不知道可能是什么原因。
我的代码如下:
#include <stdio.h>
#include <string.h>
char * reverse(char *string);
int main(int argc, char *argv[])
{
printf("Please input a string: \t");
char string[256];
scanf("%s", string);
char *reversed = reverse(string);
printf("The reversed string is %s\n", reversed);
return 0;
}
char * reverse(char string[])
{
int size = strlen(string);
printf("DEBUG: The size of the string that we got as input was: %d\n", size);
int counter;
char reversed[size + 1];
for(counter = size - 1; counter >= 0; counter--) {
reversed[size - counter] = string[counter];
printf("DEBUG: The character copied now was %c and was at index %d\n", string[counter], counter);
}
reversed[size + 1] = '\0';
printf("DEBUG: The reversed string is %s\n", reversed);
return reversed;
}
(请原谅那些乱丢代码逻辑的调试语句。除此之外,请随时纠正您可能看到的任何错误,并随时提出建议以改进它)
现在,我的代码正在运行(大部分),但错误是它复制了我没有输入的字符。以下是两次测试运行的(有趣)结果:
第一个:
nlightnfotis@crunchbang:~/SoftwareExperiments$ ./reverse
Please input a string: fotis
DEBUG: The size of the string that we got as input was: 5
DEBUG: The character copied now was s and was at index 4
DEBUG: The character copied now was i and was at index 3
DEBUG: The character copied now was t and was at index 2
DEBUG: The character copied now was o and was at index 1
DEBUG: The character copied now was f and was at index 0
DEBUG: The reversed string is $sitof
The reversed string is $sitof
(请注意$
)
和第二个:
nlightnfotis@crunchbang:~/SoftwareExperiments$ ./reverse
Please input a string: lol
DEBUG: The size of the string that we got as input was: 3
DEBUG: The character copied now was l and was at index 2
DEBUG: The character copied now was o and was at index 1
DEBUG: The character copied now was l and was at index 0
DEBUG: The reversed string is lol
The reversed string is lol
这里描述得更准确:
比我更有知识和经验的人可以向我解释我的代码有什么问题,或者可能会给我一个暗示,为什么我面对这个令人沮丧的错误?
答案 0 :(得分:10)
您正在返回一个本地变量:
char * reverse(char string[]) {
char reversed[size + 1];
....
return reversed;
}
在函数reversed
返回后,在堆栈上分配的局部变量reverse
不再存在。因此,main
对它的任何引用都会导致未定义的行为。
要解决此问题,您可以执行以下任一操作:
创建函数void
并修改输入数组。
将数组reversed
声明为静态,以使其生命周期更改为程序的生命周期。
动态分配(以及稍后取消分配)reversed
答案 1 :(得分:8)
总是一样的错误,一遍又一遍......
我
char reversed[size + 1];
// ...
return reversed;
你返回一个自动数组,一旦函数返回就超出范围 - 未定义的行为。将reversed
变为static
变量以避免这种情况(然后在您开始相信它的魔力之前阅读static
关键字。)
II。
char string[256];
scanf("%s", string);
当输入带有空格的字符串时,潜在的缓冲区溢出和错误。将其更改为
fgets(string, sizeof(string), stdin);
III。
char reversed[size + 1];
// ...
reversed[size + 1] = '\0';
另一个缓冲区溢出。在C中,数组从0开始索引。
是时候读一本好的C书了。
答案 2 :(得分:3)
除了codaddict的帖子和H2CO3的好解释之外,还有一个错误:
char reversed[size + 1];
reversed[size + 1] = '\0';
这将导致出界索引。说size = 10
,然后size +1 =11
。 char数组reversed
的索引值是
0,1,2,3,...,10
。因此,reversed[11]
会让您遇到麻烦。
答案 3 :(得分:2)
好的,注释上面发现的错误加上我自己的答案:
char * reverse(char string[])
{
int size = strlen(string);
printf("DEBUG: The size of the string that we got as input was: %d\n", size);
int counter;
/* BUGBUG: You are using a stack variable to store the return string.
* char *reversed = malloc(sizeof(char) * (size + 1))
* to allocate a string that can be returned safely.
*/
char reversed[size + 1];
for(counter = size - 1; counter >= 0; counter--) {
/* BUGBUG: You are setting the wrong char in "reversed", it should be
* reversed[size - 1 - counter]. You want the "size - 1" char from the original
* to be copied to the 0 position of the reversed
*/
reversed[size - counter] = string[counter];
printf("DEBUG: The character copied now was %c and was at index %d\n", string[counter], counter);
}
/* BUGBUG: You are setting the null character one past the end of the string.
* Here you want reversed[size], which with 0-indexing is the size+1'st
* character.
*/
reversed[size + 1] = '\0';
printf("DEBUG: The reversed string is %s\n", reversed);
/* BUGBUG: Just to stress this -- you cannot expect this to work; that it
* does so is accidental because the call stack is not cleaned. If the calling
* function called another function (say printf) then the printf is likely to
* overwrite the contents of reversed.
*/
return reversed;
}