2016-11-28 61 views
2

數組我試圖通過fscanf讀取文件test.txt並將其存儲在結構數組中。這是我試過的。這裏的問題是fscanf不能正常工作。閱讀文件後,我也試圖在屏幕上打印它,但它不起作用。C編程:讀取文件並存儲在struct

#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文件:

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

錯誤:計劃與一些警告編譯,但我得到段錯誤當我執行的代碼。

任何想法爲什麼?

輸出期望:OUTPUT應該從test.txt文件中讀取並顯示在屏幕上。

+3

也許是因爲 「約翰」 是不正確;那就是「Jon」Snow ... –

+0

@ringø哈哈:D:D:D – John

+0

您必須調試程序以查看發生錯誤的位置(閱讀或顯示),並查看是否得到您認爲應該得到的結果。 – Phil1970

回答

2

在節目多問題:

1.

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

fopen返回一個FILE*,而不是一個char,使用

FILE* ck = fopen(...); 

2.

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

你可以試試這個不同的方法。

它使用:

  • mallocrealloc分配和用於結構的數組重新分配存儲器。我認爲使用更多行的更大的文本文件將被使用,並且這允許數組在需要時調整大小以容納更多信息。
  • 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); 
    } 
}