繁体   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