2016-07-24 13 views
0

Sagte ich habe eine Datei mit einer nicht spezifizierten Größe von Doppel Zahlen.Wie liest man Werte aus einer nicht spezifizierten Dateigröße und speichert sie dynamisch in einem Vektor in C?

Ich muss diese Werte dynamisch in einem double *note Zeiger für die spätere Verwendung speichern.

habe ich versucht, den folgenden Code, aber es gibt core dumped:

FILE *ifile = fopen("numbers.txt", "r"); 
double *note; 
int i = 1; 

note = (double *) malloc(i * sizeof(double)); 
fscanf(ifile, "%lf", &note[0]); 

while (!feof(ifile)) { 
     i++; 
     note = (double *) realloc(note, i * sizeof(double)); 
     fscanf(ifile, "%lf", &note[i]); 
}  

for (n=0; n < i; n++) { 
    printf("%lf\n", note[i]); 
} 
+2

[ 'while (! Feof (...))' ist immer falsch] (http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) . – melpomene

+0

Der Note [1] wird kein Wert zugewiesen. –

+0

@SergeBallesta die Übung spezifiziert, einen Vektor mit einer begrenzten großen Größe nicht zu verwenden. – ovrwngtvity

Antwort

0

Ihr i von 0 bis 2 geht, und Ihr Index ist permanent aus Ihrer Grenze: Sie zuteilen 2 Doppelzimmer, und schreiben in Index 2 welches ist das dritte. Vergessen Sie auch nicht, Ihre Datei zu schließen. UND der endgültige Druck verwendet ich, wo es n verwenden soll. Es ist nicht gut, gewöhnliche Buchstaben zu mischen (i für den Schleifenindex und n für die Grenze), am Ende werden alle verwirrt.

Es ist besser, zu vereinfachen/faktorisieren Ihr Code wie folgt, die den Fehler vermeidet:

Als Bonus habe ich einen Mechanismus hinzugefügt, die Neuzuweisung jedes Mal vermeidet, die nicht sehr gut leistungsmäßig ist.

Der folgende Code wurde getestet und arbeitet

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

int main() 
{ 
FILE *ifile = fopen("numbers.txt", "r"); 
double v,*note=NULL; 
int i = 0,n; 
int alloc_step = 10; 
int note_size = 0; 

while (!feof(ifile)) { 
     fscanf(ifile, "%lf", &v); 
     if ((i % alloc_step)==0) 
     { 
      note_size += alloc_step; 
      note = (double *) realloc(note, note_size * sizeof(double)); 
     } 
     note[i++] = v; 

}  

for (n=0; n < i; n++) { 
    printf("%lf\n", note[n]); 
} 
fclose(ifile); 
} 
+0

Ich habe den Code geändert, aber es funktioniert nicht. Es gibt Kern gedumpt. Ich habe alles überprüft, aber es scheint nicht zu funktionieren. – ovrwngtvity

+0

Überprüfen Sie meine letzte Änderung –

1

Ihr Code das Array aus seinen Grenzen zugreift jedes Mal note[i] verwendet wird.

Im (wrong) while-Schleife ist es immer ein nach dem letzten Element (zum Beispiel in der ersten Iteration i wird 2, genug Platz für zwei double s zugeordnet ist, aber Sie Zugriff note[2] die die dritte ist).

Während des Druckens verwenden Sie n als steigenden Schleifenindex, aber drucken Sie immer note[i] anstelle von note[n].

Es wäre auch eine gute Praxis, die Rückgabewerte aller Bibliotheksfunktion verwendet werden, wie open, new, realloc und scanf zu überprüfen.

Eine schnelle Lösung dieser Probleme könnte das folgende Snippet sein. Bitte beachten Sie, dass ich die gleiche Neuzuweisungsstrategie wie Ihre verwendet habe (jedes Mal), aber wie @Serge Ballesta darauf hingewiesen hat, kann dies ineffizient sein. Schauen Sie sich die Alternative in @ Jean-François Fabre zum Beispiel an.

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

int main() { 
    double value, 
      *note = NULL, 
      *newptr = NULL; 

    int i, 
     size = 0; 

    char file_name[] = "numbers.txt"; 
    FILE *ifile = fopen(file_name, "r"); 
    if (!ifile) { 
     fprintf(stderr, "Error while opening file %s.\n", file_name); 
     exit(EXIT_FAILURE); 
    } 

    while (fscanf(ifile, "%lf", &value) == 1) { 
     size++; 
     newptr = realloc(note, size * sizeof(double)); 
     if (!newptr) { 
      fprintf(stderr, "Error while reallocating memory.\n"); 
      free(note); 
      exit(EXIT_FAILURE); 
     } 
     note = newptr; 
     note[size - 1] = value; 
    }  

    for (i=0; i < size; i++) { 
     printf("%lf\n", note[i]); 
    } 

    free(note);  // <-- don't leak memory! 
    fclose(ifile); 
    return EXIT_SUCCESS; 
}