2013-11-22 191 views
4

我正在編寫一個程序,它將一些文件作爲參數並打印所有反轉的行。問題是,我得到意想不到的結果:打印一個字符串反轉C

如果我把它應用到一個文件包含以下行

one 
two 
three 
four 

我得到預期的結果,但是如果文件中包含

september 
november 
december 

它返回

rebmetpes 
rebmevons 
rebmeceds 

而且我不明白爲什麼它在末尾添加了「s」

這裏是我的代碼

#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

void reverse(char *word); 

int main(int argc, char *argv[], char*envp[]) { 
    /* No arguments */ 
    if (argc == 1) { 
     return (0); 
    } 

    FILE *fp; 

    int i; 
    for (i = 1; i < argc; i++) { 
     fp = fopen(argv[i],"r"); // read mode 

     if(fp == NULL) 
     { 
      fprintf(stderr, "Error, no file"); 
     } 

     else 
     { 
      char line [2048]; 
/*read line and reverse it. the function reverse it prints it*/ 
      while (fgets(line, sizeof line, fp) != NULL) 
       reverse(line); 
     } 
     fclose(fp); 
    } 

    return (0); 
} 

void reverse(char *word) 
{ 
    char *aux; 
    aux = word; 
    /* Store the length of the word passed as parameter */ 
    int longitud; 
    longitud = (int) strlen(aux); 

    /* Allocate memory enough ??? */ 
    char *res = malloc(longitud * sizeof(char)); 

    int i; 

    /in this loop i copy the string reversed into a new one 
    for (i = 0; i < longitud-1; i++) 
    { 
     res[i] = word[longitud - 2 - i]; 
    } 

    fprintf(stdout, "%s\n", res); 
    free(res); 
} 

(注意:一些代碼已被刪除,爲了清晰,但它應該編譯)

+0

當你malloc爲字符串,使用strlen()測量長度時,你需要爲NULL終止符+1。 – moeCake

回答

4

你忘了\0符,終止您的字符串。在反轉字符串\0成爲您反轉字符串的第一個字符。首先分配內存的一個或多個字符比你分配

char *res = malloc(longitud * sizeof(char) + 1); 

而且試試這個

for (i = 0; i < longitud-1; i++) 
{ 
    res[i] = word[longitud - 2 - i]; 
} 
res[i] = '\0'; // Terminating string with '\0' 
+0

是的,但'strlen'給你的長度沒有尾隨零,所以你應該'malloc(longitudinal + 1)'爲''\ 0''留出空間。 ('sizeof(char)'保證是1.)或者,你可以在格式字符串中使用精度修飾符來寫出最多'縱向'字符,如下所示:'printf(「%。* s \ n」,縱向 - 1,res);' –

+0

@Meehm;我錯過了'char * res = malloc(longitudinal * sizeof(char));'line。添加到我的答案。 – haccks

1

我想我知道的問題,這是一個有點怪異的問題。

C中的字符串是零終止的。這意味着字符串「Hi!」在內存中實際上表示爲'H','i','!','\0'strlen等方式知道字符串的長度是通過從零終止符之前的第一個字符開始計算字符數。同樣,打印字符串時,fprintf將打印所有字符,直到它達到零終止符。

問題是,您的reverse函數永遠不會在最後設置零終止符,因爲您需要逐字符地將字符複製到緩衝區中,因此需要這樣做。這意味着它會在分配的緩衝區結束時運行,並進入未定義的內存,當您點擊它時恰好爲零(malloc沒有對您分配的緩衝區的內容做出承諾,只是說它足夠大)。你應該在Windows上得到不同的行爲,因爲我相信在調試模式下,malloc將所有緩衝區初始化爲0xcccccccc。

因此,發生了什麼事是你複製九月,逆轉,到res。如你所見,這是有效的,因爲它恰好在最後有一個零。

然後您再免費res,然後malloc它。再次,偶然(因爲在malloc中有一些聰明),你會得到相同的緩衝區,它已經包含「rebmetpes」。然後你把「11月」放進去,倒過來,稍微短一點,因此你的緩衝區現在包含「rebmevons」。

那麼,修復?也分配另一個字符,這將保持您的零終止符(char *res = malloc(longitud * sizeof(char) + 1);)。反轉字符串後,在字符串末尾設置零終止符(res[longitud] = '\0';)。

1

有兩個錯誤出現,第一個是,你需要一個字符更多分配(所有字符的字符串+ 1終止)

char *res = malloc((longitud+1) * sizeof(char)); 

第二個是,你必須終止字符串:

res[longitud]='\0'; 

您可以在進入循環之前終止字符串,因爲您已知道目標字符串的大小。

注意,使用的calloc代替malloc你不會需要終止字符串作爲存儲器得到alreay零初始化

0

謝謝,它解決了我的問題。我在字符串中讀了一些關於「\ 0」的內容,但不是很清楚,現在閱讀所有答案後(都很好)。謝謝大家的幫助。