2014-06-09 62 views
1

我是C編程新手,我想嘗試從CSV文件讀取並將其打印出來。我的CSV文件中的格式:從具有結構數組的CSV文件讀取

指數,國家,年死亡率

1世界

  50s  36 
     60s  29 
     70s  22 

2非洲

  50s  34 

209湯加

  50s  49 
     60s  67 

等等......

我不知道如何閱讀我的CSV文件的末尾,所以我的代碼輸出只打印到索引143,而我當前的CSV文件打印到204.任何人都可以用這個指導我嗎?

void readRecords(){ 
    FILE *fptr; 
    int i,j,k; 
    char line[200], hold[10]; 

    if((fptr=fopen("data.csv","r"))==NULL){ 
     printf("Cannot open input file data.csv\n"); 
    } 

    else{ 
     for(i=0;i<999;i++){ 
      fgets(line, 200, fptr); 

      j=0; 
      k=0; 
      while (line[j] != ','){  // This while loop extract the country name until a comma is detected 
       hold[k++] = line[j++]; // Simply copy all character from each line to the country 
      } 
      hold[k]='\0'; 
      myRecords[i].index=atoi(hold); 
      j++; 


      k=0; 
      while (line[j] != ','){  // This while loop extract the country name until a comma is detected 
       myRecords[i].country[k++] = line[j++]; // Simply copy all character from each line to the country 
      } 
      myRecords[i].country[k]='\0'; 
      j++; 


      k=0; 
      while (line[j] != ','){  // This while loop extract the country name until a comma is detected 
       hold[k++] = line[j++]; // Simply copy all character from each line to the country 
      } 
      hold[k]='\0'; 
      myRecords[i].year=atoi(hold); 
      j++; 


      k=0; 
      while (line[j] != ','){  // This while loop extract the country name until a comma is detected 
       hold[k++] = line[j++]; // Simply copy all character from each line to the country 
      } 
      hold[k]='\0'; 
      myRecords[i].deathrate=atoi(hold); 
      j++; 

     } 

     } 
     fclose(fptr); 
    } 
+0

我想使用EOF來讀取CSV文件的末尾,但我不知道如何實現它。 –

+0

當文件結束時,'fgets'返回NULL。檢查並從循環中分離出來。一般來說,所有的文件讀取函數都有一個特殊的返回值,表示文件的結尾,通常是NULL或特殊(整數)值EOF。 –

+0

另外,小心不要溢出'hold'。10個字符應該足以保存整數,但是對於外部輸入,您不能依賴它。 –

回答

0

另一種選擇是簡單地通過fgetsgetline的指針讀取踩線,並與\0字符替換逗號的和不斷的讀取每個變量在您工作的路線。下面是一個工作實現給定的數據文件:

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

int main (int argc, char *argv[]) { 

    if (argc < 2) { 
     fprintf (stderr, "error: insufficient input, usage: %s <filename>\n", argv[0]); 
     return 1; 
    } 
    FILE *fptr; 
    char *line = NULL; 
    size_t len = 0; 
    ssize_t read; 
    char *p = NULL; 
    char *start = NULL; 

    int index = 0; 
    char *country; 
    int years = 0; 
    int deaths = 0; 

    if ((fptr=fopen (argv[1],"r")) == NULL) { 
     fprintf(stderr, "Cannot open input file %s\n", argv[1]); 
    } 

    while ((read = getline(&line, &len, fptr)) != -1) 
    { 
     p = line; 

     while (*p != ',' && *p != 0) p++; 
     *p = '\0'; 
     index = atoi (line); 
     start = ++p; 
     while (*p != ',' && *p != 0) p++; 
     *p = '\0'; 
     country = strdup (start); 
     start = ++p; 
     while (*p != ',' && *p != 0) p++; 
     *p = '\0'; 
     years = atoi (start); 
     start = ++p; 
     deaths = atoi (start); 

     printf ("idx: %3d country: %12s years: %3d deaths: %3d\n", 
       index, country, years, deaths); 
    } 

    free(line); 

    return 0; 
} 

現在,給定一個輸入.csv文件格式:

1,world,50s,36 
1,world,60s,65 
1,world,70s,58 
2,africa,50s,37 
2,africa,60s,66 
2,africa,70s,59 
207,tonga,50s,37 
207,tonga,60s,66 
207,tonga,70s,59 

你的輸出將是:

idx: 1 country:  world years: 50 deaths: 36 
idx: 1 country:  world years: 60 deaths: 65 
idx: 1 country:  world years: 70 deaths: 58 
idx: 2 country:  africa years: 50 deaths: 37 
idx: 2 country:  africa years: 60 deaths: 66 
idx: 2 country:  africa years: 70 deaths: 59 
idx: 207 country:  tonga years: 50 deaths: 37 
idx: 207 country:  tonga years: 60 deaths: 66 
idx: 207 country:  tonga years: 70 deaths: 59 

這只是大概就這麼簡單。使用strtok或者只是沿緩衝區走,然後直接讀取你需要的內容。如果您花時間仔細閱讀代碼。你會看到它所做的只是讀取一個逗號,用\0替換逗號,從開始(或開始)讀取以獲取所需信息,將指針前進1,設置新的「開始」點,然後在緩衝區中一直重複。讀完'死亡'後,最後一個循環確保讀取了該行中的所有字符。 getline讀取下一行並繼續,直到.csv文件中無法讀取更多行。我希望這有幫助。 (如果不是很明顯,你給它的命令行上的CSV文件名:

$ readcsv dat.csv 

你已經擁有的數據並將其解析爲在上述變量如果你想使用的結構,你可以簡單地從公共變量的存儲類型更改爲一個結構數據類型。類似於下面的作品東西結構數組。

int recs = 0; 

struct _stats { 
    int index; 
    char *country; 
    int years; 
    int deaths; 
}; 

struct _stats *stats[100]; 
struct _stats *statsptr = NULL; 

if ((fptr=fopen (argv[1],"r")) == NULL) { 
    fprintf(stderr, "Cannot open input file %s\n", argv[1]); 
} 

while ((read = getline(&line, &len, fptr)) != -1) { 

    p = line; 
    statsptr = malloc (sizeof (struct _stats)); 

    while (*p != ',' && *p != 0) p++; 
    *p = '\0'; 
    statsptr->index = atoi (line); 
    start = ++p; 

    while (*p != ',' && *p != 0) p++; 
    *p = '\0'; 
    statsptr->country = strdup (start); 
    start = ++p; 

    while (*p != ',' && *p != 0) p++; 
    *p = '\0'; 
    statsptr->years = atoi (start); 
    start = ++p; 

    statsptr->deaths = atoi (start); 

    stats[recs] = statsptr; 
    recs++; 

} 

int iter = 0; 
for (iter = 0; iter < recs; iter++) { 
    printf ("idx: %3d country: %12s years: %3d deaths: %3d\n", 
      stats[iter]->index, 
      stats[iter]->country, 
      stats[iter]->years, 
      stats[iter]->deaths); 
} 

除了最初宣佈指針的最大數量結構,則需要使用一個動態數據類型就像一個鏈表(超出了本討論的範圍)

+0

嗯,但事情是我正在使用一個結構,以便我可以稍後添加更多的輸入到以下數據並再次顯示它。 –

+0

我會使用一個結構。事實上,我會將數據讀入鏈表。這樣可以事先掌握數據集大小,因爲您可以在每個「getline」後動態分配數據集。可以使用指向結構數組的指針,或者添加一個指向'struct-next'的額外指針並將其稱爲鏈接列表。 –