2017-03-29 5 views
0

Ich mache einen Dateileser, der Ganzzahlen Zahlen Zeile für Zeile aus einer Datei liest. Das Problem ist, dass es nicht funktioniert. Ich denke, ich benutze fscanf falsch. Kann mir jemand helfen?Lesen von Ganzzahlen aus der TXT-Datei in C

Ich hatte bereits in anderen Fragen nach Antworten gesucht, aber ich kann nichts finden, das erklärt, warum ich meinen Code nicht funktioniert.

int read_from_txt(){ 
    FILE *file; 
    file = fopen("random_numbers.txt", "r"); 
    //Counting line numbers to allocate exact memory 
    int i; 
    unsigned int lines = 0; 
    unsigned int *num; 
    char ch; 
    while(!feof(file)){ 
     ch = fgetc(file); 
     if (ch == '\n'){ 
      lines++; 
     } 
    } 
    //array size will be lines+1 
    num = malloc(sizeof(int)*(lines+1)); 
    //storing random_numbers in num vector 
    for(i=0;i<=lines;i++){ 
     fscanf(file, "%d", &num[i]); 
     printf("%d", num[i]); 
    } 
    fclose(file); 
} 

Die txt-Datei ist wie:

12 
15 
32 
68 
46 
... 

Aber der Ausgang dieses Codes hält "0000000000000000000 ..." geben

+3

überprüfen, nachdem die 'fgetc'-Schleife den Dateizeiger am Ende der Datei befindet. Sie müssen die Datei zurückspulen, bevor Sie sie erneut lesen. – kaylum

+0

@Lashane 'Datei' wurde im Textmodus geöffnet. Textdateien, die der C-Bibliothek des Compilers entsprechen und eine Textdatei verstehen, übersetzen das '\ n',' \ r \ n' oder '\ r' in ein' \ n''. 'if (ch == '\ n')' ist ausreichend. Wenn andere Textdateien verarbeitet werden müssen, treten viele andere Probleme auf, die über den Umfang dieses Posts hinausgehen. – chux

+1

Tipp: Jeder Zeitcode verhält sich nicht wie erwartet und der Code tut I/O, Code hinzufügen, um den Rückgabewert von I/O-Funktionen wie 'fscanf (Datei,"% d ", & num [i]); hätte ein Problem gezeigt - das spart Zeit. – chux

Antwort

2

Sie haben vergessen, die Datei zu "zurückspulen":

fseek(file, 0, SEEK_SET); 

Ihr Prozess des Lesens geht zweimal durch die Datei - einmal, um Zeilen zu zählen, und noch einmal, um die Daten zu lesen. Sie müssen vor dem zweiten Durchlauf zum Anfang der Datei zurückkehren.

Beachten Sie, dass dies durch die Verwendung realloc in einem einzigen Durchgang tun, wie Sie gehen: lesen Zahlen in einer Schleife in eine temporären int, und für jede erfolgreiche Lese erweitert das num Array durch einen von realloc Aufruf. Dadurch wird der Puffer nach Bedarf erweitert, und Sie müssen nicht zurückspulen.

Achten Sie darauf, die Ergebnisse von realloc zu überprüfen, bevor Sie sie erneut an num zuweisen, um Speicherlecks zu vermeiden.

+0

Erinnert mich an [be-kind-rewind] (https://wtfmarketing.com/be-kind-please-rewind/). – chux

1

Sie könnten versuchen, die getline-Funktion von Standard IO zu verwenden und die geparsten Zahlen in das Array mit nur einer Schleife hinzufügen. Siehe den folgenden Code. Überprüfen Sie bitte https://linux.die.net/man/3/getline

Sie können auch die atoi oder strtoul Funktionen verwenden, um die Leselinie in eine Ganzzahl zu konvertieren. Fühlen Sie sich frei https://linux.die.net/man/3/atoi oder https://linux.die.net/man/3/strtoul

Der folgende Code zu bewerten, eine Datei mit einer Liste von Zahlen zu überprüfen und diese Zahlen auf einen C integer Zeiger

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

int main(int argc, char ** argv) { 
    FILE * file; 

    file = fopen("./file.txt", "r"); 

    size_t read; 
    char * line = NULL; 
    size_t line_len = 0; 

    size_t buffer_size = 10; 
    int * buffer = (int *)malloc(sizeof(int) * buffer_size); 

    int seek = 0; 
    while((read = getline(&line, &line_len, file)) != -1) { 
     buffer[seek++] = atoi(line); 

     if (seek % 10 == 0) { 
      buffer_size += 10; 
      buffer = (int *)realloc(buffer, sizeof(int) * buffer_size); 
     } 
    } 

    for (int i = 0; i < seek; i++) { 
     printf("%d\n", buffer[i]); 
    } 

    free(buffer); 
    fclose(file); 
} 

hinzufügen Wenn Sie nicht sicher sind, welche Konvertierungsfunktion sollten Sie . Sie können den Unterschied zwischen atoi und sscanf bei What is the difference between sscanf or atoi to convert a string to an integer?

+1

Ein paar Notizen, es gibt absolut ** no ** Fehlerprüfung von 'atoi', jeder nachfolgende Code, der auf' buffer [X] 'mit einem' unsigned' Wert im Bereich '0 - INT_MAX' hat keine Möglichkeit zu validieren, dass 'buffer [X]' einen gültigen Wert enthält. (besser, 'strtoul' mit Fehlerprüfung zu verwenden). Als nächstes riskiert die Zuweisung der Rückgabe von "realloc" an den Zeiger selbst (und nicht an einen "tmp" -Zeiger) das Erzeugen eines Speicherlecks, indem ein Verweis auf den ursprünglichen Speicherblock verloren geht. (besser: void * tmp = realloc (buffer, sizeof * buffer * buffer_size); if (tmp) buffer = tmp; '. (keine Notwendigkeit zu werfen) –

+0

@ DavidC.Rankin hat Recht, Sie könnten die Integrität der Konvertierung überprüfen Verwenden Sie 'sscanf' oder' strtoul'. Außerdem sollten Sie die Integrität der Zeiger überprüfen, um mögliche Leck- oder Speicherprobleme zu vermeiden. Danke David C. –

Verwandte Themen