2016-12-10 2 views
1

Ich habe eine Datei wie dieseSplit eine Zeichenfolge, die ich aus einer Datei lesen

GET /index.html k 
GET /docencia.html k 
GET /ejemplo.html k 

und ich möchte es Zeile für Zeile lesen und teilen Sie es mit diesem Begrenzer " ", aber mir diesen Fehler geben: segmentation fault(core dumped) und ich weiß nicht, was ich versuchen soll.

Dies ist mein Code:

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char *argv[]) { 
    char ordenes[150]; 
    char *orden[3]; 
    char *token; 
    int tok; 

    FILE *fp; 
    fp = fopen(argv[1], "r"); 
    if (fp == NULL) { 
     printf("File error"); 
     exit(1); 
    } 

    while (feof(fp) == 0) { 
     fgets(ordenes, sizeof(ordenes), fp); 
     printf("%s \n", ordenes); 
     token = strtok(ordenes, " "); 
     tok = 0; 
     while (token != NULL) { 
      orden[tok] = strdup(token); 
      tok++; 
      token = strtok(NULL, " "); 
     } 

     printf("\n%s\n", orden[0]); 
     printf("\n%s\n", orden[1]); 
     printf("\n%s\n", orden[2]); 
    } 
    fclose(fp); 
} 

Der Fehler zeigt an, wenn ich die erste strdup nennen. Wenn ich versuche, das Token zu drucken, nur nachdem ich das erste strtok anrufe, scheitert es auch (das gleiche segmentation fault core dumped), also denke ich, dass das Problem mit dem strtok ist.

+0

'token = strtok (NULL,“ „) ; 'zum Loop-Ende wechseln. oder 'if (Token) break;' nach 'token = strtok (NULL," ");'. – BLUEPIXY

+1

setzen '#include '. – BLUEPIXY

+0

Okay, das Include war das Problem ... Der Compiler zeigte nichts, also dachte ich, mit der Std wäre gut. –

Antwort

5

Sie enthalten keine <string.h>, so dass der Compiler die Standardargument Aktionen auf der Unterschrift von strtok gilt insbesondere der Auffassung, dass strtok ein int zurückgibt.

So wird der Compiler einen Operator des Zwangs von int zu pointer to char bei der Zuordnung gelten

token = strtok(ordenes, " "); 

und diese Zuordnung wird kompiliert werden als

token = (int->char*) strtok(ordenes, " "); 
+0

Guter Fang! Dies wird definitiv Probleme auf 64-Bit-Systemen verursachen, während dies bei 32-Bit-Systemen unbemerkt bleibt. Definitiv undefiniertes Verhalten! Sie könnten dem OP auch raten, Compiler-Warnungen zu verwenden, um solche dummen Fehler zu vermeiden. 'gcc -Wall -W',' clang -Weverything' ... – chqrlie

-1

versuchen Sie dies:

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

int main(int argc, char *argv[]){ 
    char ordenes[150]; 
    char *orden[3]; 
    char *token; 
    int tok; 
    FILE *fp; 

    fp = fopen (argv[1], "r"); 
    if(fp==NULL){ 
     printf("File error"); 
     exit(1); 
    } 
    while(fgets(ordenes, sizeof(ordenes), fp)){ 
     printf("%s\n",ordenes); 
     token = strtok(ordenes, " "); 
     tok = 0; 
     while (token != NULL){ 
      orden[tok++] = strdup(token); 
      token = strtok(NULL," "); 
     } 
     printf("\n%s\n",orden[0]); 
     printf("\n%s\n",orden[1]); 
     printf("\n%s\n",orden[2]); 
     free(orden[0]);free(orden[1]);free(orden[2]); 
    } 
    fclose(fp); 
} 
+0

Sie haben undefiniertes Verhalten, 'tok ++' was ist, wenn es über 2 geht? 'argv [1]' was ist, wenn es 'NULL' ist? Du hast elem nicht auf 'NULL' gesetzt, also 'frei' oder benutze sie als UB. – Stargateur

+0

@Stargateur Die Lesedatei wird als drei Elemente angenommen. – BLUEPIXY

+1

Angenommen, das korrekte Eingabeformat führt zu undefiniertem Verhalten und ausnutzbaren Fehlern. – chqrlie

0

Sie können Folgendes tun:

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

static void play_with_token(char *token, char const *delim) 
{ 
    if (token == NULL) 
    return; 
    printf(" %s", token); 
    play_with_token(strtok(NULL, delim), delim); 
} 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2) 
     return 1; 
    FILE *fp = fopen(argv[1], "r"); 
    if (fp == NULL) 
     return 1; 

    char *line = NULL; 
    size_t len = 0; 
    ssize_t read; 
    while ((read = getline(&line, &len, fp)) != -1) { 
     printf("parsing line :"); 
     char const *delim = " "; 
     play_with_token(strtok(line, delim), delim); 
     printf("\n"); 
    } 
    free(line); 
    fclose(fp); 
} 
+1

