调试器跳过函数问题排查:读取文件计算学生成绩程序异常
问题分析与修复
直接导致程序跳步的核心原因
你main函数里的操作完全搞反了:把整个文件内容读成字符串out,然后把这个字符串传给gradeAspects当文件名用——gradeAspects里是调用input.open(filename),这里需要的是文件路径,不是文件内容!这直接导致文件打开失败,if(input)条件不成立,函数里的循环根本没执行,后面的计算函数拿不到数据,程序自然就快速结束了。
逐个修复代码里的问题
1. 修正main函数的文件传递逻辑
直接把文件名传给gradeAspects就行,不用读整个文件:
int main() { GradeCalc gCalc; gCalc.gradeAspects("TestAnswers(5).txt"); // 直接传文件名 gCalc.gradeCalculation(); gCalc.grade(); }
2. 修复gradeAspects函数的致命问题
- 别用
!input.eof()循环:这种写法会重复读最后一行,换成while(getline(input, line))才对 delim类型错了:line.find(DELIM)返回的是size_t类型,不是char,找不到分隔符会返回string::npos,直接用char会炸- 加格式错误判断:如果某一行找不到分隔符,直接跳过或退出,避免
substr崩溃 - 把行数存到类成员里:你之前定义的
rsize是局部变量,后面的函数拿不到这个值,得存到类的GradeAspects成员里或者用vector的size() - 替换固定数组为vector:
readFile[25]超过25个学生就会越界,用vector<GradeAspects> read更安全
改后的gradeAspects:
void GradeCalc::gradeAspects(string filename) { ifstream input(filename); string line; size_t rnum = 0; size_t delim; if (input.is_open()) { while (getline(input, line)) { if(line.empty()) continue; // 跳过空行 GradeAspects ga; // 提取学号 delim = line.find(DELIM); if(delim == string::npos) break; ga.studentN = line.substr(0, delim); line = line.substr(delim + 1); // 提取名字 delim = line.find(DELIM); if(delim == string::npos) break; ga.firstname = line.substr(0, delim); line = line.substr(delim + 1); // 提取姓氏 delim = line.find(DELIM); if(delim == string::npos) break; ga.lastname = line.substr(0, delim); line = line.substr(delim + 1); // 提取答案 ga.answers = line; read.push_back(ga); if(rnum <25) readFile[rnum] = ga; // 兼容原来的数组 rnum++; } if(!read.empty()) read[0].rsize = rnum; // 存学生数量 } }
3. 修复gradeCalculation的逻辑错误
rsize别初始化为0:用read.size()或者之前存的read[0].rsize,不然循环根本不跑- 答案比较索引错了:
answers[t] == readFile[i].answers[i]应该是readFile[i].answers[t],你拿第i个学生的第i个答案和标准答案的第t个比,完全不对 - 把分数存对地方:别乱赋值给
answers,存到read[i].scores里
改后的gradeCalculation:
void GradeCalc::gradeCalculation() { if(read.empty()) return; // 没数据直接返回 string standardAnswers = read[0].answers; // 假设第一行是标准答案,按需调整 int aSize = standardAnswers.size(); int rsize = read.size(); for (int i = 0; i < rsize; i++) { int score = 0; string studentAnswers = read[i].answers; if(studentAnswers.size() != aSize) continue; // 答案长度不对跳过 for (int t = 0; t < aSize; t++) { if (standardAnswers[t] == studentAnswers[t]) score++; } read[i].scores = score; // 保存正确得分 } }
4. 修复grade函数的低级错误
aSize别用空字符串初始化:line是空的,aSize就是0,后面除以0会崩溃,用标准答案的长度rsize别初始化为0:用read.size()- 别覆盖学生名字:给
GradeAspects加个string gradeLetter;成员,把等级存这里,别把A/B/C/F写到firstname里 - 百分比计算别用整数除法:
(score / aSize)要转成浮点型,不然结果都是0
改后的grade:
// 先给GradeAspects加成员:string gradeLetter; void GradeCalc::grade() { if(read.empty()) return; int aSize = read[0].answers.size(); int rsize = read.size(); for (int i = 0; i < rsize; i++) { double score = read[i].scores; double percent = (score / aSize) * 100; string gradeLetter; if (percent >= 90) gradeLetter = "A"; else if (percent >=80) gradeLetter = "B"; else if (percent >=70) gradeLetter = "C"; else gradeLetter = "F"; // 正确输出信息 cout << "学生 " << read[i].firstname << " " << read[i].lastname << " 答对 " << score << " 题,总分 " << aSize << ",得分率 " << percent << "%,等级 " << gradeLetter << endl; } }
最后总结
程序一开始直接结束,就是因为你把文件内容当成文件名传了,导致文件打不开,后续逻辑全没执行。先把这个核心问题改了,再逐个解决代码里的类型错误、索引错误、逻辑错误,程序就能正常跑起来了。
内容的提问来源于stack exchange,提问作者Colin
相关产品推荐
相关产品推荐

