2016-03-01 97 views
0

因此,下面是一個函數,用於從字符串中過濾出給定的字符ch,並將結果放入過濾後的版本。底部的puts語句最終輸出與原始字符串相同的字符串,無論過濾後的字符如何,結果都是空的。從C中的字符串中過濾字符C

void filter_ch_index(char string[], char result[], char ch) { 
    result[0] = NUL ; // placeholder 
    int i; 
    for(i = 0; i < strlen(string); i++) 
    { 
     if(string[i] != ch) 
     { 
      result[i] = string[i]; 
     } 
    } 
    puts(result); 
} 

回答

1

其中一個問題是您的複製邏輯。

當字符不同時,您不會將其複製到result,,但您仍然增量i。在result字符串中留下。爲了解決這個問題,你可以使用指針(引用和增量)。

我看到的另一個問題是您如何調用該函數。你爲兩者分配了足夠的內存空間嗎?

我會把非常不安全的函數的實現來展示你如何做到這一點。您應該修改函數以考慮字符串大小。

#include <stdio.h> 

void filter(char *a, char *b, char c) 
{ 
    char *aux = b; 
    while(*a) { 
     if(*a != c) *b++ = *a; 
     a++; 
    } 
    *b = 0x0; // thx to @PaulRoub for pointing it out 
    puts(aux); 
} 

int main(int argc, char *argv[]) 
{ 
    char buffer[100]; 

    if(argc < 3) { 
     printf("Usage: %s <string> <character>\n", argv[0]); 
     return 0; 
    } 

    filter(argv[1], buffer, argv[2][0]); 
    return 0; 
} 

在上面的代碼,aux充當的b起始地址的備份。 while循環將繼續,而當前的a字符不是\0(您可以將其讀取爲while (*a != '\0'))。條件也很簡單。複製部分是我之前談到的。

我們只會增加b字符串如果我們複製一些東西,否則它的引用保持不變。該過程將繼續,直到循環找到a字符串中的\0終止字符。

輸出:

[ ~/src/test ] $ ./filter "Stack Overflow Questions" e 
Stack Ovrflow Qustions 
[ ~/src/test ] $ ./filter "Stack Overflow Questions" S 
tack Overflow Questions 
[ ~/src/test ] $ ./filter "Stack Overflow Questions" s 
Stack Overflow Quetion 
[ ~/src/test ] $ ./filter "aaa bbb ccc abc cba" a  
bbb ccc bc cb 
[ ~/src/test ] $ ./filter "aaa bbb ccc abc cba" b 
aaa ccc ac ca 
[ ~/src/test ] $ ./filter "aaa bbb ccc abc cba" c 
aaa bbb ab ba 
[ ~/src/test ] $ 
+0

這清理了很多,非常感謝。 –

+0

@PaulRoub噢,謝謝! –

1

需要兩個指標,一個你正在閱讀和你寫的一個:

void filter_ch_index(char string[], char result[], char ch) 
{ 
    int j = 0; 
    for (int i = 0; string[i] != '\0'; i++) 
    { 
     if (string[i] != ch) 
      result[j++] = string[i]; 
    } 
    result[j] = '\0' 
    puts(result); 
} 

這假定result足夠大。請注意,複製函數中參數的最常見順序是'目的地,源'(請參閱strcpy(),memmove(),...),但您的順序相反。

請注意,使用原始for(i = 0; i < strlen(string); i++)是一個壞主意。在循環條件中使用strlen()就像將線性算法轉換爲二次算法,除非您有足夠複雜的編譯器來發現字符串的長度在循環的每次迭代中都不會更改。 (戰爭故事:千年一遇,有一個包含循環條件的strstr()的實現,它在小字符串上工作正常 - 比如低於100字節;在20 KiB或更多的字符串上使用時,這是一個災難。平臺很好 - 這一個沒有,這個bug早已修復)

請注意,你可以在原地安全地修改源字符串;輸出字符串永遠不會比源字符串長。這樣可以避免緩衝區溢出,除非源字符串本身無效(不是空終止)。接口是void replace_ch(char *string, char ch)。上面的函數可以使用void filter_ch_index(const char string[], char result[], char ch)const來表示源字符串不會被函數修改。