C 如何读取文本文件中以逗号分隔的行,并将其字段插入结构指针数组中?
我一直在想这个问题,现在我觉得我必须接近。基本上,我有一个数据文件,其中包含由新行分隔的各种国家记录。每个记录都包含逗号分隔的字段,我试图提取其中的某些字段 例如(作为单行): 60,阿富汗联邦政府,阿富汗,亚洲,南亚和中亚,650090191922720000,45.95976,阿富汗伊斯兰酋长国阿法加尼斯坦/阿法内斯坦,穆罕默德·奥马尔,1,阿富汗联邦 每一行将组成一个结构。本质上,我希望读取这些行中的每一行,并将其插入到结构指针数组中(如此动态)。我也只想要特定的字段。当我“标记”行时,我想要代码、姓名、人口和生活经历的字段。分别为: 阿富汗,阿富汗,22720000,45 我的想法是使用fgets()读取文件中的每一行,并在循环malloc()中为指针提供一些内存,对我想要的字段进行标记,然后插入。然而,我正在做的某些事情肯定是错误的,因为各种测试似乎没有在我的输出中显示任何东西 这是我迄今为止的工作。我将感谢任何和所有的帮助C 如何读取文本文件中以逗号分隔的行,并将其字段插入结构指针数组中?,c,arrays,pointers,struct,strtok,C,Arrays,Pointers,Struct,Strtok,我一直在想这个问题,现在我觉得我必须接近。基本上,我有一个数据文件,其中包含由新行分隔的各种国家记录。每个记录都包含逗号分隔的字段,我试图提取其中的某些字段 例如(作为单行): 60,阿富汗联邦政府,阿富汗,亚洲,南亚和中亚,650090191922720000,45.95976,阿富汗伊斯兰酋长国阿法加尼斯坦/阿法内斯坦,穆罕默德·奥马尔,1,阿富汗联邦 每一行将组成一个结构。本质上,我希望读取这些行中的每一行,并将其插入到结构指针数组中(如此动态)。我也只想要特定的字段。当我“标记”行时,我
#include "allheaders.h" // contains all common headers for personal use
#define BUF_SIZE 512
#define NUM_RECS 238
typedef struct {
char code[4];
char name[40];
int population;
float lifeExpectancy;
} Country;
typedef Country *countryPtr;
int main( int argc, const char* argv[] ) {
/* Opening the file */
FILE *filePtr; // pointer to file
if ((filePtr = fopen("AllCountries.dat", "r")) == NULL) { // if couldn't open file
printf("Error opening file\n"); // error message
exit(1);
}
/* Reading the file */
char buffer[BUF_SIZE]; // buffer to read
int index = 0;
char *token;
countryPtr *myCountries = malloc(sizeof(*myCountries) * NUM_RECS);
for(int i = 0; i < NUM_RECS; ++i) {
myCountries[i] = malloc(sizeof(*myCountries[i]));
}
while (fgets(buffer, BUF_SIZE, filePtr) != NULL) {
token = strtok(buffer,",");
token = strtok(NULL, ",");
strcpy(myCountries[index]->code, token);
token = strtok(NULL, ",");
strcpy(myCountries[index]->name, token);
token = strtok(NULL, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
myCountries[index]->population = atoi(token);
token = strtok(NULL, ",");
myCountries[index]->lifeExpectancy = atof(token);
//printf("%s", buffer);
index++;
}
printf("%s", myCountries[1]->code); // test?
free(myCountries);
#include“allheaders.h”//包含供个人使用的所有常用标题
#定义BUF_大小512
#定义NUM_RECS 238
类型定义结构{
字符码[4];
字符名[40];
国际人口;
浮动寿命;
}国家;
typedef Country*countryPtr;
int main(int argc,const char*argv[]{
/*打开文件*/
FILE*filePtr;//指向文件的指针
if((filePtr=fopen(“AllCountries.dat”,“r”))==NULL){//if无法打开文件
printf(“打开文件时出错”);//错误消息
出口(1);
}
/*读取文件*/
char buffer[BUF_SIZE];//要读取的缓冲区
int指数=0;
字符*令牌;
countryPtr*myCountries=malloc(sizeof(*myCountries)*NUM_RECS);
对于(int i=0;i代码、令牌);
令牌=strtok(空,“”,“”);
strcpy(myCountries[索引]->名称、令牌);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
myCountries[指数]->人口=atoi(代币);
令牌=strtok(空,“”,“”);
myCountries[指数]->预期寿命=atof(代币);
//printf(“%s”,缓冲区);
索引++;
}
printf(“%s”,myCountries[1]->代码);//测试?
自由(我国);
}请看以下内容。 首先,您需要做一些工作来改进标记为NYI的区域
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#define BUF_SIZE 512
#define NUM_RECS 238
typedef struct {
char code[4]; // NYI - magic numbers
char name[41]; // NYI - magic numbers
int population; // NYI - what if atoi fails?
float lifeExpectancy; // NYI - what if atof fails?
} Country;
typedef Country* countryPtr;
int main( int argc, const char* argv[] ) {
/* Opening the file */
FILE *filePtr; // pointer to file
if ((filePtr = fopen("a.txt", "r")) == NULL) { // if couldn't open file
printf("Error opening file\n"); // error message
exit(1);
}
/* Reading the file */
char buffer[BUF_SIZE]; // buffer to read
int index=0;
char *token; // NYI - initial value
countryPtr* myCountries = calloc(NUM_RECS, sizeof(countryPtr));
for(int i = 0; i < NUM_RECS; ++i) {
myCountries[i] = calloc(1, sizeof(Country));
}
while (fgets(buffer, BUF_SIZE, filePtr) != NULL) {
// NYI - magic lengths / overflow strcpy targets
token = strtok(buffer,","); // NYI - This is probably not the best way to do this. At least fold into a loop.
token = strtok(NULL, ",");
strcpy(myCountries[index]->code, token);
token = strtok(NULL, ",");
strcpy(myCountries[index]->name, token);
token = strtok(NULL, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
token = strtok(NULL, ",");
myCountries[index]->population = atoi(token); // NYI - atoi failure
token = strtok(NULL, ",");
myCountries[index]->lifeExpectancy = atof(token); // NYI - atof failure
printf("%s", buffer);
index++;
}
printf("%s\n", myCountries[0]->code); // test? NYI - need more proof
free(myCountries); // NYI - this is a sequence - need to free each of the new elements
}
#包括
#包括
#包括
#包括
#定义BUF_大小512
#定义NUM_RECS 238
类型定义结构{
字符代码[4];//NYI-幻数
字符名[41];//NYI-幻数
int population;//NYI-如果atoi失败怎么办?
浮点预期寿命;//NYI-如果atof失败怎么办?
}国家;
typedef Country*countryPtr;
int main(int argc,const char*argv[]{
/*打开文件*/
FILE*filePtr;//指向文件的指针
if((filePtr=fopen(“a.txt”,“r”))==NULL){//if无法打开文件
printf(“打开文件时出错”);//错误消息
出口(1);
}
/*读取文件*/
char buffer[BUF_SIZE];//要读取的缓冲区
int指数=0;
char*token;//NYI-初始值
countryPtr*myCountries=calloc(NUM_RECS,sizeof(countryPtr));
对于(int i=0;i代码、令牌);
令牌=strtok(空,“”,“”);
strcpy(myCountries[索引]->名称、令牌);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
令牌=strtok(空,“”,“”);
myCountries[index]->population=atoi(令牌);//NYI-atoi失败
令牌=strtok(空,“”,“”);
myCountries[索引]->预期寿命=atof(令牌);//NYI-atof故障
printf(“%s”,缓冲区);
索引++;
}
printf(“%s\n”,myCountries[0]->代码);//测试?NYI-需要更多证据
free(myCountries);//NYI-这是一个序列-需要释放每个新元素
}
根据您的代码和数据文件,我采用了不同的方法来解决它。我测试过了。它与您显示的记录类型的文件一起工作。希望它能解释一些事情,让你的工作更轻松,给你一个好的工作场所
我不喜欢以一种必须根据一般原则预先计算(耗时)或预先知道文件中记录数的方式编写程序,除非在极少数情况下。因此,在读取文件时,我更喜欢边读边分配内存。现在,如果有一个大文件和大量数据,那么您必须想出一个更好的内存管理方案,而不是将其全部保存在内存中。在某些情况下,您最好使用某种罐装db解决方案。MySQL、API、库、解析器等。。。但这应该适用于小文件
通常在UNIX上的C中,exit(0)
表示成功,exit(-1)
表示失败。此外,由于您的国家/地区代码为3个字符,因此保存该代码的字段必须至少包含4个字符,以表示尾随“\0”
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#define MAXRECL 512
#define MAXFIELDS 100
#define MAXFIELDL 80
// Field indicies
#define COUNTRY_CODE 1
#define COUNTRY_NAME 2
#define POPULATION 7
#define LIFE_EXPECTANCY 8
#define CCMAX 3
#define CNMAX 40
typedef struct Country {
struct Country *next;
char code[CCMAX + 1]; // (Need room for trailing '\0')
char name[CNMAX + 1]; // (Need room for trailing '\0')
int population;
float lifeExpectancy;
} country_t;
country_t *countryRecords;
int main( int argc, const char* argv[] ) {
FILE *fp;
if ((fp = fopen("AllCountries.dat", "r")) == NULL) {
printf("Error opening file\n");
exit(-1);
}
int totalCountries = 0;
char buf[MAXRECL];
char fields[MAXFIELDS][MAXFIELDL];
country_t *prev_country = NULL;
while (fgets(buf, MAXRECL, fp) != NULL) {
++totalCountries;
country_t *country = calloc(sizeof(struct Country), 1);
if (country == NULL) {
fprintf(stderr, "Out of memory\n");
exit(-1);
}
char *field = strtok(buf, ",");
int i = 0;
while(field != NULL) {
strncpy(fields[i++], field, MAXFIELDL);
field = strtok(NULL, ",");
}
strcpy(country->code, fields[COUNTRY_CODE]);
strcpy(country->name, fields[COUNTRY_NAME]);
country->population = atoi(fields[POPULATION]);
country->lifeExpectancy = atof(fields[LIFE_EXPECTANCY]);
if (countryRecords == NULL)
countryRecords = country;
else
prev_country->next = country;
prev_country = country;
}
printf("Total countries: %d\n", totalCountries);
country_t *country = countryRecords;
while(country != NULL) {
printf("%3s %30s Population: %7d Life Expectancy: %5.2f\n",
country->code, country->name, country->population, country->lifeExpectancy);
country_t *prev_country = country;
country = country->next;
free(prev_country);
}
printf("Done\n");
exit(0);
}
#包括
#包括
#包括
#包括
#定义MaxRecl512
#定义最大字段100
#定义MAXFIELDL 80
//田间指标
#定义国家/地区代码1
#定义国家/地区名称2
#定义人口7
#定义预期寿命8
#定义CCMAX 3
#定义CNMAX 40
类型定义结构国家/地区{
结构国家*下一步;
字符代码[CCMAX+1];/(需要为尾随“\0”留出空间)
字符名[CNMAX+1