【问题标题】:fscanf doesn't seem to be reading from file while in a loopfscanf 在循环中似乎没有从文件中读取
【发布时间】:2021-11-17 18:09:17
【问题描述】:

我正在尝试编写一个程序作为练习,从文件中获取一些值,将它们分类为两个变量,名为 studentsPassedstudentsFailed,然后打印通过的学生人数和通过的学生人数失败以及模块代码和学生人数。

这是 .txt 文件:

101 20
65 72 23 59 80 75 55 88 92 77 44 57 73 31 48 59 71 48 66 59

101 是模块代码,20 是班级学生人数。下面一行中的 20 个数字是这 20 名学生中每个人的分数(例如学生 1 得 65 分,学生 2 得 72 分等)

这是我的代码:

#include <stdio.h>

FILE *fp;

int main(){

    //Open the file and assign its address/disk location to file pointer
    fp = fopen("marks.txt", "r");

    //Variables
    int moduleCode, numStudents;
    const int size = 20;

    int studentMark;
    int studentsPassed;
    int studentsFailed;

    //Scan in the first line for the module code and the number of students
    fscanf(fp, "%d %d", &moduleCode, &numStudents);

    //Scan in the student marks and loop through them
    for (int i = 0; i < size; i++)

        if (fscanf(fp, "%d", &studentMark) < 40){

            int studentsFailed = studentsFailed + 1;

        }

        else if (fscanf(fp, "%d", &studentMark) >= 40){

            int studentsPassed = studentsPassed + 1;

        }

        else{

            printf("Error: Number of marks exceeds cap!");
            return 0;
        }

    //Print the results
    printf("%d %d\n", moduleCode, numStudents);
    printf("Number of students passed: %d\n", studentsPassed);
    printf("Number of students failed: %d\n", studentsFailed);

    return 0;
}

程序应该做的是读取模块代码和学生人数并将它们打印在第一行(这是成功的),然后程序应该循环遍历 20 个数字中的每一个,并将它们分类为不同的变量如果它们高于或低于 40,这是我正在努力的部分,因为程序执行,但它会为studentsPassed 打印出一个随机的大数,每次我为studentsFailed 打印一个“1”运行它。

我做错了什么?我觉得我错过了与循环遍历每个数字有关的东西,但我不确定如何更正它。

注意:这是我在reading another answer 之前在本网站上最初尝试的(也没有工作)以获得我当前的代码。

//Scan in the student marks and loop through them
    fscanf(fp, "%d", &studentMark);
    for (int i = 0; i < size; i++)

        if (studentMark < 40){

            int studentsFailed = studentsFailed + 1;

        }

        else if (studentMark >= 40){

            int studentsPassed = studentsPassed + 1;

        }

【问题讨论】:

  • if (fscanf(fp, "%d", &amp;studentMark) &lt; 40) scanf 函数系列不是这样工作的。请阅读更多关于what it returns的信息。
  • 另外,如果你多次调用fscanf,它会尝试读取多个值。这意味着您对studentMark 的多次调用将跳过每秒的值。

标签: c loops


【解决方案1】:

您的第二个版本几乎是正确的,只是对 fscanf() 的调用需要在循环内。

此外,您不应在 if 块中重新声明 studentsFailedstudentsPassed。只需分配给之前声明的变量即可。

    for (int i = 0; i < size; i++)
        fscanf(fp, "%d", &studentMark);
        if (studentMark < 40){
            studentsFailed++;
        }
        else{
            studentsPassed++;
        }
    }

当第二个条件与第一个相反时,您也不应该使用else if。只需使用else

【讨论】:

  • 不幸的是,我仍然得到一个奇怪的输出,高数表示通过,“1”表示失败。虽然有趣的是,如果我将 studentsPassedstudentsFailed 设置为 0,studentsPassed 会打印为值为 1,这似乎在循环中起作用。
  • 我强烈建议修改答案以检查 fscanf 返回的值,以向 OP 演示如何正确使用返回值。
  • @Callum 未初始化的局部变量(函数内部的变量)实际上是未初始化的,并且会有一个indeterminate(“垃圾”)值。
  • @Someprogrammerdude 感谢您的澄清,我不知道这就是它打印奇怪输出的原因。
【解决方案2】:

*scanf 返回的值是成功匹配的转换说明符的数量。它与从输入流中读取的值无关。

你应该改掉依赖输入流来提供预期数据点数量的习惯;它很脆弱,通常没有必要。相反,只需读取所有数据,直到到达输入流的末尾。在您的情况下,您可以执行以下操作:

#include <stdio.h>

int
main(int argc, char **argv)
{
    int moduleCode, numStudents, studentsPassed = 0, studentsFailed = 0;
    int actualNumStudents = 0;
    int score;
    FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;

    if( fp == NULL ){
        perror(argv[1]);
        return 1;
    }
    if( fscanf(fp, "%d%d", &moduleCode, &numStudents) != 2 ){
        fprintf(stderr, "invalid input\n");
        return 1;
    }
    while( fscanf(fp, "%d", &score) == 1 ){
        actualNumStudents += 1;
        *( score < 40 ? &studentsFailed : &studentsPassed ) += 1;
    }
    if( ! feof(fp) ){
        fputs(ferror(fp) ? "read error\n" : "invalid input\n", stderr);
        return 1;
    }
    if( actualNumStudents != numStudents ){
        fprintf(stderr, "Warning: the declared number of students does "
            "not match the actual number of students\n");
    }

    printf("%d %d\n", moduleCode, actualNumStudents);
    printf("Number of students passed: %d\n", studentsPassed);
    printf("Number of students failed: %d\n", studentsFailed);
}

【讨论】:

  • 罕见地正确使用if( ! feof(fp) ){
猜你喜欢
  • 2021-04-05
  • 1970-01-01
  • 2017-06-25
  • 1970-01-01
  • 2021-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多