2016-04-07 23 views
1

Cを使用して.txtファイルを2重配列に解析するコードを作成しました。各ポイントを"、"で区切ってフォーマットしました。今、私はこのコードを.csvファイルから同じデータを解析するようにします。ファイルタイプを変更すると、セグメント化エラーが発生します。.txtと.csvの解析C

これはなぜ発生するのですか?これらの2つのドキュメントタイプが同じ方法で読み取られると信じて間違っていますか?

この記事の主な質問は、.txtと.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

文字列からスキャンするために 'sscanf'を使うだけで、何らかのRegexをサポートしています。http://www.cplusplus.com/reference/cstdio/scanf/ – k06a

+0

あなたの.txtと.txtを比較することをお勧めします。 CSVファイル。私はそれらがファイル名の拡張子を除いてあらゆる点で同一でなければならないと思うでしょう、あなたのコードが1つのために働くならば、それは他のもののために働くはずです。 – Logicrat

+0

[Strcpyを使わないでください](http://stackoverflow.com/questions/5122882/strcpy-string-array)[strcpyのマニュアルページ](http://linux.die.net/man/3/strcpy)なぜそれを避けたいのでしょうか? –

答えて

0

for(k = 0; k < 361; k++) 
{ 
    val = atof(result[k]); 
    cal[k] = val; 
} 
はあなたが置くためにデータを持っているときにのみ結果配列の要素にメモリを割り当てる
配列「結果」の境界の外に起こっているこのコードでコンバージョンatofそれ

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

未満361件のレコードが作成された場合は、una​​llから読んでいますしたがって、エラーです。

結果の配列を処理する際に、読み取った結果の数を記録し、その値を使用して範囲内に収まるようにする必要があります。

ファイル拡張子に基づいてファイル間に違いはありません。

2

問題はファイルの名前ではなく、ファイルの内容が異なることです。その異なるコンテンツは、あなたのコードのメモリの問題を露呈しています。

私の目はすぐにどこでもハードコード361になります。これは、入力ファイルに361行があることを前提としており、segfaultがあります。 val = atof(result[k]);result配列から離れたときに、40行目(valgrindを使用して識別されます)で発生します。ハードコードのサイズは、でCの中では非常に魅力的ですです。特に入力のために、それをしないでください。あなたが信頼できない松葉杖です。

代わりに、コードはファイル内のフィールドと行の数に適応する必要があります。 reallocを使って独自の動的配列コードを書くこともできますが、これを行うCライブラリがたくさんあります。私は基本についてはGLibに達しています。

もう1つの問題は、各行に10バイトしか割り当てられていないことです。これは非常に小さいです。 fgetsは、それが9文字より長い場合、常にlineから歩いていきます。入力から読み込むときの静的なメモリ割り当ては問題になります。 fgetsの代わりにgetlineを使用すると、1行にどれだけのメモリを割り当てるかの問題が回避されます。 getlineがこれを担当します。 getlinelineを再利用するように注意してください。lineを変更する場合は、最初にstrdupにする必要があります。

/* 
* 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; 

} 

それが主な問題から気晴らしだので、私はatof変換を剥ぎ取ってきました。あなたが好きなら、それを戻すことができます。

これは、まだ各行の最初のセルだけを読み取るという問題があります。私はあなたにそれを固定しておきます。