对于给定的代表,
typedef struct {
int age;
char *firstName;
char *lastName;
}Record;
给予 file.txt
,
Age,LastName,FirstName
50,B,A
30,A,B
20,X,D
10,F,A
90,V,E
60,N,M
以下是 main()
中的代码,
pFile=fopen("file.txt", "r");
...
//Complete file is copied to 'readBuffer', approach inspired from
// http://stackoverflow.com/a/11487960/3317808
....
char *record = strtok(readBuffer,"\n"); //Ignore header record
record = strtok(NULL, "\n");// Read first data record(50,'B','A')
for(;record != NULL; record = strtok(NULL,"\n")){
printf("###Print complete record\n");
puts(record);
Record *r = malloc(sizeof(Record)*1);
r->age = atoi(strtok(record,","));
char *firstName = strtok(NULL,",");
char *lastName = strtok(NULL, ",");
r->firstName = strdup(firstName);
r->lastName = strdup(lastName);
printf("Age: %d\n", r->age);
printf("First name: %s\n", r->firstName);
printf("Last name: %s\n", r->lastName);
}
strtok(readBuffer,",")
在for循环中将编译器与 strtok(record,",")
混淆
实际输出显示只有一条记录发生了标记化 .
$ ./program.exe
Print complete file
Age,LastName,FirstName
50,B,A
30,A,B
20,X,D
10,F,A
90,V,E
60,N,M
###Print complete record
50,B,A
Age: 50
First name: B
Last name: A
怎么解决?
3 回答
正如@David C. Rankin建议的那样,使用fgets和strtok来读取每一行是解决这个问题的好方法 .
如果您希望将来使用
mergesort
,那么使用此排序算法最容易实现将数据存储在结构数组中 . 此外,如果您不知道文件中将包含多少行,则可能需要在运行时动态分配该行 .您可以在文件中存储较低级别的
struct
:还有一个更高级别的
struct
存储文件的所有内容:有关fgets的注意事项:
在空终止符
\0
之前的缓冲区末尾添加\n
字符 . 这个附加的\n
可以很容易地删除 .出错时,返回
NULL
. 如果达到EOF
且没有读取任何字符,则返回NULL
.必须静态声明缓冲区大小 .
需要从
stdin
或FILE *
从指定的流中读取 .程序中fgets的可选用法:
使用
fgets()
时,您可以调用一次以使用标头信息:然后,您可以在
while()
循环中再次调用它,以使用文件中的其余数据:在计划中实施所有这些想法:
Note :我使用
malloc()
strcpy()
而不是strdup()
,因为它们来自标准C库,如<string.h>
和<stdlib.h>
,而不是POSIX C.节目输出:
如果在我们的情况下可行,使用
strtok_r()
似乎是最简单的方法 . 只是告知,这不是标准C,它在POSIX中 .来自man page,
和
手册页还有一个您正在寻找的场景的示例 .
问题更多的是与逻辑而不是strtok的使用 .
另外值得注意的是您正在阅读的记录的格式,您在姓氏字段后面没有逗号的问题 .
下面的代码将实现您的问题所要求的