[英]Using fgets() and strtok() to read in a file line-by-line in C?
我正在嘗試使用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;
}
這段代碼有幾個問題。 我已經快速修改了你的代碼以完成預期的工作。
#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;
}
人們已經評論了這一變化的細節。
strtok
將修改原始字符串。 因此,在每次迭代后,您存儲的先前指針不再存在。
簡單的解決方案是使用: strdup來分配和復制值。
只需在任何地方修改您的value
分配:
result[i][0] = value;
至:
result[i][2] = strdup(value);
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};
如果需要,您需要將令牌復制到單獨的存儲中。
strtok()
將修改讀取行的緩沖區,並用NUL字符替換分隔符,並返回指向緩沖區中某個位置的指針(即當前標記的開頭)。
當您在下一行中讀取時,緩沖區將填充新數據,因此,您保存的所有指針都是無用的,因為之前的數據現在已經消失。
從文檔引用:
為了確定令牌的開始和結束,該函數首先從起始位置掃描未包含在分隔符中的第一個字符(它成為令牌的開頭 )。 然后從令牌的開頭開始掃描包含在分隔符中的第一個字符,這將成為令牌的結尾 。
令牌的這一端由函數自動替換為空字符,並且該函數返回令牌的開頭 。
並且(強調我的):
海峽
C字符串要截斷。 修改此字符串的內容並將其分解為更小的字符串(標記)。
或者,可以指定空指針,在這種情況下,該函數繼續掃描先前成功調用該函數的位置。分隔符:
包含分隔符的C字符串。
這些可能因呼叫而異。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.