2013-10-27 109 views
2

我正在寫一個簡單的c程序,它反轉了一個字符串,從argv [1]中取出字符串。這裏是代碼:C字符串反轉

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

char* flip_string(char *string){ 
    int i = strlen(string); 
    int j = 0; 

    // Doesn't really matter all I wanted was the same size string for temp. 
    char* temp = string; 
    puts("This is the original string"); 
    puts(string); 
    puts("This is the \"temp\" string"); 
    puts(temp); 

    for(i; i>=0; i--){ 
     temp[j] = string[i] 
     if (j <= strlen(string)) { 
      j++; 
     } 
    } 

    return(temp); 
} 

int main(int argc, char *argv[]){ 
    puts(flip_string(argv[1])); 
    printf("This is the end of the program\n"); 
} 

這基本上就是它,程序編譯和一切,但最終不會返回臨時字符串(只是空白)。在開始時,當它等於字符串時,它會打印出臨時文件。此外,如果我在for循環中通過字符printf of temp來創建正確的臨時字符串,即字符串 - >反轉。正當我試圖將其打印到標準輸出(在for循環之後或在主文件中)時,沒有任何反應只會打印空白區域。

感謝

+0

我也在Ubuntu論壇上寫過這篇文章,但認爲它更像是一個通用的編碼問題。 – SeahawksRdaBest

+8

你知道'temp'和'string'指向相同的內存位置嗎? – 2013-10-27 22:21:46

+0

不要忘記接受WhozCraig答案,這是正確的方式來做你想做的。很好,很乾淨。 – Rerito

回答

5

您正在嘗試使用指針正確的方向。多思考一下,你可能會擁有它。一個安全的實現如下所示:

#include <stdio.h> 

char *flip_string(char *str) 
{ 
    char *lhs = str, *rhs = str; 
    if (!str || !*str || !*(str+1)) 
     return str; 

    while (*++rhs); // rhs to eos 
    while (lhs < --rhs) 
    { 
     char tmp = *lhs; 
     *lhs++ = *rhs; 
     *rhs = tmp; 
    } 
    return str; 
} 

int main() 
{ 
    char test1[] = "Hello, World!"; 
    char test2[] = ""; 
    char test3[] = "1"; 
    printf("%s, %s, %s\n", flip_string(test1), flip_string(test2), flip_string(test3)); 
    return 0; 
} 

輸出

!dlroW ,olleH, , 1 

希望它能幫助。

+0

比我的好多了...... – Rerito

+0

可能值得指出'char []'和'char *'之間的重要區別。在這種情況下,它複製字符串,否則將是未定義的行爲。 –

+0

我認爲'flip_string'做一個in-place反轉*和*返回參數是令人煩惱的。看到'printf'行的人可能不會期望'flip_string'實際上*修改*它的參數。實現這個想法意味着你不再需要保留原始的'str'指針,所以你可以使用它來遍歷,保存一個局部變量。 –

2

在這裏,你顯然希望tempstring的其他變量。但是你做的初始化將導致兩個指針指向同一個位置。

你應該做的卻是:

char *flip_string(const char *string) 
{ 
    char *tmp = NULL; 
    size_t len = strlen(string); 
    int i = 0; 
    /* 
    * Don't forget that strlen() returns the length of the string 
    * **WITHOUT** counting the ending '\0' character. 
    * Thus, you have to add the extra space when you're allocating 
    */ 
    if (!(tmp = malloc(len + 1))) { 
     printf("Allocation failed ...\n"); 
     return NULL; 
    } 
    /* 
    * The newly created string must have an ending character 
    * Which is '\0' 
    */ 

    tmp[len] = '\0'; 

    /* 
    * Here, you want to reverse the "true content" of your string. 
    * That is why you ignore the ending '\0' of the string by 
    * setting the upper bound to strlen (with a strict '<') **AND** 
    * it is also the reason a '- 1' just pops in the index choice. 
    */ 
    for(i = 0; i < len; i++) { 
     tmp[i] = string[len - i - 1]; 
    } 
    return tmp; 
} 

正如所強調的WhozCraig,還存在另一種解決方案,簡單的修改了參數字符串,而無需內存分配:

void flip_string(char *s) 
{ 
    size_t len = strlen(s); 
    char *p = s + len - 1; 
    while (s < p) { 
     *p ^= *s; 
     *s ^= *p; 
     *p ^= *s; 
     p--; 
     s++; 
    } 
} 

注意XOR招以避免使用交換字符的臨時存儲變量(^XOR運算符C

+1

你可能,但我不知道。沒有理由分配內存*來反轉標準的以零結尾的字符串。兩個指針和一個while循環(兩個,如果你想從'strlen()'獨立)是所需要的。 – WhozCraig

+1

@WhozCraig,你應該發佈它,你的答案應該比我的更具啓發性(這裏沒有諷刺!)。 – Rerito

+0

你們真棒。謝謝! – SeahawksRdaBest

3

你的函數似乎做了'in-place reversal',即它替換了內存中給定的字符串。這樣做時,請確保您不要將尾隨零移到最前面。這裏有一個簡單的實現功能

#include <assert.h> 
#include <string.h> 

void flip_string(char *s) 
{ 
    assert(s); 
    char *t = strchr(s, '\0') - 1; 
    for (; s < t; ++s, --t) { 
     char tmp = *s; 
     *s = *t; 
     *t = tmp; 
    } 
} 

的功能聲稱,它得到的字符串(即不是空指針),而內存是可寫的。然後它建立一個t指針指向字符串的最後一個字符 - 通過strchr而不是寫入手動循環,這樣做的好處是strchr通常是一個高度優化的函數,它不會以單字節步長遍歷字符串而是一次考慮四個甚至更多的字節。這也可以說是更具表現力。

主循環然後交換由st(即最初是第一個和最後一個字符)引用的字符,然後向前/向後移動指針直到它們相遇。

該函數稍微簡潔一些,因爲它不需要保留傳入的原始指針,而是可以直接修改s。這是決定一個函數應該要麼修改其參數返回一個新的值 - 但不是兩個。這樣做既意味着你可以調用像

printf("%s", flip_string(s)); 

功能......,這將完全掩蓋了s真正被修改了。

flip_string(s); 
printf("%s", s); 

在這方面更明確。