首页 > 解决方案 > 如何让我的 C 代码读取并显示 C 文件中的多行?

问题描述

我正在尽力让代码从文本文件中读取多行文本。文本文件包含的示例输出如下所示(第一个是 studentID,第二个是 gpa,第三个是缩写):

12345 3.50000 aj
34286 4.10000 be

我只需要屏幕向我显示学生 ID 和 gpa。我已经让它显示第一行代码,但不显示其余代码。我的代码如下:

void displayStudentGpas(FILE* inFile){
    int studentID;
    double gpa;
    char pipe = '|';
    
    while(fscanf(inFile, "%d %lf", &studentID, &gpa) == 2){
        printf("||%11d%4c%11.2lf%8c| \n", studentID, pipe, gpa, pipe);
        printf("||--------------|---------------------|| \n);
    }
}

我将不胜感激您能给我的任何帮助...谢谢!

标签: c

解决方案


在 C 中,每当您需要一次读取一行时,您可以使用面向行的输入函数,如fgets()POSIX 或 POSIX getline()。这样您就可以使用整行输入,并且不会留下部分行未读。

在您的情况下,您尝试使用带有格式字符串的格式化输入函数。(但干得好!检查退货!)。当您尝试阅读时会发生什么:fscanf()"%d %lf"

12345 3.50000 aj

是从输入缓冲区中12345 3.50000留下的行中读取的- 未读。"aj\n"然后在您的下一次迭代中,您尝试再次读取"%d %lf"并发生匹配失败,因为"aj"不是有效的整数输入。

匹配失败发生时,字符提取将停止"aj"在输入缓冲区中留下未读 - 再次。但是,由于您正确地检查了返回并在成功读取两个值的情况下设置了读取循环 - 您的循环终止,而不是进入无限循环,试图一遍又一遍地读取"aj"

注意:您的第三类输入函数是面向字符的函数,例如getchar()orfgetc()getc()

解决方案很简单。使用fgets()和一个足够大的缓冲区(不要吝啬大小)来读取整行,然后用于sscnaf()解析缓冲区中的所有(或仅前两个)值并输出 studentID 和 gpa。你可以做:

#include <stdio.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */
#define MAXI 8

int main (int argc, char **argv) {
    
    char buf[MAXC];     /* buffer to hold entire line */
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
    
    if (!fp) {  /* validate file open for reading */
        perror ("file open failed");
        return 1;
    }
    
    while (fgets (buf, MAXC, fp)) {                     /* read each line */
        int id;         /* ID */
        double gpa;     /* GPA */
        if (sscanf (buf, "%d %lf", &id, &gpa) == 2)     /* parse id & gpa from buf */
            printf ("%-8d %5.1f\n", id, gpa);           /* on success -- output */
    }
    
    if (fp != stdin)   /* close file if not stdin */
        fclose (fp);
}

注意:程序将从作为第一个参数传递给程序的文件名中读取,stdin如果没有提供参数,则默认从文件名中读取——许多 Linux 实用程序的方式)

如果您使用的是内存有限的嵌入式系统,则可以进行MAXC相应调整。(比如说32是一个很好的二的幂,并且仍然提供 15 个字符的边距)

示例使用/输出

只需将您的示例输入传递给stdin,您将收到:

$ cat << eof | ./bin/studentidgpa
> 12345 3.50000 aj
> 34286 4.10000 be
> eof
12345      3.5
34286      4.1

要从文件名中读取值,您可以使用:

$ ./bin/studentidgpa filetoread

或者,如果您愿意,您可以重定向filetoreadstdin例如

$ ./bin/studentidgpa < filetoread

如果您有其他问题,请查看并告诉我。


推荐阅读