2017-08-08 11 views
1

memmoveを使って文字列から部分文字列を取り除く関数を実装しようとしています。 結果を出力するとき、ソース文字列の正しい位置を使用したように見えますが、部分文字列を正しく移動していないようです。 My機能は次のとおりです。C言語でmemmoveを使って文字列から部分文字列を取り除く

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; 
} 

例えば私の出力は、次のとおりです。 文字列を送信する場合、私は戻ってきてる、 を "レム削除rem999を削除してください":

"RMは999を再ovmove OVEしてください"

ありがとう!

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

は非常に意味をなさない:

+1

(無関係です。しかし、あなたがstrlen' 'に' substr'を渡す前に、それ以外の場合は、あなたが呼び出しに終わるかもしれない 'SUBSTR == NULL'をテストする必要があります。 'null 'ポインタの' strlen')。 –

答えて

0

sizeof(temp_p)は通常4

あなたはおそらく次strlen(temp_p)

+0

strlenは' \ n 'のない長さを返し、sizeofは' \ n 'を内部に含みます。ではない? – ILG

+0

いいえ、ポインタのサイズを返します:-) –

4

を書きたかった、char *の大きさです。

あなたはこのようなものが必要です。

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

注:私の答えの最初のバージョンでは、私はちょうどstrlen()を使用していたが、コメンターが指摘したように、それが原因で、標準で勧められないだろうし。 (これは、おそらくおそらく動作するでしょう。コピーしているからではありませんが、標準に違反することによってあなたの運命を誘惑しないのが最善です。)だから、我々はmemmove()が必要なのです。

2行以上のコードでは、ループの各繰り返しでlength = strlen(temp_p);を計算する必要がないように最適化することができます。この最適化は、学生に練習として残されます。

も注意してください。

  • をあなたがより良い後int subStrSize = strlen(substr);を行うあなたはsubstr == NULLをご確認ください。

  • styrlen()

  • sizeof(temp_p)あなたはそれがないと思うものとは完全に異なる何かをするようなものはありません。

  • このループで
+0

memmoveは良い考えではありませんか? – ILG

+0

'strcpy(temp_p、temp_p + subStrSize);'は未定義の動作です。 Per ** 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); 

} 

2つのバグがあります。

最初の1つは、ループの各繰り返しの後で、ポインタtemp_pはポインタscan_pの値と同じでなければならないというのは、文字列の末尾がこの位置に移動されるためです。

もう一つは、この式

sizeof(temp_p) 

ポインタtemp_pによって指さタイプchar *の物体の大きさの代わりに提供する文字列の長さが得られることです。

また、あなたの関数は関数strlenをよく呼びます。

関数設計全体では、関数はパラメータの1つが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全くありません。どういたしまして。:) –

関連する問題