2017-06-30 11 views
0

私はこれをデバッグして、セグメンテーションフォルトの原因となっている可能性があるものを見つけようとしています。私はかなり新しいです。これは、配列内で連続する重複を削除するはずの小さなメソッドです。それが呼び出されるセグメンテーションフォールトと文字配列とポインタ

void removeddup(char *str){ 
    int i; 
    int j; 
    int len= str_len(str)-1; 
    int removed = 0; 
    for(i=0; i < (len-removed);) 
    { 
     if(str[i]==str[i+1]) 
     { 
      for(j=i; i<(len-removed);j++) 
      str[j]=str[j+1]; 
      removed++; 
     }else{ 
     i++; 
     } 
    } 
} 

この

char str1[100] 
case '6': 
     removeddup(str1); 
     break; 
+3

で終了していることに注意してください変更されない場合、無限ループが発生する可能性があります。 – BLUEPIXY

+2

@BLUEPIXY 'else {i ++; } ' – Barmar

+0

あなたはどのようにあなたの関数を呼び出しますか? – AnT

答えて

0

あなたのアイデアは、一つの問題は、ここで

for(j=i; i<(len-removed);j++) 
    str[j]=str[j+1]; 

悪いされていないようにあなたはjをインクリメントしておくが、条件i<(len-removed)は永遠に真の を開催します。ある時点で、あなたはメモリの境界を越えてメモリを読み書きしようとします( のように)segfaultとなります。あなたの問題は、正確にいくつかのdupplicate の文字が計算されないということです。

はのは

str[j]=str[j+1]; 

も非常に効率的ではないことをあなたが言ってみましょう。私はポイントを得る、str[j] の次の文字にコピーしようとすると、\0を見つけるまで。あなたの入力がabccccddddeee、 であり、あなたがしようとしている1枚のコピーがひどく長いとします。

重複コピーの数を計算し、 memmoveを使用すると、一度にメモリブロック全体を移動する方が効率的です。

あなたのアプローチの代わりにmemmoveを使用してコードを修正しました。私はまた、 のコメントを複写の長さを計算する方法と、 のパラメータがmemmoveであると説明しました。私は通常 の紙を取って、手で最初にやってみると、より早くアイデアを得ることができます。

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

void removeddup(char *str){ 
    int i; 
    int j; 
    int len= strlen(str)-1; 
    int removed = 0; 

    for(i=0; i < (len-removed);) 
    { 
     if(str[i]==str[i+1]) 
     { 
      // we calculate the length of the duplicates 
      j = 0; 
      while(str[i] == str[i + ++j]); 

      // we have j duplicates of str[i] (counting str[i]) 
      // we copy the rest of the string after the j-1 duplicates 
      // the destination is the next character after str[i] (str + i +1) 
      // the source is str[i+j] 
      // 
      // now we have to determine how many chars to copy. In general 
      // you do string_length - index_of_source + 1, which also copies 
      // the \0 string-terminating character. 
      // 
      // In your case 
      // string_length: len - removed + 1 (the +1 because you 
      //     defined len := strlen(str)-1; 
      // index_of_source: i + j 
      // ==> len - removed + 1 - (i + j) + 1 
      // so 

      memmove(str + i + 1, str + i + j, len - removed + 1 - (i+j) + 1); 

      // now we set how many characters we've removed 
      removed += j - 1; 

      // we go the next character 
      i++; 

     }else{ 
      i++; 
     } 
    } 
} 


int main(void) 
{ 

    char text[] = "abccccccdeeefffffffffffff"; 

    printf("Original: %s\n", text); 
    removeddup(text); 
    printf("removed: %s\n", text); 

    return 0; 
} 

はまた、あなたが バッファへの書き込みアクセス権を持っている場合、このメソッドはのみ動作することに注意してください。文字列リテラル(const char *text = "abcdddd";)、 を渡すと、segfaultが返されます。これは、文字列リテラルが読み取り専用メモリにあるためです。 `私は(LEN-除去)<`ので: `

は、ラインがwhileは(J ++; iが<(LEN-除去)J = i)について` ;

while(condition); 

// is equivalent to 

while(condition) 
{ 
} 
関連する問題