简体   繁体   English

C中的字符串反转:我做错了什么?

[英]String reversal in C: What is it I am doing wrong?

I am amidst reading K&R C, mainly to brush my C skills, and while attempting to code a program to reverse a given string, and I have a bug that plagues, which, worst of all, I am unable to debug - nor have a clue what might be the cause of it. 我正在阅读K&R C,主要是为了刷我的C技能,并且在尝试编写程序来反转给定的字符串时,我有一个困扰的错误, 最糟糕的是,我无法调试 - 也没有可能是什么原因造成的。

My code is the following: 我的代码如下:

#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;
}

(Please forgive the debug statements that litter the code logic. Apart from that, feel free to correct any mistake you might see, and also feel free to make suggestions to improve it) (请原谅那些乱丢代码逻辑的调试语句。除此之外,请随时纠正您可能看到的任何错误,并随时提出建议以改进它)

Now, my code is working (for the most part) but the bug is that it copies characters that I have not input. 现在,我的代码正在工作(大部分),但错误是它复制了我没有输入的字符。 Below are the (funny) results of two test runs: 以下是两次测试运行的(有趣)结果:

The first one: 第一个:

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

(Notice the $ ) (注意$

and the second one: 第二个:

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

More accurately depicted here: 这里更准确地描述:

错误

Could someone more knowledgeable and experienced than me explain to me what's wrong with my code, or maybe give me a hint as to why I am facing this frustrating bug? 有没有比我更有知识和经验的人向我解释我的代码有什么问题,或者可能会给我一个暗示,为什么我面对这个令人沮丧的错误?

You are returning a local variable: 您正在返回一个局部变量:

char * reverse(char string[]) {    
  char reversed[size + 1];
  ....
  return reversed;
}

The local variable reversed which was allocated on the stack, ceases to exist once the function reverse returns. 在堆栈上分配的局部变量reversed ,一旦函数reverse返回就不再存在。 So any reference to it from main leads to undefined behavior. 所以从main引用它会导致未定义的行为。

To fix this you can do either of the following: 要解决此问题,您可以执行以下任一操作:

  1. Make the function void and modify the input array. 使函数为void并修改输入数组。

  2. Declare the array reversed as static so that its lifetime changes to the lifetime of the program. 声明数组reversed为静态,使得其寿命更改程序的生命周期。

  3. Dynamically allocate (and later de-allocate) reversed 动态分配(以及后来取消分配) reversed

Always the very same errors, over and over... 总是一样的错误,一遍又一遍......

I. 一世。

char reversed[size + 1];
// ...
return reversed;

You're returning an automatic array, which is out of scope as soon as the function returns - undefined behavior. 您将返回一个自动数组,该函数在函数返回时超出范围 - 未定义的行为。 Make reversed a static variable to avoid this (then read up on the static keyword before you start to believe it's magic). 使reversed一个static变量以避免这种情况(然后在你开始相信它的魔力之前读取static关键字)。

II. II。

char string[256];
scanf("%s", string);

Potential buffer overrun and bug when entering strings with spaces in them. 输入带有空格的字符串时可能存在缓冲区溢出和错误。 Change this to 将此更改为

fgets(string, sizeof(string), stdin);

III. III。

char reversed[size + 1];
// ...
reversed[size + 1] = '\0';

Another buffer overrun. 另一个缓冲区溢出。 In C, arrays are indexed from 0. 在C中,数组从0开始索引。


Time to read a good C book. 是时候读一本好的C书了。

Besides codaddict's post and H2CO3's nice explanation, you have one more error: 除了codaddict的帖子和H2CO3的漂亮解释,你还有一个错误:

 char reversed[size + 1];
 reversed[size + 1] = '\0';

this will result in index of out bound. 这将导致出界索引。 say size = 10 , then size +1 =11 . size = 10 ,然后size +1 =11 index values of char array reversed are 0,1,2,3,...,10 . reversed的char数组的索引值是0,1,2,3,...,10 Therefore, reversed[11] will be get you in trouble. 因此, reversed[11]会让你陷入困境。

Okay, annotated with the errors found above plus my own answer: 好的,注释上面发现的错误加上我自己的答案:

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM