2017-06-19 146 views
0
char * removeChar(char * str, char c){ 
    int len = strlen(str); 
    int i = 0; 
    int j = 0; 
    char * copy = malloc(sizeof(char) * (len + 1)); 
    while(i < len){ 
     if(str[i] != c){ 
      copy[j] = str[i]; 
      j++; 
      i++; 
     }else{ 
      i++; 
     } 
    } 

    if(strcmp(copy, str) != 0){ 
     strcpy(str,copy); 

    }else{ 
     printf("Error"); 
    } 
    return copy; 
} 




int main(int argc, char * argv[]){ 
    char str[] = "Input string"; 
    char * input; 
    input = removeChar(str,'g'); 
    printf("%s\n", input); 
    free(input); 
    return 0; 
} 

我不知道爲什麼每次我嘗試運行它時,它總是說未初始化的變量並粘在strcpy行和printf行中。爲什麼malloc不能使用strcpy?

基本上這個函數是取一個字符串和一個字符,並從字符串中移除該字符(因爲我正在學習malloc,所以我就這樣寫了這個函數)。

+0

在我看來,在if(strcmp(copy,str)!= 0)塊結束後至少有兩行代碼丟失。請添加它們。 (你可以編輯你的問題 - 看到一個盒子裏的藍色「c」下的小灰色單詞「edit」,這是一個按鈕。是的,真的。) – zwol

+6

我想你忘了把字符串的最後一個字節設置爲'NUL '('\ 0')。 – Alexander

+2

我沒有得到那個警告,但另一個〜*警告C4715:'removeChar':並非所有的控制 路徑返回值*。但看到我不得不添加一個缺失的'}'也許我把它放在了錯誤的地方。 –

回答

2

你從來沒有初始化的輸入,並將該值永遠不會在你的代碼行

input = removeChar(str, 'g'); 

之前使用的一些編譯器根本沒有注意到, 。所以他們發佈診斷只是爲了確保。

strcpy(str, copy) 

卡在你的代碼,因爲拷貝從來沒有關閉0字節, 如此依賴於你的記憶在 時刻內存分配的不確定性內容備份副本,多長的strcpy 會運行,如果你最終得到一個SIGSEGV(或類似的)。

strcpy將循環直到它在您的內存中找到0字節。

+4

這有點缺乏答案....它只是一個評論。 –

+0

哦,我明白了。多謝 。它現在有效:) –

4

while循環後做:

copy[j] = '\0'; 

NULL -terminate您的字符串;這樣它可以使用來自<string.h>的方法,它假定該字符串是nul-terminated。


PS:一個警告,你應該看到的是關於不是在你的功能在任何情況下返回copy,因爲現在如果if語句是錯誤的,你的函數將不會返回的東西有效,因此添加此條件:

return copy; 

在你的函數結束時(這是現在與你的編輯校正)。

除此之外,你仍然應該得到的唯一的警告是對的main()未使用的參數,沒有別的:

prog.c: In function 'main': 
prog.c:32:14: warning: unused parameter 'argc' [-Wunused-parameter] 
int main(int argc, char * argv[]){ 
       ^~~~ 
prog.c:32:27: warning: unused parameter 'argv' [-Wunused-parameter] 
int main(int argc, char * argv[]){ 
          ^~~~ 
+4

Nitpick:NULL是一個指針。字符串是NUL終止的,只有一個L. – zwol

+1

@zwol:這就是爲什麼現在幾乎完全說「零終止」的原因。減少混淆。 –

3

當你從str拷貝過來字節copy,你不添加終結空字節在結尾。因此,strcmp會將複製的字符讀取到單元化內存中,可能會超出分配的內存塊的末尾。這調用undefined behavior

在您的while循環之後,將終止空字節添加到copy

此外,如果末尾的if塊爲假,則永不返回值。你需要爲此返回一些東西,可能是複製的字符串。

char * removeChar(char * str, char c){ 
    int len = strlen(str); 
    int i = 0; 
    int j = 0; 
    char * copy = malloc(sizeof(char) * (len + 1)); 
    while(i < len){ 
     if(str[i] != c){ 
      copy[j] = str[i]; 
      j++; 
      i++; 
     }else{ 
      i++; 
     } 
    } 
    // add terminating null byte 
    copy[j] = '\0'; 

    if(strcmp(copy, str) != 0){ 
     strcpy(str,copy); 
    } 
    // always return copy 
    return copy; 
} 
+0

是的,你現在工作正常。謝謝:) –

0

對於初學者刪除從字符串中的字符沒有必要動態地創建一個字符數組,然後該數組複製到原始字符串。

您應該編寫一個函數,該函數確實可以從字符串或函數中刪除指定的字符,該函數根據不包含指定字符的源字符串創建新字符串。

這只是一個糟糕的設計,只會讓用戶感到困惑。這是功能太複雜,並使用多餘的功能,如malloc,strlen,strcmpstrcpy。事實上它有一個不明顯的副作用。此外,對於字符串的長度,使用不正確的類型int,而不是類型size_t

至於你的函數實現,那麼你忘了將終止零'\ 0'附加到動態分配數組中構建的字符串。

如果你確實想從一個字符串中刪除一個字符,那麼這個函數看起來就像在演示程序中顯示的那樣。

#include <stdio.h> 

char * remove_char(char *s, char c) 
{ 
    char *p = s; 

    while (*p && *p != c) ++p; 

    for (char *q = p; *p++;) 
    { 
     if (*p != c) *q++ = *p; 
    } 

    return s; 
} 

int main(void) 
{ 
    char str[] = "Input string"; 

    puts(str); 
    puts(remove_char(str, 'g')); 

    return 0; 
} 

程序輸出是

Input string 
Input strin 

如果你正在學習的功能malloc並想使用它,你在任何情況下,應儘量實現一個正確的設計。

要使用malloc您可以編寫一個函數,該函數根據不包含指定字符的源字符串創建新字符串。例如

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

char * remove_copy_char(const char *s, char c) 
{ 
    size_t n = 0; 

    for (const char *p = s; *p; ++p) 
    { 
     if (*p != c) ++n; 
    } 

    char *result = malloc(n + 1); 

    if (result) 
    { 
     char *q = result; 

     for (; *s; ++s) 
     { 
      if (*s != c) *q++ = *s; 
     } 

     *q = '\0'; 
    } 

    return result; 
} 

int main(void) 
{ 
    char *str = "Input string"; 

    puts(str); 

    char *p = remove_copy_char(str, 'g'); 

    if (p) puts(p); 

    free(p); 

    return 0; 
} 

程序的輸出結果與上面相同。

Input string 
Input strin 

,請注意函數聲明

char * remove_copy_char(const char *s, char c); 
         ^^^^^^ 

在這種情況下,源字符串可以是一個字符串文字。

char *str = "Input string";