C++中std::array读取文件时重复写入最后一个数值的问题求助
问题描述
我需要处理多个包含不同数量数字的文件并计算总分。当前代码的问题是:从文件读取数字存入std::array时,文件的最后一个数字会被重复写入数组,本该在文件结束时停止。我试过用for循环,还是有同样问题,代码如下:
#include <iostream> #include <fstream> #include <iomanip> #include <array> const int kMaxSize {30}; std::array < int, kMaxSize > ProcessFile(std::ifstream &infile, int &num_grades); double CalculateFinalGrade(std::array < int, kMaxSize > grades, int &num_grades); int CalculateTotal(std::array < int, kMaxSize > grades, int &num_grades); char CalculateLetter(double final_grade); int main(){ std::string filename{}; std::cout << "Enter the input file: "; std::cin >> filename; std::ifstream infile { filename }; if (!infile){ std::cout << '\n' << filename << " does not exist.\n"; return 1; } int num_grades {}; double final_grade {}; char letter_grade {}; int points_earned {}; int max_points {}; std::array < int, kMaxSize > grades {}; max_points = num_grades * 100; grades = ProcessFile(infile, num_grades); // this is block checking contents to array std::cout << '\n'; for (int i{0}; i < kMaxSize; i++){ std::cout << grades.at(i) << " "; } std::cout << '\n'; // end of block final_grade = CalculateFinalGrade(grades, num_grades); points_earned = CalculateTotal(grades, num_grades); letter_grade = CalculateLetter(final_grade); infile.close(); std::cout << '\n' << "Number of Grades: " << std::setw(11) << std::right << num_grades; std::cout << '\n' << "Total Points Earned: " << std::setw(8) << std::right << points_earned; std::cout << '\n' << "Max Possible Points: " << std::setw(8) << std::right << max_points << '\n'; std::cout << std::fixed << std::setprecision(1); std::cout << '\n' << "Final Grade: " << std::setw(7) << std::right << letter_grade << std::setw(8) << std::right << final_grade << "%" << '\n'; return 0; } std::array <int, kMaxSize > ProcessFile(std::ifstream &infile, int &num_grades){ int number {}; std::array < int, kMaxSize > grades {}; infile >> number; while (infile){ for (int i{0}; i < kMaxSize; i++){ grades.at(i) = number; num_grades = num_grades + 1; infile >> number; } } return grades; } double CalculateFinalGrade(std::array < int, kMaxSize > grades, int &num_grades){ double final_grade{}; int max_points {}; max_points = num_grades * 100; double points_earned {}; for (int i{0}; i < kMaxSize; i++){ points_earned += grades.at(i); } if (max_points != 0){ final_grade = points_earned / max_points * 100; } else { final_grade = 0; } return final_grade; } int CalculateTotal(std::array < int, kMaxSize > grades, int &num_grades){ double points_earned {}; for (int i{0}; i < num_grades; i++){ points_earned += grades.at(i); } return points_earned; } char CalculateLetter(double final_grade){ if (final_grade >= 90){ return 'A'; } else if (final_grade < 90 && final_grade >= 80){ return 'B'; } else if (final_grade < 80 && final_grade >= 70){ return 'C'; } else if (final_grade < 70 && final_grade >= 60){ return 'D'; } else { return 'F'; } }
问题分析
核心问题集中在以下几点:
ProcessFile函数逻辑错误:先读取一个数字后进入循环,再用for循环将该数字写入数组所有位置,同时每次写入后读取下一个数字。当文件读完最后一个数字后,读取操作失败,但之前的数字会被重复写入数组剩余位置,且num_grades被错误累加至30。CalculateFinalGrade遍历整个数组而非实际读取的成绩数量,会把未初始化的0计入总分,导致计算错误。- main函数中
max_points的计算提前,此时num_grades还是0,导致该值始终为0。
修正后的代码
#include <iostream> #include <fstream> #include <iomanip> #include <array> const int kMaxSize {30}; std::array<int, kMaxSize> ProcessFile(std::ifstream &infile, int &num_grades); double CalculateFinalGrade(std::array<int, kMaxSize> grades, int num_grades); int CalculateTotal(std::array<int, kMaxSize> grades, int num_grades); char CalculateLetter(double final_grade); int main(){ std::string filename{}; std::cout << "Enter the input file: "; std::cin >> filename; std::ifstream infile { filename }; if (!infile){ std::cout << '\n' << filename << " does not exist.\n"; return 1; } int num_grades {}; double final_grade {}; char letter_grade {}; int points_earned {}; int max_points {}; std::array<int, kMaxSize> grades {}; grades = ProcessFile(infile, num_grades); max_points = num_grades * 100; // 打印实际读取的成绩 std::cout << '\n'; for (int i{0}; i < num_grades; i++){ std::cout << grades.at(i) << " "; } std::cout << '\n'; points_earned = CalculateTotal(grades, num_grades); final_grade = CalculateFinalGrade(grades, num_grades); letter_grade = CalculateLetter(final_grade); infile.close(); std::cout << '\n' << "Number of Grades: " << std::setw(11) << std::right << num_grades; std::cout << '\n' << "Total Points Earned: " << std::setw(8) << std::right << points_earned; std::cout << '\n' << "Max Possible Points: " << std::setw(8) << std::right << max_points << '\n'; std::cout << std::fixed << std::setprecision(1); std::cout << '\n' << "Final Grade: " << std::setw(7) << std::right << letter_grade << std::setw(8) << std::right << final_grade << "%" << '\n'; return 0; } std::array<int, kMaxSize> ProcessFile(std::ifstream &infile, int &num_grades){ int number {}; std::array<int, kMaxSize> grades {}; num_grades = 0; // 读取成功且数组未满时才写入 while (num_grades < kMaxSize && infile >> number){ grades.at(num_grades) = number; num_grades++; } return grades; } double CalculateFinalGrade(std::array<int, kMaxSize> grades, int num_grades){ if (num_grades == 0){ return 0; } double points_earned = CalculateTotal(grades, num_grades); int max_points = num_grades * 100; return (points_earned / max_points) * 100; } int CalculateTotal(std::array<int, kMaxSize> grades, int num_grades){ int points_earned = 0; for (int i{0}; i < num_grades; i++){ points_earned += grades.at(i); } return points_earned; } char CalculateLetter(double final_grade){ if (final_grade >= 90){ return 'A'; } else if (final_grade >= 80){ return 'B'; } else if (final_grade >= 70){ return 'C'; } else if (final_grade >= 60){ return 'D'; } else { return 'F'; } }
关键修正点
- ProcessFile函数:重构读取逻辑,仅在读取成功且数组未满时写入数字并计数,彻底避免重复写入和错误计数。
- main函数:将
max_points计算移至ProcessFile调用后,确保使用正确的成绩数量。 - CalculateFinalGrade函数:复用
CalculateTotal函数,只遍历实际读取的成绩,减少冗余并避免错误累加。 - 调试打印:修改打印逻辑,仅输出实际读取的成绩,便于验证结果。
内容的提问来源于stack exchange,提问作者Delaney Logan
相关产品推荐
相关产品推荐

