我的 C 程序从 .csv 计算每个学期的成绩时出现问题

问题描述 投票:0回答:1

我的C代码

#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;

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 (line[0] != ',') {
            if (line[0] != '\n') {
                sscanf(line, "%[^,],", grades[numGrades].grade);
                grades[numGrades].numSubjects = 0;
                numGrades++;
            }
        } else {
            Subject newSubject;
            sscanf(line, ",%[^,],%[^,],%f,%f", newSubject.code, newSubject.subjectName, &newSubject.cr, &newSubject.grade);
            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
      }
    }
  }
  // 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;
}

代码读取grades.csv

,CODE,Subject NAME,CR,Grade
Grade 10 Term 1,TH31101,Thai Language 1,1.0,1.5
,MA31101,Mathematics 1,1.0,4
,SC30101,Science (Physics),1.0,4
,EN31201,English Reading-Writing 1,1.5,4
,,,,
,,,,
Grade 10 Term 2,TH31102,Thai Language 2,1.0,4
,MA31102,Mathematics 2,1.0,4
,SC30103,Computational Science 1,0.5,3.5
,EN31202,English Reading - Writing 2,1.5,4

但是它的输出缺少每个学期的第一个主题

Grade,Average Grade
Grade 10 Term 1,3.72
Grade 10 Term 2,3.88
Overall Average Grade,3.86

Subject Group,Average Grade
MA,3.75
SC,3.83
EN,4.00

我认为存在一个问题,它没有读取每个术语中的第一个主题,因为我与术语名称位于同一行。

我曾尝试克隆计算数据的行,以确保当它是新主题时条件为真,但它不起作用

c csv struct file-access
1个回答
0
投票

如果您的 csv 文件始终采用这种方式格式化,您只需阅读每一行的主题,包括术语行。

if (line[0] != ',') {
    if (line[0] != '\n') {
        sscanf(line, "%[^,],%[^,],%[^,],%f,%f", grades[numGrades].grade, newSubject.code, newSubject.subjectName, &newSubject.cr, &newSubject.grade);
        grades[numGrades].numSubjects = 0;
        numGrades++;
    }
} else {
    sscanf(line, ",%[^,],%[^,],%f,%f", newSubject.code, newSubject.subjectName, &newSubject.cr, &newSubject.grade);
}
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++;
}

这将为您提供输出:

Grade,Average Grade
Grade 10 Term 1,3.58
Grade 10 Term 2,3.88
Overall Average Grade,3.70

Subject Group,Average Grade
TH,2.75
MA,4.00
SC,3.75
EN,4.00
© www.soinside.com 2019 - 2024. All rights reserved.