簡體   English   中英

使用fgets()和strtok()在C中逐行讀取文件?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM