2010-10-07 63 views
2

我有表單數據的文本文件:將這行文本讀入結構的最簡單方法是什麼?

Lee AUS 2 103 2 62 TRUE 
Check AUS 4 48 0 23 FALSE 
Mills AUS 8 236 0 69 FALSE 

我需要各行成一個結構等,然而,我想爲儘量避免使用固定長度陣列(用於fgets問題我可以告訴):

struct Data 
{ 
    char *sname; 
    char *country; 
    int *a; 
    int *b; 
    int *c; 
    int *d; 
    char *hsisno; 
}; 

我對C.很新。我應該使用fscanf還是fgets?

+0

我通常使用strtok的,但有可能是一個更好的辦法 – GWW 2010-10-07 02:51:07

回答

4

fscanf代表「格式化文件掃描」和用戶數據大約是格式化,你可以得到。

你不應該使用的數據裸體"%s"格式字符串,你不必在什麼可以讀的絕對控制權。

最好的解決方案是使用fgets讀取線,因爲這可以讓你避免緩衝區溢出。

然後,一旦你知道你行的大小,這是每一個你將需要串的最大尺寸。使用sscanf來獲取實際字段。

的最後一件事。因爲你知道它們已經有了一個特定的最大尺寸,所以整數類型可能有點浪費。我會使用非指針變種,是這樣的:

struct Data { 
    char *sname; char *country; 
    int a; int b; int c; int d; 
    char *hsisno; 
}; 

舉例來說,這裏的一些安全代碼:

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

// Here's all the stuff for a linked list of your nodes. 

typedef struct sData { 
    char *sname; char *country; char *hsisno; 
    int a; int b; int c; int d; 
    struct sData *next; 
} Data; 
Data *first = NULL; Data *last = NULL; 

#define MAXSZ 100 
int main (void) { 
    char line[MAXSZ], sname[MAXSZ], country[MAXSZ], hsisno[MAXSZ]; 
    int a, b, c, d; 
    FILE *fIn; 
    Data *node; 

    // Open the input file. 

    fIn = fopen ("file.in", "r"); 
    if (fIn == NULL) { 
     printf ("Cannot open file\n"); 
     return 1; 
    } 

    // Process every line. 

    while (fgets (line, sizeof(line), fIn) != NULL) { 
     // Check line for various problems (too short, too long). 

     if (line[0] == '\0') { 
      printf ("Line too short\n"); 
      return 1; 
     } 

     if (line[strlen (line)-1] != '\n') { 
      printf ("Line starting with '%s' is too long\n", line); 
      return 1; 
     } 

     line[strlen (line)-1] = '\0'; 

     // Scan the individual fields. 

     if (sscanf (line, "%s %s %d %d %d %d %s", 
      sname, country, &a, &b, &c, &d, hsisno) != 7) 
     { 
      printf ("Line '%s' didn't scan properly\n", line); 
      return 1; 
     } 

     // Allocate a new node to hold data. 

     node = malloc (sizeof (Data)); 
     if (node == NULL) { 
      printf ("Ran out of memory\n"); 
      return 1; 
     } 

     node->sname = strdup (sname); 
     node->country = strdup (country); 
     node->a = a; 
     node->b = b; 
     node->c = c; 
     node->d = d; 
     node->hsisno = strdup (hsisno); 
     node->next = NULL; 
     if (first != NULL) { 
      last->next = node; 
      last = node; 
     } else { 
      first = node; 
      last = node; 
     } 
    } 

    fclose (fIn); 

    // Output the list for debugging. 

    node = first; 
    while (node != NULL) { 
     printf ("'%s' '%s' %d %d %d %d '%s'\n", 
      node->sname, node->country, node->a, node->b, 
      node->c, node->d, node->hsisno); 
     node = node->next; 
    } 

    return 0; 
} 

它在讀取文件,並將其存儲鏈表。它輸出:

'Lee' 'AUS' 2 103 2 62 'TRUE' 
'Check' 'AUS' 4 48 0 23 'FALSE' 
'Mills' 'AUS' 8 236 0 69 'FALSE' 

最後,如預期。


我已經做了一系列的答案對使用非控制數據*scanf功能(輸入user:14860 fgets到搜索框上方)的缺陷,其中一些(hereherehere,例如)包括我的常年最喜歡的功能,getLine,用於更安全的用戶輸入。

+0

謝謝。但是fgets不需要你知道你的行的大小,因爲它需要緩衝區大小參數? – 2010-10-07 03:04:49

+0

通常人們使用的尺寸比他們預期在文件中發生的尺寸要大。 – GWW 2010-10-07 03:12:12

+0

好吧,那就是我要做的事情,但認爲這是一個很糟糕的代碼味道。 – 2010-10-07 03:16:14

相關問題