2017-10-08 18 views
0

Cで、指定されたキーの周りにテキストをソートする関数を開発しています。あなたがプログラムを実行し、入力として、それをこのファイルを与えると、それは印刷する必要がありCソートプログラムのセグメンテーションフォールト

this line is first 
but this line is second 
finally there is this line 

but this line is second 
finally there is this line 
this line is first 

を最終的には、この前にされる前に、アルファベット順ですので のは、あなたが次のファイルがあるとしましょう。

しかし、別のキーをソートするフラグを渡すと、別の出力が得られます。たとえば、このファイルでfastsort -2を呼び出すと、次のようになるはずです。

this line is first 
finally there is this line 
but this line is second 

この前にこれが来るはずです。はい、私は-2と仮定しています.2行目は各行の2番目の単語を意味します(ほとんどの人がそうですが、常に0から始めるコンピュータサイエンスを除く)。

また、指定したキーが入力ファイルの特定の行に存在しない場合は、その行の最後の単語をキーとして使用してください。たとえば、ユーザーが4番目の単語(-4)をソートし、ソートに次のような行が見つかった場合(サンプル行)、ソートではの行を使用してその行をソートする必要があります。

私はstrtok()を使ってキーで与えられた単語を抽出していますが、そのキーがその行の単語の数よりも大きければセグメント化エラーが発生します。ここに関数の本体があります。

typedef struct { 
    char word[128]; 
    int index; 
} wordIndex; 

char** fastsort(char** text, int word){ 

char** sortedText; 
char* LineAux; 
int i; 
wordIndex tokenLines[numLines]; 

for(i=0; i<numLines; i++){ 
    char* token; 
    int j = 0; //counter 

    LineAux = (char*) malloc(MAX_LENGTH*sizeof(char)); //MAX_LENGTH = 128 
    if (LineAux==NULL){ 
     fprintf(stderr,"Error, malloc failed"); 
     exit(1); 
    } 

    strcpy(LineAux,text[i]); 

    token = strtok(LineAux, " \n"); 
    j++; 

    if(token == NULL){ //if blank line 
     token=" "; 

    } else { 

     while(token != NULL){ //segmentation fault 
      if(j == word){ 
       break; 
      } 
      token = strtok(NULL, " \n"); 
      j++; 

     } 
    } 

    strcpy(tokenLines[i].word,token); 
    tokenLines[i].index=i; 
    free(LineAux); //free Aux string 
    printf("token: %s Line: %d \n",tokenLines[i].word, tokenLines[i].index); 
} 

qsort(tokenLines,numLines,sizeof(wordIndex),compareTo); //sorting tokens 

sortedText = (char**) malloc(numLines*sizeof(char*)); 
if (sortedText==NULL){ 
    fprintf(stderr,"Error, malloc failed"); 
    exit(1); 
} 


//reordering text 
int n; 
for (n=0; n<numLines; n++){ 
    int index; 

    sortedText[n]=(char*) malloc(MAX_LENGHT*sizeof(char)); 

    if (sortedText[n]==NULL){ 
     fprintf(stderr,"Error, malloc failed"); 
     exit(1); 
    } 

    index = tokenLines[n].index; 
    strcpy(sortedText[n],text[index]); 

} 


return sortedText; 

}

セグメンテーション違反は、whileループの内側に表示されます。 お手数ですが、よろしくお願いいたします。

+0

'text [i]]は127文字と終端バイトを超えることができますか?できれば、 'strcpy'は' LineAux'の範囲をオーバーランさせます。同じことが 'text [index]'の続きです。 –

+0

@CharlesSrstkaいいえ、私は別の関数(ファイルからテキストを抽出する)があります。これは、行が127文字以上(+終了)になることを防ぐためです。 – Setekorrales

+0

'wordIndex'とは何ですか?構造体のいくつかの並べ替え私はそれを取る? –

答えて

1

私は自分のマシン上で上記のコードを実行しました。それは1つの警告で動作します。 jが何かと比較される前にインクリメントされているため、wordは、0の代わりに0のインデックスが付けられています。あなたが0を入力した場合は、当然、あなたが最初の単語でソートしたいかどうように、この行が真になるだろうことはありません:トークンがNULLなるまで

if(j == word){ 

したがって、あなたのwhileループが続きます。

strcpy(tokenLines[i].word,token); // don't NULL me bro! 

これはあなたのクラッシュの原因である:次に、ループの後、あなたのstrcpyクラッシュは、それはあなたがそれに渡されたNULLポインタを欽慕してみましたので。

  1. は、ループの前j++を取り除く:それを修正するために、私は2つの変更を行いたいです。索引付けは0から開始します。これは通常、Cで行われるものであり、関数のユーザーが通常期待するものです。

  2. ループが終了した後、tokenをテストして、NULLであるかどうかを確認します。そうであれば、関数を正常に終了し、何らかのエラーをユーザに返します。誰かが無効な単語番号を入力するとクラッシュするとUIが悪くなります。

0

Allrigth、私には解決策があります。

問題は、whileループ内の命令の順序です。ここで

は、実用的なソリューションです:

/** 
* Function that sorts text by a given key 
* @param text: array of strings which is going to be sorted 
* @param word: key where the sort starts 
* @return sorted text 
*/ 
char** fastsort(char** text, int word){ 

    char** sortedText; 
    char* LineAux; 
    int i; 
    wordIndex tokenLines[numLines]; 

    for(i=0; i<numLines; i++){ 
     char* token; 
     int j = 0; //counter 

     LineAux = (char*) malloc(MAX_LENGHT*sizeof(char)); 
     if (LineAux==NULL){ 
      fprintf(stderr,"Error, malloc failed"); 
      exit(1); 
     } 

     strcpy(LineAux,text[i]); 

     token = strtok(LineAux, " \n"); 
     j++; 

     if(token == NULL){ //if blank line 
      token=" "; 

     } else { 

      while(token != NULL){ //segmentation fault 
       strcpy(tokenLines[i].word,token); 
       if(j == word){ 
        break; 
       } 

       token = strtok(NULL, " \n"); 
       j++; 

      } 
     } 

     tokenLines[i].index=i; 
     free(LineAux); //free Aux string 
    } 

あなたが見ることができるように、変更は非常に効率的ではありませんが、それはあなたが別のソリューションを持っている場合、私はそれを試して喜んでいるよ、今のために働くありません。

関連する問題