2016-04-07 7 views
1

Ich habe einen Code erstellt, der eine TXT-Datei mit C in ein Doppel-Array zerlegt. Meine .txt-Datei ist so formatiert, dass jeder der Punkte durch "," begrenzt wird. Jetzt möchte ich, dass dieser Code die gleichen Daten parst, aber aus einer .csv-Datei. Wenn ich meinen Dateityp ändere, erhalte ich einen Segmentierungsfehler..txt vs .csv Parsing C

Warum tritt dies auf? Habe ich einen falschen Eindruck, dass diese beiden Dokumenttypen auf dieselbe Art und Weise gelesen werden?

Die Hauptfrage dieses Beitrags ist, was ist der Unterschied beim Lesen einer .txt und einer .csv?

/* 
* Calibration File Read Test 
*/ 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 

int main() 
{ 
    FILE *myfile = fopen ("BarEast.txt", "r"); 
    /* I want to change this file type to .csv */ 

    /* opening file for reading */ 
    if(myfile == NULL) 
    { 
     printf("Error opening file"); 
     return(-1); 
    } 

    int i = 0; 
    int j, k; 

    char *result[361] = {0}; 
    char line[10]; 
    char *value; 

    while(fgets(line, sizeof(line), myfile)) 
    { 
     value = strtok(line, ","); 
     result[i] = malloc(strlen(value) + 1); 
     strcpy(result[i], value); 
     i++; 
    } 

    double val; 
    double cal[361] = {0}; 

    for(k = 0; k < 361; k++) 
    { 
     val = atof(result[k]); 
     cal[k] = val; 
    } 

    for(j = 0; j < 361; j++) 
    { 
     printf("Element[%d] = %f\n", j, cal[j]); 
    } 
    fclose(myfile); 
    return 0; 

} 
+0

Verwenden Sie einfach 'sscanf', um aus einer Zeichenkette zu scannen, die eine Art Regex unterstützt, lesen Sie hier: http://www.cplusplus.com/reference/cstdio/scanf/ – k06a

+0

Ich würde vorschlagen, dass Sie Ihre .txt und. CSV-Dateien. Ich würde denken, dass sie in jeder Hinsicht identisch sein sollten, außer für die Dateinamenerweiterung, und wenn Ihr Code für einen funktioniert, sollte er für den anderen funktionieren. – Logicrat

+0

[Strcpy nicht verwenden] (http://stackoverflow.com/questions/5122882/strcpy-string-array) Wenn Sie die Notizen in der [man page for strcpy] (http://linux.die.net/man/3/strcpy) es macht Sinn, warum du dich davon fern halten willst. –

Antwort

0

Ihre Conversion atof in diesem Code

for(k = 0; k < 361; k++) 
{ 
    val = atof(result[k]); 
    cal[k] = val; 
} 

ist außerhalb der Grenzen des Arrays ‚Ergebnis‘ gehen
Sie nur Speicher in dem Ergebnis-Array zuweisen, wenn Sie Daten setzen in es

result[i] = malloc(strlen(value) + 1);

Wenn weniger als 361 Datensätze erstellt wurden Sie von unall lesen ocated Speicher - daher der Fehler.

Sie müssen notieren, wie viele Ergebnisse Sie eingelesen haben, und dann diesen Wert verwenden, um sicherzustellen, dass Sie bei der Verarbeitung des Ergebnisarrays in Reichweite bleiben.

Es gibt keinen Unterschied zwischen Dateien basierend auf der Dateierweiterung.

2

Das Problem ist nicht der Name der Datei, es ist, dass die Dateien unterschiedlichen Inhalt haben. Dieser unterschiedliche Inhalt macht die Speicherprobleme in Ihrem Code verfügbar.

Sofort geht mein Auge auf die hartcodierte 361 überall. Dies setzt voraus, dass in der Eingabedatei 361 Zeilen stehen und dass Ihr Segfault vorhanden ist. Es passiert in Zeile 40 (identifiziert mit valgrind), wenn val = atof(result[k]); aus dem result Array geht. Es ist sehr verlockend in C zu harten Codegrößen. Tun Sie es nicht, vor allem für die Eingabe, es ist eine Krücke, auf die Sie sich nicht verlassen können.

Stattdessen muss der Code an die Anzahl der Felder und Zeilen in der Datei angepasst werden. Sie können Ihren eigenen dynamischen Array-Code mit realloc schreiben, aber es gibt viele C-Bibliotheken, die dies für Sie tun werden, und viel besser. Ich erreiche für GLib für die Grundlagen.

Ein weiteres Problem ist, dass Sie nur 10 Bytes für jede Zeile zugewiesen haben. Das ist sehr klein. Es bedeutet fgets ist ständig von line gehen, wenn es länger als 9 Zeichen (was es sein wird). Jede Art von statischer Speicherzuweisung beim Lesen von Eingabe wird ein Problem sein. Die Verwendung von getline anstelle von fgets vermeidet das Problem, wie viel Speicher pro Zeile zugewiesen werden muss. getline kümmert sich darum für Sie. Seien Sie vorsichtig, getline wiederverwendet line, wenn Sie also line ändern möchten, müssen Sie zuerst strdup es.

/* 
* Calibration File Read Test 
*/ 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <glib.h> 

int main (int argc, char **argv) 
{ 
    /* Check we got the right number of arguments. */ 
    if(argc != 2) { 
     fprintf(stderr, "Usage: %s <filename>\n", argv[0]); 
     return -1; 
    } 

    /* Open the file */ 
    FILE *fp = fopen (argv[1], "r"); 
    if(fp == NULL) 
    { 
     fprintf(stderr, "Error opening file %s for reading.\n", argv[1]); 
     return(-1); 
    } 

    /* A dynamic array which will grow as needed */ 
    GArray *result = g_array_new(TRUE, TRUE, sizeof(char *)); 

    /* Read each line using getline which does the line memory allocation 
     for you. No buffer overflow to worry about. */ 
    char *line = NULL; 
    size_t linecap = 0; 
    while(getline(&line, &linecap, fp) > 0) { 
     /* This will only read the first cell. Exercise left for the reader. */ 
     char *value = strtok(line, ","); 
     if(value == NULL) { 
      fprintf(stderr, "Could not parse %s\n", line); 
      continue; 
     } 

     char *field = malloc(strlen(value) + 1); 
     strcpy(field, value); 

     g_array_append_val(result, field); 
    } 

    free(line); 
    fclose(fp); 

    /* Iterate through the array using result->len to know the length */ 
    for(int i = 0; i < result->len; i++) 
    { 
     printf("Element[%d] = %s\n", i, g_array_index(result, char *, i)); 
    } 

    /* Free the array */ 
    g_array_free(result, TRUE); 

    return 0; 

} 

Ich habe die atof Umwandlung, weil es eine Ablenkung von dem Hauptproblem abgezogen. Sie können das zurückstellen, wenn Sie möchten.

Dies hat immer noch das Problem, dass es nur die erste Zelle jeder Zeile liest. Ich überlasse es dir das zu tun.