2017-10-08 9 views
0

Ich entwickle eine Funktion in C, die Text um einen bestimmten Schlüssel sortiert. Angenommen, Sie haben die folgende Datei:Segmentierungsfehler im C-Sortierprogramm

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

Wenn Sie das Programm ausführen und diese Datei als Eingabe geben, sollte es drucken:

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

weil aber alphabetisch ist, bevor sie schließlich vor dieser ist.

Wenn Sie jedoch ein Flag übergeben, um einen anderen Schlüssel zu sortieren, erhalten Sie eine andere Ausgabe. Zum Beispiel, wenn Sie FastSort -2 auf diese Datei aufrufen, sollten Sie:

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

weil Leitung kommt, bevor es vor diesem kommt. Ja, ich nehme an, -2 bedeutet das zweite Wort in jeder Zeile (wie die meisten Leute, außer Informatikern, die immer bei 0 anfangen wollen).

Darüber hinaus, wenn der angegebene Schlüssel nicht in einer bestimmten Zeile der Eingabedatei vorhanden ist, sollte ich nur das letzte Wort dieser Zeile als Schlüssel verwenden. Wenn der Benutzer beispielsweise nach dem vierten Wort (-4) sortieren möchte und die Sortierung auf eine Zeile wie diese trifft (Beispielzeile), sollte die Sortierung das Wort Zeile verwenden, um diese Zeile zu sortieren.

Mein Problem kommt von dieser letzten Annahme, ich verwende strtok(), um das durch den Schlüssel gegebene Wort zu extrahieren, aber ich bekomme einen Segmentierungsfehler, wenn der Schlüssel größer als die Anzahl der Wörter in der Zeile ist. Hier ist der Körper der Funktion;

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; 

}

die Segmentierungsfehler erscheint innerhalb der while-Schleife. Hoffe, dass Sie helfen können, Vielen Dank im Voraus.

+0

Kann 'text [i]' jemals länger als 127 Zeichen plus das abschließende Byte sein? Denn wenn es möglich ist, wird Ihr 'strcpy' die Grenzen von LineAux' überschreiten. Dasselbe gilt für 'text [index]' weiter unten. –

+0

@CharlesSrstka Nein, habe ich eine andere Funktion (die den Text aus der Datei extrahiert), die die Linie aus, die mehr als 127 Zeichen (+ endet), so dass es länger als das wird nie Was ist – Setekorrales

+0

verhindert 'wordIndex'? Eine Art Struktur nehme ich es? –

Antwort

1

Ich habe den Code oben auf meinem Computer ausgeführt. Es funktioniert, mit einem Vorbehalt; word ist 1-indexed anstelle von 0 wie Sie vielleicht erwarten, da j inkrementiert wird, bevor Sie es überhaupt mit irgendetwas vergleichen. Also, wenn Sie 0 eingeben, wie Sie natürlich, wenn Sie durch das erste Wort sortieren wollen, wird diese Linie nie wahr sein werde:

if(j == word){ 

Daher Ihre while-Schleife wird fortgesetzt, bis Token NULL ist. Dann, nach der Schleife, Ihre strcpy abstürzt, weil es versucht, den Null-Zeiger auf Ehrerbietung Sie an sie übergeben:

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

Dies ist die Quelle des Absturzes.Um es zu beheben, würde ich zwei Änderungen vor:

  1. Sie sich von den j++ vor der Schleife befreien. Lassen Sie die Indizierung bei 0 beginnen, da dies normalerweise in C geschieht und was ein Benutzer der Funktion normalerweise erwarten würde.

  2. Nachdem die Schleife beendet ist, testen Sie token, um zu sehen, ob es NULL ist. Ist dies der Fall, beenden Sie die Funktion ordnungsgemäß und geben Sie dem Benutzer möglicherweise einen Fehler zurück. Abstürze, wenn jemand eine ungültige Wortnummer eingibt, ist eine schlechte Benutzeroberfläche.

0

Allrigth, ich habe die Lösung;

Das Problem war die Reihenfolge der Anweisungen innerhalb der While-Schleife.

Hier ist die Arbeitslösung:

/** 
* 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 
    } 

Wie Sie sehen können, ist die Änderung nicht sehr effizient ist, aber es funktioniert jetzt, wenn Sie eine alternative Lösung haben, werde ich froh sein, es zu versuchen.