簡體   English   中英

C中的字符串反轉:我做錯了什么?

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

我正在閱讀K&R C,主要是為了刷我的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

這里更准確地描述:

錯誤

有沒有比我更有知識和經驗的人向我解釋我的代碼有什么問題,或者可能會給我一個暗示,為什么我面對這個令人沮喪的錯誤?

您正在返回一個局部變量:

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

在堆棧上分配的局部變量reversed ,一旦函數reverse返回就不再存在。 所以從main引用它會導致未定義的行為。

要解決此問題,您可以執行以下任一操作:

  1. 使函數為void並修改輸入數組。

  2. 聲明數組reversed為靜態,使得其壽命更改程序的生命周期。

  3. 動態分配(以及后來取消分配) reversed

總是一樣的錯誤,一遍又一遍......

一世。

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書了。

除了codaddict的帖子和H2CO3的漂亮解釋,你還有一個錯誤:

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

這將導致出界索引。 size = 10 ,然后size +1 =11 reversed的char數組的索引值是0,1,2,3,...,10 因此, reversed[11]會讓你陷入困境。

好的,注釋上面發現的錯誤加上我自己的答案:

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