簡體   English   中英

在while循環中讀取c中的文件

[英]reading from a file in c in a while loop

我試圖從文件中讀取患者信息,將文件中的數據插入結構的字段中,並將節點插入到鏈表中,直到到達EOF。 我遇到的問題是嘗試到達EOF時終止while循環。 我使用fscanf讀取文件的每一行,並使用另一行檢查文件的末尾。 放置2個fscanf會導致每次換行,並跳過一半的數據。 在while循環中檢查EOF的更好方法是什么? 我的文本文檔中的信息是這樣格式化的。 除非它們不是每個患者之間的換行符。 我只是在這篇文章中這樣做,以提高可讀性。

索菲亞·傑克遜1234 141.0 1.1

艾瑪·艾登5432 142.0 1.2

奧利維亞·盧卡斯(Olivia Lucas)5685 143.0 1.3

阿瓦·利亞姆5672 144.0 1.4

米婭·諾亞(Mia Noah)3467 145.0 1.5

伊莎貝拉(Isabella Ethan)8654 146.0 1.6

萊利梅森2567 147.0 1.7

詠嘆調Caden 6794 148.0 1.8

佐伊·奧利弗(Zoe Oliver)3467 149.0 1.9

fp = fopen("info.txt","r");

if(fp == NULL){
    printf("ERROR File Doesn't exist\n");
}


while(1){

    newptr = (node*)malloc(sizeof(node));
    newptr->back = NULL;
    newptr->next = NULL;
    newptr->phgnum = 0;
    newptr->pid = 0;
    newptr->pwt = 0;
    fscanf(fp,"%s %s %i %f %f",newptr->pfn,newptr->pln,&newptr->pid,&newptr->pwt,&newptr->phgnum);
    printf("First Name: %s\n",newptr->pfn);
    printf("Last Name: %s\n",newptr->pln);
    printf("PID: %i\n",newptr->pid);
    printf("Weight: %f\n",newptr->pwt);
    printf("HG1AC: %f\n",newptr->phgnum);

    (insert node into linked list)

    // test for EOF        
    if( 5!= fscanf(fp,"%s %s %i %f %f",newptr->pfn,newptr->pln,&newptr->pid,&newptr->pwt,&newptr->phgnum)) 
        break;

讀取格式化的數據時,您希望基於成功讀取數據單位(此處為一行)來控制循環。 這樣可以確保僅在驗證讀取后才嘗試處理信息。 雖然通常最好使用fgets然后調用sscanf ,但從格式化的文件讀取時,最終等同於fscanf調用。 唯一的區別是您失去了獨立驗證讀取和解析的能力。 (重要的是取決於情況)

為了便於閱讀,最好在分配節點之前將值讀取到臨時結構中,以達到更好的服務效果。 在讀取之前不需要分配,這使您可以在調用malloc之前驗證讀取。 有多種方法可以執行此操作,具體取決於您的需求,但是一般的方法是:

#include <stdio.h>
#include <stdlib.h>

#define MAXNAME 16  /* size as appropriate - or dynamically allocate */

typedef struct {    /* declare struct as required */
    char pfn[MAXNAME],
         pln[MAXNAME];
    float pwt,
          phgnum;
    int pid;
} node_t;

int main (int argc, char **argv) {

    size_t npt = 0;                 /* number of patients */
    node_t tmp = { .pfn = "" };     /* temp struct for read */
    /* read from filename given as 1st argument (or stdin by defaut) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open for reading */
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    /* while there is a good read of patient data */
    while (fscanf (fp, "%15s %15s %d %f %f", tmp.pfn, tmp.pln, &tmp.pid,
            &tmp.pwt, &tmp.phgnum) == 5) {
        node_t *newptr = malloc (sizeof *newptr);   /* allocate node */

        if (!newptr) {  /* validate allocation */
            perror ("malloc-newptr");
            break;
        }

        *newptr = tmp;  /* assign tmp data to node */
        /* add to linked list -- here */

        printf ("%-16s %-16s %5d %6.2f %6.2f\n", newptr->pfn, newptr->pln,
                newptr->pid, newptr->pwt, newptr->phgnum);

        npt++;  /* increment patient count */
    }
    if (fp != stdin) fclose (fp);   /* close file if not stdin */
                                    /* don't forget to free list */
    return 0;
}

(注意:數據只是上面的輸出,您只需要將其添加到列表中並刪除輸出(或將其包裝在#ifdef DEBUG ... #endif ,使其以是否定義DEBUG為條件))

輸入文件示例

$cat dat/patients.txt
Sophia Jackson 1234 141.0 1.1
Emma Aiden 5432 142.0 1.2
Olivia Lucas 5685 143.0 1.3
Ava Liam 5672 144.0 1.4
Mia Noah 3467 145.0 1.5
Isabella Ethan 8654 146.0 1.6
Riley Mason 2567 147.0 1.7
Aria Caden 6794 148.0 1.8
Zoe Oliver 3467 149.0 1.9

使用/輸出示例

$ ./bin/patient_read <dat/patients.txt
Sophia           Jackson           1234 141.00   1.10
Emma             Aiden             5432 142.00   1.20
Olivia           Lucas             5685 143.00   1.30
Ava              Liam              5672 144.00   1.40
Mia              Noah              3467 145.00   1.50
Isabella         Ethan             8654 146.00   1.60
Riley            Mason             2567 147.00   1.70
Aria             Caden             6794 148.00   1.80
Zoe              Oliver            3467 149.00   1.90

仔細看一下,如果您有任何問題,請告訴我。

fscanf()的返回值在文件結束時為EOF,如果早期匹配失敗,則返回0。 否則,將返回成功匹配的輸入項的數量。 這樣,您可以將此作為while循環本身的測試條件:

while (fscanf(fp, "%s %s %i %f %f", ...) == 5) {
    // ...
}

例如,考慮以下最小程序:

#include <stdio.h>

int main(void) {
    char fname[50], lname[50];
    int id;
    float weight, hgnum;

    FILE *fp = fopen("info.txt", "r");
    if (fp == NULL) {
        perror("Error: Failed to open file.");
        return 1;
    }

    while (fscanf(fp, "%49s %49s %i %f %f", fname, lname, &id, &weight, &hgnum) == 5) {
        printf("First Name: %s\n", fname);
        printf("Last Name: %s\n", lname);
        printf("PID: %i\n", id);
        printf("Weight: %.1f\n", weight);
        printf("HG1AC: %.1f\n\n", hgnum);
    }

    return 0;
}

這將打印您的文本文件示例,如下所示:

First Name: Sophia
Last Name: Jackson
PID: 1234
Weight: 141.0
HG1AC: 1.1

First Name: Emma
Last Name: Aiden
PID: 5432
Weight: 142.0
HG1AC: 1.2

First Name: Olivia
Last Name: Lucas
PID: 5685
Weight: 143.0
HG1AC: 1.3

First Name: Ava
Last Name: Liam
PID: 5672
Weight: 144.0
HG1AC: 1.4

First Name: Mia
Last Name: Noah
PID: 3467
Weight: 145.0
HG1AC: 1.5

First Name: Isabella
Last Name: Ethan
PID: 8654
Weight: 146.0
HG1AC: 1.6

First Name: Riley
Last Name: Mason
PID: 2567
Weight: 147.0
HG1AC: 1.7

First Name: Aria
Last Name: Caden
PID: 6794
Weight: 148.0
HG1AC: 1.8

First Name: Zoe
Last Name: Oliver
PID: 3467
Weight: 149.0
HG1AC: 1.9

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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