我正在尝试使用fgets和strtok()逐行读取文件,并创建每个不同信息行的链接列表。
现在,我只是将信息放入一个数组中,只是为了试图弄清楚如何正确读取信息,但它无法正常工作。
在while(fgets)部分,它似乎正确地将所有内容加载到数组中,并将其打印出来。然而,在循环执行完并且我尝试打印整个数组之后,我得到了非常奇怪的结果..这主要是最后一行的部分,而不是完整的单词或大部分内容。
例如,如果我正在阅读:
Simpson, Homer, Male, 1976
Simpson, Marge, Female, 1978
Simpson, Bart, Male, 2002
Simpson, Lisa, Female, 2004
Simpson, Maggie, Female, 2011
我最后得到的打印输出是这样的:
le
Simpson
Maggie
Simpson
Maggie
e
ale
Simpson
Maggie
e
e
Simpson
Maggie
Female
2011
请让我知道我哪里出错了,谢谢!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRINGSIZE 10
#define LINESIZE 128
struct person{
char firstName[MAXSTRINGSIZE];
char lastName[MAXSTRINGSIZE];
char gender[MAXSTRINGSIZE];
int birthYear;
struct person *next;
} *first, *current;
int main (void){
static const char filename[] = "Assignment1file.txt";
FILE *myfile = fopen ( "Assignment1file.txt", "r" );
int i=0;
int j=0;
int k=0;
int l=0;
char *result[10][4];
char line[LINESIZE];
char *value;
for(i=0; i<9; i++){
for(j=0;j<4;j++){
result[i][j] = NULL;
}
}
i=0;
// loop through each entry in Assignment1file
while(fgets(line, sizeof(line), myfile)){
//load last name
value = strtok(line, ",");
result[i][0] = value;
printf("%i 0 %s", i, value);
//load first time
value = strtok(NULL, ",");
result[i][1] = value;
printf("%i 1 %s", i, value);
// load gender
value = strtok(NULL, ",");
result[i][2] = value;
printf("%i 2 %s", i, value);
// load birth year
value = strtok(NULL, "\n");
result[i][3] = value;
printf("%i 3 %s", i, value);
printf("\n");
for(j=0;j<4;j++){
printf("%s\n", result[i][j]);
}
//go to next line
i++;
}
// read out the array
for(k=0; k<5; k++){
for(j=0;j<4;j++){
printf("%s\n", result[k][j]);
}
}
fclose(myfile);
return 0;
}
答案 0 :(得分:4)
此代码存在几个问题。我已经快速修改了你的代码以完成预期的工作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSTRINGSIZE 10
#define LINESIZE 128
struct person{
char firstName[MAXSTRINGSIZE];
char lastName[MAXSTRINGSIZE];
char gender[MAXSTRINGSIZE];
int birthYear;
struct person *next;
} *first, *current;
int main (void){
FILE *myfile = fopen ( "Assignment1file.txt", "r" );
int i=0;
int j=0;
int k=0;
int l=0;
char *result[10][4];
char line[LINESIZE];
char *value;
for(i=0; i<=9; i++){
for(j=0;j<=4;j++){
result[i][j] = NULL;
}
}
i=0;
// loop through each entry in Assignment1file
while(fgets(line, sizeof(line), myfile)){
//load last name
value = strtok(line, ", ");
result[i][0] = strdup(value);
printf("last: %s\n", value);
//load first time
value = strtok(NULL, ", ");
result[i][1] = strdup(value);
printf("first: %s\n", value);
// load gender
value = strtok(NULL, ", ");
result[i][2] = strdup(value);
printf("gender: %s\n", value);
// load birth year
value = strtok(NULL, " \n");
result[i][3] = strdup(value);
printf("birth year: %s\n", value);
//go to next line
i++;
}
// read out the array
for(k=0; k<5; k++){
for(j=0;j<4;j++){
printf("%s\n", result[k][j]);
}
}
fclose(myfile);
return 0;
}
人们已经对这一变化的细节发表了评论。
答案 1 :(得分:2)
strtok
将修改原始字符串。因此,在每次迭代后,您存储的先前指针不再存在。
简单的解决方案是使用:strdup来分配和复制值。
只需在任何地方修改value
的作业:
result[i][0] = value;
要:
result[i][2] = strdup(value);
答案 2 :(得分:2)
strtok()
返回line[]
内的指针,因此当您读取下一行时,您保存的所有指针现在都指向存储文件最后一行的位置。
您可以为每个字符串分配内存,如下所示:
//load last name
value = strtok(line, ",");
result[i][0] = malloc(strlen(value) + 1);
strcpy(result[i][0], value);
顺便说一句,你不需要在开始时将循环设置为NULL
,你可以这样做:
char *result[10][4] = {0};
答案 3 :(得分:1)
如果需要,您需要将令牌复制到单独的存储空间中。
strtok()
将修改读取行的缓冲区,并用NUL字符替换分隔符,并返回指向缓冲区中某个位置的指针(即当前标记的开头)。
当您在下一行中读取时,缓冲区将填充新数据,因此,您保存的所有指针都是无用的,因为之前的数据现已消失。
要确定令牌的开头和结尾,该函数首先从起始位置扫描分隔符中包含的第一个字符不(后者成为令牌的开头)。然后从 delimiters 中包含的第一个字符开始,从开头的分区开始扫描,这将成为令牌的结尾。
令牌的端由函数自动替换为空字符,并且函数返回开头的令牌。
并且(强调我的):
STR
C字符串要截断。 修改此字符串的内容并将其分解为较小的字符串(标记)。
或者,可以指定空指针,在这种情况下,函数继续扫描先前成功调用函数的位置。分隔符:
包含分隔符的C字符串。
这些可能因呼叫而异。