2017-08-08 107 views
1

我試圖實現一個函數,用於從memmove字符串中刪除一個子字符串。 打印結果時,看起來好像我沒有正確移動子字符串,即使它看起來像我在源字符串中使用了正確的位置。 我的功能是:從一個字符串中刪除一個子字符串,使用memmove在C

char * removeSubStr(char * str, const char * substr){ 
    char *scan_p, *temp_p; 
    int subStrSize = strlen(substr); 
    if (str == NULL){ 
     return 0; 
    } 
    else if (substr == NULL){ 
     return str; 
    } 
    else if (strlen(substr)> strlen(str)){ 
     return str; 
    } 
    temp_p = str; 
    while(scan_p = strstr(temp_p,substr)){ 
     temp_p = scan_p + subStrSize; 
     memmove(scan_p, temp_p, sizeof(temp_p)+1); 

    } 
    return str; 
} 

我的輸出,例如是: 如果發送字符串 「請刪除REM刪除rem999」, 我得到回: 「請奧雅納RM ovmove重999」

謝謝!

+1

(無關您的問題,但你通過'substr'到'strlen'之前,應先試'SUBSTR == NULL'否則,你可能最終調用。 'strlen'在空指針上。) –

回答

0

sizeof(temp_p)char *的大小,一般爲4

你可能想寫strlen(temp_p)

+0

strlen返回沒有'\ n'的長度,sizeof包含'\ n'裏面。不是嗎? – ILG

+0

不,它返回指針的大小:-) –

4

以下:

while(scan_p = strstr(temp_p,substr)){ 
    temp_p = scan_p + subStrSize; 
    memmove(scan_p, temp_p, sizeof(temp_p)+1); 
} 

讓人很沒有意義。

你需要的東西是這樣的:

while(temp_p = strstr(temp_p, substr)) 
{ 
    length = strlen(temp_p); 
    memmove(temp_p, temp_p + subStrSize, length - subStrSize + 1); 
} 

注:在我的答案,我只是用strlen()的第一個版本,但批評家指出,這將是因爲標準的不妥當的。 (它仍然最有可能的工作,因爲我們複製下來,不起來,但最好不要試圖違反標準來誘惑你的命運。)所以,這就是爲什麼我們需要memmove()

請注意,使用更多的代碼行,可以對其進行優化,以便您不必在循環的每次迭代中計算length = strlen(temp_p);。這個優化作爲練習留給學生。

同時請注意:

  • 您做的更好int subStrSize = strlen(substr);你檢查substr == NULL;

  • 有作爲styrlen()

  • sizeof(temp_p)沒有這樣的事情確實的東西從你認爲它完全不同。

+0

所以memmove不是一個好主意嗎? – ILG

+0

'strcpy(temp_p,temp_p + subStrSize);'是未定義的行爲。每** 7.24.2.3 [C標準]的'strcpy'函數**(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf):「如果複製發生在 重疊的對象之間,行爲是不確定的。「 –

+0

@AndrewHenle哦,我不知道。我會解決這個問題。謝謝。 –

1

在這個循環中

temp_p = str; 
while(scan_p = strstr(temp_p,substr)){ 
    temp_p = scan_p + subStrSize; 
    memmove(scan_p, temp_p, `sizeof(temp_p)`+1); 

} 

有兩個錯誤。

第一個問題是,在循環的每次迭代之後,指針temp_p應該等於指針scan_p的值,因爲字符串的尾部會移動到此位置。

第二個是,這種表達

sizeof(temp_p) 

產生類型char *的對象的大小,而不是提供該字符串的長度由指針temp_p指向。

你的功能也經常調用功能strlen

至於整個函數的設計,那麼函數不應該檢查其中一個參數是否等於NULL。這是該功能的客戶端的任務。標準C字符串函數不做這樣的檢查。

功能實現可以按照演示程序中顯示的以下方式進行查看。

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

char * removeSubStr(char *str, const char *substr) 
{ 
    size_t m1 = strlen(str); 
    size_t m2 = strlen(substr); 

    if (!(m1 < m2)) 
    { 
     for (char *p = str; (p = strstr(p, substr)) != NULL;) 
     { 
      size_t n = m1 - (p + m2 - str); 
      memmove(p, p + m2, n + 1); 
     } 
    } 

    return str; 
} 

int main(void) 
{ 
    char s[] = "12A12B12C12D"; 

    puts(s); 

    puts(removeSubStr(s, "12")); 

    return 0; 
} 

程序輸出是

12A12B12C12D 
ABCD 
+0

謝謝。我從你的帖子中學到了很多東西 – ILG

+0

@ILG沒有。不用謝。:) –

相關問題