将文本文件读入C中的数据结构

时间:2012-10-18 14:00:36

标签: c data-structures file-io

  

可能重复:
  C, reading from file into structure

我需要读取一个大文本文件,然后填写邮件列表的数据结构。

数据结构如下:

typedef struct mentry {
    char *surname;
    int house_number;
    char *postcode;
    char *full_address;
} MEntry;

,文本文件格式为:

Bloggs, Joe  
1 Street Name, City  
M53 3JK  
Surname, Firstname  
University of Nowhere, City  
G44 3GB

我的数据结构构造函数:

/* me_get returns the next file entry, or NULL if end of file*/
MEntry *me_get(FILE *fd);

返回指向包含邮件列表条目的MEntry结构的指针。

到目前为止,我只是设法逐行读取文件。

#define MAXLINE 1024

int main(){
    char line[MAXLINE];
    FILE *fp = fopen("S.txt","r");

    while(fgets(line,MAXLINE,fp))
        {
        printf("%s %d",line,linecount);
    }

    fclose(fp);
    return 0;
}

目前我的主要问题是我不知道如何分割我的线条以便我可以正确地填充我的数据结构。我想知道在一段时间内使用fgetc读取一个字符会比阅读整行然后尝试拆分它更容易吗?

3 个答案:

答案 0 :(得分:2)

可能你应该使用 strtok

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

int main ()
{
    char str[] ="Elizarraras, Salvador, UG";
    char *token = NULL;
    int n_tokens = 0;

    printf ("Get tokens from string \"%s\"\n",str);
    printf("%s\n", "*********************************************");

   // Split the string into tokens delimited by spaces and commas
   token = strtok (str," ,");
   while (token != NULL)
   {
       printf("%s\n", token);
       // Different call
       token = strtok (NULL, " ,");
       n_tokens++;
   }

  return 0;
}

<强>输出:

Get tokens from string "Elizarraras, Salvador, UG"

*********************************************
Elizarraras

Salvador

UG

有一篇关于这个主题的有趣文章Finding Tokens in a String

答案 1 :(得分:0)

在您的示例中,第二个地址没有任何house_number

这意味着您不能依赖数据格式来盲目读取文件。

您别无选择,只能读取数据然后解析它。

如果地址在指定postcode之前有2行文字,则可能会发生其他问题。

您是唯一知道输入文件可靠性的人,因此必须应用哪些规则来解析它而不会出错。

关于这个方法,我会逐行读取文件并通过解析每一行文本来解释它,直到找到每个记录的postcode(因为这似乎是你的结束记录标记)。

解析意味着查看line[]个字符并在读取数据时对数据进行分类(即:逗号是名字/姓氏的分隔符,街道号码是数字,邮政编码是否遵循某种格式,等)。

这需要一些工作,但这是可行的。根据品味,您了解我不会冒险进入RegEx区域(而C有一个专用的运行时库)。

Goog运气好!

答案 2 :(得分:0)

我就是这样做的:

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

// It is easyer for the memory allocator to have all in the struct
// It is a bit more wasteful on memory though if you set those too large
#define MAX_SURNAME_LENGTH 32
#define MAX_POSTCODE_LENGTH 32
#define MAX_FULL_ADDRESS_LENGTH (256 - MAX_SURNAME_LENGTH - MAX_POSTCODE_LENGTH - sizeof(int))

typedef struct mentry {
    char surname[MAX_SURNAME_LENGTH];
    char postcode[MAX_POSTCODE_LENGTH];
    int house_number;
    char full_address[MAX_FULL_ADDRESS_LENGTH];
} MEntry;

MEntry *me_get(FILE *fp) {
    MEntry *mentry = calloc(sizeof(MEntry), 1);

    // get name
    char * name = fgets(mentry->surname, sizeof(mentry->surname), fp);
    if (!name) { //failure
        free(mentry);
        return NULL;
    }

    char * comma = strchr(name, ','); // find the first comma appearance
    if (comma) *comma = '\0'; // If name has a comma in it, terminate the string there

    char * address = fgets(mentry->full_address, sizeof(mentry->full_address), fp);
    if (!address) { //failure
        free(mentry);
        return NULL;
    }

    char * restaddress;
    int housenumber = strtol(address, &restaddress, 10);

    if (restaddress != address) // there was a valid number at the start of address
        mentry->house_number = housenumber;

    char * postcode = fgets(mentry->postcode, sizeof(mentry->postcode), fp);
    if (!postcode) { //failure
        free(mentry);
        return NULL;
    }

    return mentry;
}

int main() {
    FILE *fp = fopen("S.txt","r");

    MEntry *mentry;
    while ((mentry = me_get(fp))) {
        // do something useful with mentry
    }

    fclose(fp);
    return 0;
}