C++解析CSV文件显示异常及GPA计算实现技术问询
CSV解析异常原因及GPA计算实现方案
一、CSV解析异常的原因及修复
问题根源
你的代码在读取完RollNumbers后,输入流中残留了逗号分隔符,后续直接用>>读取数值时,因逗号不是有效数字导致读取失败,未初始化的变量会显示随机垃圾值(如0、212、负数等)。此外,CSV前两行的表头和总分说明被当作学生数据读入,也会产生无效输出。
修复后的完整代码
#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> #include <iomanip> using namespace std; struct StudentRecord{ string StudentNames; int RollNumbers; int Mid; int Final; int Project; StudentRecord(string name, int roll, int mid, int final, int project) : StudentNames(name), RollNumbers(roll), Mid(mid), Final(final), Project(project) {} void displayInfo(){ cout << "学生姓名: " << StudentNames << endl; cout << "学号: " << RollNumbers << endl; cout << "期中成绩: " << Mid << endl; cout << "期末成绩: " << Final << endl; cout << "项目成绩: " << Project << endl; cout << "-------------------------" << endl; } double calculateGPA(double midWeight, double finalWeight, double projectWeight) { // 将成绩转换为百分制占比 double midPercent = static_cast<double>(Mid) / 100; double finalPercent = static_cast<double>(Final) / 100; double projectPercent = static_cast<double>(Project) / 40; // 加权计算总分后转换为4分制GPA double totalScore = midPercent * midWeight + finalPercent * finalWeight + projectPercent * projectWeight; return (totalScore / 100) * 4.0; } }; void displayStudents(vector<StudentRecord>& students){ for(auto& student : students){ student.displayInfo(); } } void displayStudentsWithGPA(vector<StudentRecord>& students, double midW, double finalW, double projectW) { cout << fixed << setprecision(2); for(auto& student : students){ student.displayInfo(); double gpa = student.calculateGPA(midW, finalW, projectW); cout << "GPA: " << gpa << endl; cout << "-------------------------" << endl; } } int main(){ ifstream inputFile("C:\\Users\\hasan\\Desktop\\file_handling project\\NCA.csv"); if(!inputFile.is_open()){ cout << "无法打开文件!" << endl; return 1; } string line; vector<StudentRecord> students; // 跳过表头和总分说明行 getline(inputFile, line); getline(inputFile, line); while(getline(inputFile, line)){ stringstream inputString(line); string name, rollStr, midStr, finalStr, projectStr; // 按逗号分割所有字段 getline(inputString, name, ','); getline(inputString, rollStr, ','); getline(inputString, midStr, ','); getline(inputString, finalStr, ','); getline(inputString, projectStr, '\n'); // 字符串转整数,自动忽略首尾空格 int roll = stoi(rollStr); int mid = stoi(midStr); int final = stoi(finalStr); int project = stoi(projectStr); students.emplace_back(name, roll, mid, final, project); } cout << "=== 学生成绩数据 ===" << endl; displayStudents(students); // 接收权重输入并计算GPA double midWeight, finalWeight, projectWeight; cout << "\n请输入各成绩权重(期中、期末、项目,总和建议为100):" << endl; cout << "期中权重: "; cin >> midWeight; cout << "期末权重: "; cin >> finalWeight; cout << "项目权重: "; cin >> projectWeight; cout << "\n=== 学生GPA结果 ===" << endl; displayStudentsWithGPA(students, midWeight, finalWeight, projectWeight); inputFile.close(); return 0; }
修复核心要点
- 统一字段分割方式:全程用
getline(..., ',')分割所有字段,避免>>操作残留分隔符的问题,再通过stoi完成字符串到整数的转换,自动处理字段前后的空格。 - 过滤无效行:用两次
getline跳过CSV的表头行和总分说明行,避免无效数据被读入。 - 优化构造函数:改用成员初始化列表,提升代码效率与规范性。
二、GPA计算实现思路
- 权重输入:从终端接收用户输入的期中、期末、项目成绩权重(如30、50、20,总和建议为100)。
- 成绩归一化:因项目总分是40,需先将项目成绩转换为百分制占比(
项目成绩/40),期中、期末成绩直接用成绩/100转换。 - 加权计算:通过
(期中占比×期中权重)+(期末占比×期末权重)+(项目占比×项目权重)得到加权总分(0-100),再转换为4分制GPA(总分/100×4)。 - 模块化设计:将GPA计算方法集成到
StudentRecord结构体中,每个学生对象可直接调用计算自身GPA。
内容的提问来源于stack exchange,提问作者hasanfaesal
相关产品推荐
相关产品推荐

