2016-11-28 92 views
2

私はfscanfでtest.txtファイルを読み込み、構造体の配列に格納しようとしています。これが私が試みたものです。ここでの問題は、fscanfが想定どおりに動作していないことです。ファイルを読み込んだ後、画面に印刷しようとしていますが、動作しません。Cプログラミング:ファイルを読み込んで構造体の配列に格納する

205,11.20,John Snow 
336,23.40,Winter is coming 
220,34.20,You know nothing 

エラー:プログラムは、いくつかの警告をコンパイルし、私はコードを実行するとき、私はセグメンテーションフォールトを取得

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

struct Item { 
    double value; 
    int unit; 
    char name[50]; 
}; 

int load(struct Item* item, FILE* data); 
void display(struct Item item, int variableA); 

int main() 
{ 
    struct Item I; 
    int i; 
    char ck; 
    ck = fopen("test.txt", "r"); 
    if (ck) 
    { 
    for (i = 0; i < 3; i++) 
    { 
     load(&I, ck); 
     display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS 
    } 
    fclose(ck); 
    } 
return 0; 
} 


int load(struct Item* item, FILE* data) 
{ 
    fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name); 
    return 0; 
} 

void display(struct Item item, int variableA) 
{ 
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name); 
return; 
} 

これは私がtest.txtというファイルに持っているものです。

理由は何ですか?

出力期待値:OUTPUTは、test.txtファイルから読み込まれ、画面に表示される必要があります。プログラムで

+3

。それは "Jon"スノー... –

+0

@ringøhaha:D:D:D – John

+0

エラーが発生する場所(読み込み中または表示中)を確認するためにプログラムをデバッグする必要があります。 – Phil1970

答えて

2

複数の問題:

char ck; 
ck = fopen("test.txt", "r"); 

fopen戻りFILE*、ないchar

FILE* ck = fopen(...); 
fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name); 
を使用

の戻り値が常にfscanfであることを確認します。要求されたフィールドの数よりも小さい場合は、fscanfへの次の呼び出しは期待したことを起こしそうにありません。また、*item.unitは、それが短く、きれいなのでitem->unitを使用し、item->unitと同じです:

int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value); 
if (ret != 3) { // error } 

第三に、%sは非空白文字のシーケンスと一致するので、fscanfは「ジョン」を読み出す際に、それが停止しますそして次のfscanfコールは、整数を期待している間に "Snow"を読み込むでしょう。

したがって、空白文字列を入力するには、代わりにfgetsを使用し、最後に改行文字を削除してください。

は、次の試してみてください。

int main(void) 
{ 
    struct Item I; 
    int i; 
    FILE* ck; 
    int ret; 
    ck = fopen("test.txt", "r"); 
    if (ck) 
    { 
      for (i = 0; i < 3; i++) 
      { 
        ret = load(&I, ck); 
        if (ret < 0) 
          break; 
        display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS 
      } 
      fclose(ck); 
    } 
    return 0; 
} 

int load(struct Item* item, FILE* data) 
{ 
    int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value); 
    if (ret != 2) { 
      return -1; 
    } 
    fgets(item->name, sizeof item->name, data); 
    item->name[strlen(item->name)-1] = '\0'; 
    return 0; 
} 

void display(struct Item item, int variableA) 
{ 
    printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name); 
    return; 
} 

それは出力:

$ ./a.out 
|205 |  11.20|   John Snow |*** 
|336 |  23.40|  Winter is coming |*** 
|220 |  34.20|  You know nothing |*** 
+0

Ty。 :) – John

+0

私はまだ黒の出力を取得します。 – John

+0

@John貼り付けたコードを使っていましたか? – fluter

0

あなたはこの異なるアプローチを試すことができます。

これは使用:

    malloc
  • reallocを構造体の配列にメモリを割り当て、再割り当てします。私は、より多くの行を含むはるかに大きなテキストファイルが使用されると仮定し、これは、より多くの情報に対応するために必要なときに配列のサイズを変更できるようにします。
  • strtok,デリメータの間のデータの各ピースを解析し、それらを構造体の配列に格納します。
  • セグメンテーションフォルトを避けるためにポインタの戻り値をチェックします。
  • fgetsを使用して、ファイルの各行を文字列に読み取ってから、後で解析することができます。

これは、提案されたコードです: "ジョン" は正しくないため、多分

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

#define NAMESTRLEN 50 
#define INITSIZE 3 
#define MAXSIZE 100 

typedef struct { 
    int unit; 
    double value; 
    char name[NAMESTRLEN+1]; 
} item_t; 

typedef struct { 
    item_t *items; 
    int numlines; 
} allitems_t; 

allitems_t *initialize_arraystructs(void); 
void print_arraystructs(allitems_t *allitems); 
void read_insert_items(FILE *filestream, allitems_t *allitems); 
void check_ptr(void *ptr, const char *msg); 

int 
main(void) { 
    allitems_t *allitems; 
    FILE *fp; 

    fp = fopen("test.txt", "r"); 
    if (fp == NULL) { 
     fprintf(stderr, "%s\n", "Error reading file!\n"); 
     exit(EXIT_FAILURE); 
    } 

    allitems = initialize_arraystructs(); 

    read_insert_items(fp, allitems); 

    print_arraystructs(allitems); 

    return 0; 
} 

void 
read_insert_items(FILE *filestream, allitems_t *allitems) { 
    int count = 0; 
    char line[MAXSIZE]; 
    char *unit, *value, *name; 
    size_t numitems = INITSIZE; 

    allitems->items = malloc(numitems * sizeof(item_t)); 
    check_ptr(allitems->items, "Initial Allocation"); 

    while (fgets(line, MAXSIZE, filestream) != NULL) { 
     unit = strtok(line, ","); 
     value = strtok(NULL, ","); 
     name = strtok(NULL, "\n"); 

     if (count == numitems) { 
      numitems *= 2; 
      allitems->items = realloc(allitems->items, numitems * sizeof(item_t)); 
      check_ptr(allitems->items, "Reallocation"); 

     } 

     allitems->items[count].unit = atoi(unit); 
     allitems->items[count].value = atof(value); 
     strcpy(allitems->items[count].name, name); 

     count++; 
     allitems->numlines++; 
    } 
} 

allitems_t 
*initialize_arraystructs(void) { 
    allitems_t *allitems; 

    allitems = malloc(sizeof(allitems_t)); 
    check_ptr(allitems, "Initial Allocation"); 

    allitems->items = NULL; 
    allitems->numlines = 0; 

    return allitems; 
} 

void 
print_arraystructs(allitems_t *allitems) { 
    int i; 

    for (i = 0; i < allitems->numlines; i++) { 
     printf("%d,%.2f,%s\n", 
       allitems->items[i].unit, 
       allitems->items[i].value, 
       allitems->items[i].name); 
    } 
} 

void 
check_ptr(void *ptr, const char *msg) { 
    if (!ptr) { 
     printf("Unexpected null pointer: %s\n", msg); 
     exit(EXIT_FAILURE); 
    } 
} 
関連する問題