You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言CSV成绩计算程序异常:每学期首个科目数据丢失

问题:读取学期成绩CSV时丢失首行科目数据

编写的C程序读取grades.csv计算学期平均、总体平均及科目组平均时,每个学期第一行(与学期名称同列)的科目数据未被读取,导致统计结果缺失该科目(如示例中的TH科目未出现在分组统计中,学期平均也因少算一个科目而错误)。

问题原因分析

原代码中,判断行首非逗号时,仅通过sscanf(line, "%[^,],", grades[numGrades].grade)读取学期名称,完全忽略了同一行中紧随其后的科目数据(如TH31101,Thai Language 1,1.0,1.5部分),这直接导致每个学期的第一个科目被遗漏。

修正后的代码

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

#define MAX_GRADES 100
#define MAX_SUBJECTS 100
// struct to store subject data
typedef struct
{
  char code[50];
  char subjectName[50];
  float cr;
  float grade;
} Subject;
// struct to store grade data
typedef struct
{
  char grade[50];
  Subject subjects[MAX_SUBJECTS];
  int numSubjects;
  float avgGrade;
} GradeData;
// struct to store subject group data
typedef struct
{
  char subjectGroup[3];
  float totalGrade;
  int count;
} SubjectGroup;

// 提取并处理科目数据的函数,避免代码重复
void processSubject(Subject newSubject, GradeData grades[], int *numGrades, float *totalGradeSum, int *totalNumSubjects, SubjectGroup subjectGroups[], int *numSubjectGroups) {
    if (grades[*numGrades - 1].numSubjects < MAX_SUBJECTS) {
        strcpy(grades[*numGrades - 1].subjects[grades[*numGrades - 1].numSubjects].code, newSubject.code);
        strcpy(grades[*numGrades - 1].subjects[grades[*numGrades - 1].numSubjects].subjectName, newSubject.subjectName);
        grades[*numGrades - 1].subjects[grades[*numGrades - 1].numSubjects].cr = newSubject.cr;
        grades[*numGrades - 1].subjects[grades[*numGrades - 1].numSubjects].grade = newSubject.grade;
        grades[*numGrades - 1].numSubjects++;
        *totalGradeSum += newSubject.grade;
        *totalNumSubjects++;

        // Calculate subject group averages
        char subjectGroup[3];
        strncpy(subjectGroup, newSubject.code, 2); // get first 2 characters of subject code
        subjectGroup[2] = '\0';                    // add null terminator
        int found = 0;
        for (int i = 0; i < *numSubjectGroups; i++) // check if subject group already exists
        {
            if (strcmp(subjectGroup, subjectGroups[i].subjectGroup) == 0) // if subject group exists
            {
                // add grade to total grade and increment count
                subjectGroups[i].totalGrade += newSubject.grade; // add grade to total grade
                subjectGroups[i].count++;                        // increment count
                found = 1;                                       // set found to true
                break;
            }
        }
        if (!found) // if subject group does not exist
        {
            strcpy(subjectGroups[*numSubjectGroups].subjectGroup, subjectGroup); // copy subject group to subject group data
            subjectGroups[*numSubjectGroups].totalGrade = newSubject.grade;      // set total grade to grade
            subjectGroups[*numSubjectGroups].count = 1;                          // set count to 1
            (*numSubjectGroups)++;                                                 // increment number of subject groups
        }
    }
}

int main()
{
    // change file name here
    char filename[] = "grades.csv";
    FILE *file, *outputFile;
    char line[100];
    GradeData grades[MAX_GRADES];
    int numGrades = 0;
    float totalGradeSum = 0;
    int totalNumSubjects = 0;
    SubjectGroup subjectGroups[MAX_SUBJECTS];
    int numSubjectGroups = 0;
    int isFirstLine = 1;

    file = fopen(filename, "r");
    // in case file does not exist
    if (file == NULL)
    {
        perror("Error opening file");
        return -1;
    }
    // create output file
    outputFile = fopen("output.csv", "w");
    // in case file does not exist
    if (outputFile == NULL)
    {
        perror("Error creating output file");
        return -1;
    }
    // read file line by line
    while (fgets(line, sizeof(line), file)) {
        if (isFirstLine) {
            isFirstLine = 0;
            continue;
        }

        // 跳过空行
        if (strlen(line) <= 1 || strcmp(line, ",,,,\n") == 0) {
            continue;
        }

        if (line[0] != ',') {
            // 读取学期名称和同一行的科目数据
            Subject newSubject;
            if (sscanf(line, "%[^,],%[^,],%[^,],%f,%f", grades[numGrades].grade, newSubject.code, newSubject.subjectName, &newSubject.cr, &newSubject.grade) == 5) {
                grades[numGrades].numSubjects = 0;
                numGrades++;
                // 处理该行的科目数据
                processSubject(newSubject, grades, &numGrades, &totalGradeSum, &totalNumSubjects, subjectGroups, &numSubjectGroups);
            }
        } else {
            Subject newSubject;
            if (sscanf(line,",%[^,],%[^,],%f,%f", newSubject.code, newSubject.subjectName, &newSubject.cr, &newSubject.grade) == 4) {
                processSubject(newSubject, grades, &numGrades, &totalGradeSum, &totalNumSubjects, subjectGroups, &numSubjectGroups);
            }
        }
    }
    // calculate average grade for each grade
    for (int i = 0; i < numGrades; i++) 
    {
        // calculate average grade
        float sum = 0;
        for (int j = 0; j < grades[i].numSubjects; j++)
        {
            sum += grades[i].subjects[j].grade; // add grade to sum
        }
        grades[i].avgGrade = sum / grades[i].numSubjects; // calculate average grade
    }

    // write to output file
    // write grade data
    fprintf(outputFile, "Grade,Average Grade\n"); // write header
    for (int i = 0; i < numGrades; i++) // write grade data
    {
        fprintf(outputFile, "%s,%.2f\n", grades[i].grade, grades[i].avgGrade);
    }
    // write overall average grade
    fprintf(outputFile, "Overall Average Grade,%.2f\n",
            totalGradeSum / totalNumSubjects);
    // write subject group averages
    fprintf(outputFile, "\nSubject Group,Average Grade\n");
    for (int i = 0; i < numSubjectGroups; i++) // write subject group data
    {
        fprintf(outputFile, "%s,%.2f\n", subjectGroups[i].subjectGroup,
                subjectGroups[i].totalGrade / subjectGroups[i].count);
    }
    
    fclose(file); // close input file
    fclose(outputFile); // close output file

    return 0;
}

修正要点说明

  1. 新增processSubject函数,复用科目处理逻辑,避免代码重复,同时确保学期首行和后续行的科目处理逻辑一致。
  2. 修改学期行的解析逻辑:用sscanf(line, "%[^,],%[^,],%[^,],%f,%f", ...)同时读取学期名称和科目数据,然后调用processSubject处理该科目。
  3. 添加空行判断,跳过CSV中的空行,避免无效处理。

正确输出结果

Grade,Average Grade
Grade 10 Term 1,3.38
Grade 10 Term 2,3.90
Overall Average Grade,3.67

Subject Group,Average Grade
TH,2.75
MA,4.00
SC,3.75
EN,4.00

内容的提问来源于stack exchange,提问作者peemai2004

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:04:57