Ihr Tail-Rekursionsstil in 'play_with_token' ist in C nicht idiomatisch. Es ist besonders schlecht, da die ersten und nachfolgenden Aufrufe von' strtok() 'in verschiedenen Funktionen erscheinen. 'strtok()' Semantik und Nicht-Reentry-Probleme sind ein Problem, das es sehr ratsam macht, alle Anrufe dicht beieinander zu halten. – chqrlie

+0

@chqrlie Es ist ein Style-Problem, ich denke nicht, dass das schlecht ist, weil 'play_with_token()' die echte Zeichenfolge nicht kennen muss. Ich werde einfach ein Trennzeichen hinzufügen, um mehr Logik zu sein. – Stargateur

+0

Es mag ein Stilproblem sein, aber wie würden Sie eine absichtlich verschleierte Antwort bewerten? Wenn 'play_with_token' lokal und' statisch' gemacht wird, wird der schlechte pädagogische Wert dieses Ansatzes nicht behoben. Sie sind sich der Unzulänglichkeiten von 'strtok()' wohl bewusst, aber die meisten Neulinge sind es nicht. – chqrlie

3

Es gibt mehrere Probleme im Code:

  • Als alinsoar mit einem scharfen Auge diagnostiziert, Sie enthalten keine <string.h>. strtok ist nicht definiert, der Compiler muss davon ausgehen, dass es einen int zurückgibt, was nicht der Fall ist, und dieser int wird automatisch in einen char * konvertiert. Der generierte Code ruft undefiniertes Verhalten auf und stürzt höchstwahrscheinlich auf 64-Bit-Zielen ab. Sie sollten mit allen Warnungen kompilieren, damit der Compiler diesen dummen Fehler vermeiden kann. gcc -Wall -W oder clang -Weverything ...

  • Sie überprüfen nicht, ob Befehlszeilenargumente vor dem Aufruf fp = fopen(argv[1], "r"); an Ihr Programm übergeben wurden. Wenn keine Argumente übergeben werden, ist argv[1] ein Nullzeiger.

  • while (feof(fp) == 0) falsch ist, lesen Why is “while (!feof (file))” always wrong?. Sie sollten stattdessen schreiben while (fgets(ordenes, sizeof(ordenes), fp)) {...

  • Sie überprüfen nicht, ob tok < 3 vor token in die orden Array zu speichern. Wenn die Zeile mehr als 3 Felder enthält, verursachen Sie einen Pufferüberlauf.

  • Sie überprüfen nicht, ob tatsächlich 3 Token gefunden wurden, bevor alle 3 Einträge in orden gedruckt wurden. Dies kann auch zu undefiniertem Verhalten führen, insbesondere wenn fgets() eine Zeile nicht lesen konnte, die Sie nicht überprüfen.Hier

ist eine verbesserte Version:

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

int main(int argc, char *argv[]) { 
    char ordenes[150]; 
    char *orden[3]; 
    char *token; 
    int i, tok; 

    if (argc < 2) { 
     fprintf(stderr, "Missing command line argument\n"); 
     exit(1); 
    } 
    FILE *fp = fopen(argv[1], "r"); 
    if (fp == NULL) { 
     fprintf(stderr, "Cannot open input file %s: %s\n", 
       argv[1], strerror(errno)); 
     exit(1); 
    } 

    while (fgets(ordenes, sizeof(ordenes), fp)) { 
     printf("%s", ordenes); 
     token = strtok(ordenes, " "); 
     for (tok = 0; tok < 3 && token != NULL; tok++) { 
      orden[tok] = strdup(token); 
      token = strtok(NULL, " "); 
     } 
     for (i = 0; i < tok; i++) { 
      printf("%s\n", orden[i]); 
      free(orden[i]); 
     } 
     printf("\n"); 
    } 
    fclose(fp); 
    return 0; 
} 
+0

@BLUEPIXY: korrigiert! danke – chqrlie

+0

Ihre Antwort hat mir sehr geholfen, weil ich festgestellt habe, dass die Schleife noch einmal wiederholt wurde, –

0

Für den Anfang sollten Sie den Zustand in der äußeren Schleife Anweisung ändern Sie die folgende Art und Weise

while (fgets(ordenes, sizeof(ordenes), fp) != NULL) 

Der Zustand in der inneren Schleife sollte geschrieben mindestens wie

while (tok < 3 && token != NULL) { 

Die Token sollten in einer Schleife ausgegeben werden und der zugewiesene Speicher muss freigegeben werden. Zum Beispiel

for (int i = 0; i < tok; i++) 
    { 
     printf("\n%s\n", orden[i]); 
     free(orden[i]); 
    } 
Verwandte Themen