2016-08-08 36 views
1

Ich habe diese Funktion, die das gesamte Array ia in eine Datei ‚Dateinamen‘ in einem JSON Textdatei Array Dateiformat namens speichert:Was unterscheidet dieses gespeicherte Array von dem geladenen Array?

int intarr_save_json(intarr_t* ia, const char* filename) 
{ 
    if(ia==NULL) 
    { 
     return 1; 
    } 
    int *arr=ia->data; 
    int n=ia->len; 
    int i; 
    FILE *p; 
    p=fopen(filename,"w"); 
    if(p!=NULL) 
    { 
     fprintf(p,"[\n"); 
     for(i=0;i<n;i++) 
     { 
      if(i!=n-1) 
      { 
       fprintf(p," %d,\n",arr[i]); 
      } 
      else 
      { 
       fprintf(p," %d\n",arr[i]); 
      } 
     } 
     fprintf(p,"]"); 
     fclose(p); 
     return 0; 
    } 
    return 1; 
} 

Und diese Funktion, lädt ein neues Array aus der Datei mit dem Namen ‚Dateinamen‘ , das war zuvor mit intarr_save() gespeichert.

intarr_t* intarr_load_json(const char* filename) 
{ 
    FILE* f = fopen(filename, "r"); 
    if (f == NULL) return NULL; 

    intarr_t* loaded = intarr_create(0); 

    int value; 
    //Get rid of [ 
    fscanf(f, "%c ", &value); 

    while (fscanf(f, "%d, ", &value)) { 
     if (value == ']') break; 
     intarr_push(loaded, value); 
    } 


    fclose(f); 
    return loaded; 
} 

Es scheint alles schön, aber aus irgendeinem Grunde, die Länge des geladenen Array ist nicht das gleiche wie die Länge des gespeicherten Array. Was könnte das verursachen?

EDIT: Jetzt ist meine Funktion ist wie dieser

int intarr_save_json(intarr_t* ia, const char* filename) 
{ 
    if(ia == NULL) 
    { 
     return 1; 
    } 
    int *arr=ia->data; 
    int n=ia->len; 
    int i; 
    FILE *p; 
    p=fopen(filename,"w"); 
    if(p!=NULL) 
    { 
     fprintf(p,"[\n"); 
     for(i=0;i<n;i++) 
     { 
      if(i!=n-1) 
      { 
       fprintf(p," %d,\n",arr[i]); 
      } 
      else 
      { 
       fprintf(p," %d\n",arr[i]); 
      } 
     } 
     fprintf(p,"]"); 
     fclose(p); 
     return 0; 
    } 
    return 1; 
} 

and 
intarr_t* intarr_load_json(const char* filename) 
{ 
    FILE* f = fopen(filename, "r"); 
    if (f == NULL) 
    { 
     return NULL; 
    } 

    intarr_t* loaded = intarr_create(0); 

    int value; 


    char line[100]; 
    while (fgets(line, 100, f)) 
    { 
     if (line[0] == ']') 
      { 
      break; 
      } 

     if (sscanf(line, "%d", &value) != 1) 
      { 
       break; 
      } 

    // Use the number 
    intarr_push(loaded, value); 
    } 

    fclose(f); 
    return loaded; 
} 

Aber jetzt ist die Last immer einen Null-Zeiger zurück. Was könnte das verursachen?

+1

Lassen Sie mich raten, ist das geladene Array * ein * kleiner als das eigentliche Array? Sehen Sie sich das Format an, das Sie an 'fscanf' übergeben, und beachten Sie, dass außer Sonderzeichen für zusätzliche Leerzeichen genau übereinstimmen müssen (einschließlich des Kommas in Ihrem Format). –

+0

'if (value == ']')' ist das selbe wie 'if (value == 93)' was ich irgendwie bezweifle was du wolltest. Also hörst du auf, Werte zu lesen, wenn ein 93 im Array ist. – immibis

+1

Sie können auch keine anderen Dateifehler vom 'fscanf'-Aufruf erkennen, da Sie nur eine Schleife ausführen, während' fscanf' ungleich Null zurückgibt. Wenn ein Fehler auftritt, wird 'fscanf'' EOF' zurückgeben, was "-1" ist. Außerdem wird "Wert" * niemals * gleich ""] sein, das Zeichen '']' ist keine Dezimalzahl, so dass' fscanf' es niemals im '"% d "' Format liest. Abschließend ein Wort der Warnung: Verwenden Sie kein nachstehendes Leerzeichen im 'scanf'-Format, es erfordert entweder das Dateiende oder etwas Nicht-Leerzeichen, das dem Leerraum folgt. Normalerweise funktioniert es gut für Dateien, aber nicht generell. –

Antwort

1

Die in

verwendete Logik
while (fscanf(f, "%d, ", &value)) { 
    if (value == ']') break; 

ist fehlerhaft.

Die letzten beiden Zeilen der Datei wird

<some number> 
] 

Der Aufruf von fscanf an dieser Linie scheitern. Daher werden Sie am Ende eine Nummer weniger lesen, als Sie in die Datei geschrieben haben.

Ich schlage vor, die Strategie ein wenig zu ändern.

// Read the contents of the file line by line 
// Process each line. 
char line[100]; 
while (fgets(line, 100, f)) 
{ 
    if (line[0] == ']') 
    { 
     break; 
    } 

    if (sscanf(line, "%d", &value) != 1) 
    { 
     break; 
    } 

    // Use the number 
    intarr_push(loaded, value); 
} 
+0

Interessant.Also das Problem ist nur mit der Ladefunktion, nicht mit der Speicherfunktion? Ich werde das überprüfen und sehen, wie es läuft. Es scheint vernünftig. Vielen Dank – Mil3d

+0

@ Mil3d, das ist meine Einschätzung. –

+0

Hey, ich habe meinen Code nach deinem Vorschlag geändert, aber jetzt gibt die Last immer einen Nullzeiger zurück. Weißt du, was das verursachen könnte? – Mil3d

0

Sie müssen einen nicht Leerzeichen nach jeder integer, lesen und aufhören zu lesen, wenn es sich um eine schließenden Klammer ']' statt Komma ',' ist. So sollte Ihre Leseschleife sein:

do { 
    char sep[2]; 
    int cr = fscanf(f, "%d%1s", &value, sep)) { /* read one value and the separator */ 
    if (cr != 2) { 
     /* signal the error, exit, ... */ 
    } 
    intarr_push(loaded, value); /* always push the value */ 
} while (sep[0]== ']') break; /* loop until the separator if a ] */