我需要读取一个大文本文件,然后填写邮件列表的数据结构。
数据结构如下:
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读取一个字符会比阅读整行然后尝试拆分它更容易吗?
答案 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;
}