C++文件读取与信息显示程序异常排查请求
我编写的C++程序需读取superbowl.dat文件中的超级碗比赛数据(每行依次为获胜队名称、失利队名称、获胜队得分),预期实现以下功能:
- 展示所有比赛的详细信息
- 计算并输出获胜队的得分平均值
- 统计得分超过40分的获胜队数量
- 显示得分最高和最低的获胜队及其对应比赛信息
但当前程序的显示功能完全不符合预期,我咨询过同事与教授,调整过显示函数、优化过函数结构,花费数小时调试仍未解决问题。以下是完整代码与数据说明:
原代码实现
//LIBRARIES #include <iostream> #include <iomanip> #include <fstream> #include <stdio.h> #include <math.h> #include <cmath> #include <string> #include <cstring> #include <thread> #include <stdexcept> #include <limits> #include <cctype> using namespace std; //STORED ARRAY NAMES AND FUNCTION NAMES int fillArrays (string teamWin[], string teamLose[], float theScore[], ifstream & final); float pointAverage (float theScore[], float numberOfGames); int teamsScoredForty (float theScore[], int gameNum); int savedMax (float theScore[], int gameNum); int savedMin (float theScore[], int gameNum); void printStoredInformation (string teamWin[], string teamLose[], float theScore[], int gameNum); void finalDisplay (float theScore[], string teamWin[], string teamLose[], int teamsOverForty, float averagePoints, int maxSavedInfo, int minSavedInfo); //START OF MAIN int main () { ifstream final; float theScore[100]; string teamWin[100]; string teamLose[100]; int gameNum; float numberOfGames; float averagePoints; int teamsOverForty; int maxSavedInfo; int minSavedInfo; gameNum = fillArrays (teamWin, teamLose, theScore, final); numberOfGames = gameNum; averagePoints = pointAverage (theScore, numberOfGames); teamsOverForty = teamsScoredForty (theScore, gameNum); maxSavedInfo = savedMax (theScore, gameNum); minSavedInfo = savedMin (theScore, gameNum); printStoredInformation (teamWin, teamLose, theScore, gameNum); finalDisplay (theScore, teamWin, teamLose, teamsOverForty, averagePoints, maxSavedInfo, minSavedInfo); return 0; } //FINAL DISPLAY OF INFORMATION void finalDisplay (float theScore[], string teamWin[], string teamLose[], int teamsOverForty[], float averagePoints, int maxSavedInfo, int minSavedInfo) { cout << "AVERAGE = " << averagePoints << endl; cout << "TEAMS WHO SCORED OVER 40 POINTS IN ONE GAME = " << teamsOverForty << endl; cout << endl; cout << endl; cout << "TEAM WHO SCORED THE MOST POINTS IN ONE GAME" << endl; cout << "WINNERS = " << teamWin[maxSavedInfo] << endl; cout << "LOSERS = " << teamLose[maxSavedInfo] << endl; cout << "FINAL SCORE OF WINNERS" << theScore[maxSavedInfo] << endl; cout << endl; cout << endl; cout << "TEAM WHO SCORED THE LEAST POINTS AND STILL WON" << endl; cout << "WINNERS = " << teamWin[minSavedInfo]; cout << "LOSERS = " << teamLose[minSavedInfo]; cout << "FINAL SCORE OF WINNERS = " << theScore[minSavedInfo]; cout << endl; } //INFORMATION STORAGE FOR ARRAYS int fillArrays (string teamWin[], string teamLose[], float theScore[], ifstream & final) { int i = 0; final.open ("superbowl.dat"); while (!final.eof ()) { getline (final, teamWin[i]); getline (final, teamLose[i]); final >> theScore[i]; final.ignore (1, '\n'); i += 1; } final.close (); return i; } //FUNCTION TO FIND AVERAGE OF THE TEAMS SCORE float pointAverage (float theScore[], float numberOfGames) { float sum; float avg; for (int i = 0; i < numberOfGames; i++) { sum = sum + theScore[i]; } avg = sum / numberOfGames; return avg; } //FUNCTION FOR ALL THE TEAMS WHO SCORED MORE THEN FORTY int teamsScoredForty (float theScore[], int gameNum) { int teamSavedScoreOverForty = 0; for (int i = 0; i < gameNum; i++) { if (theScore[i] > 40) { teamSavedScoreOverForty = teamSavedScoreOverForty + 1; } } return teamSavedScoreOverForty; } //FUNCTION TO FIND WHICH TEAM SCORED MORE THEN ANY OTHER TEAM AND WON int savedMax (float theScore[], int gameNum) { int val = -1; int idx; for (int i = 0; i < gameNum; i++) { if (val < theScore[i]) { val = theScore[i]; idx = 1; } } return idx; } //FUNCTION TO FIND WHICH TEAM SCORED LESS THEN ANY OTHER TEAM AND WON int savedMin (float theScore[], int gameNum) { int val = theScore[0]; int idx; for (int i = 0; i < gameNum; i++) { if (theScore[i] < val) { idx = i; } } return idx; } //FINAL DISPLAY FUNCTION FOR ALL OF THE INFORMATION ABOVE void printStoredInformation (string teamWin[], string teamLose[], float theScore[], int gameNum) { int a = 1; for (int i = 0; i < gameNum; i++) { cout << "SUPER BOWL " << a << endl; cout << "NAME OF WINNING TEAM - " << teamWin[i] << endl; cout << "NAME OF LOSING TEAM - " << teamLose[i] << endl; cout << "TOTAL POINTS SCORED BY WINNERS - " << theScore[i] << endl; cout << endl; a = a + 1; } }
文件数据格式
superbowl.dat文件每行依次存储:获胜队名称、失利队名称、获胜队得分,示例数据如下(每行单独换行):
Packers Chiefs 35 Packers Raiders 33 Jets Colts 16 ...(剩余数据略)
问题排查与修复方案
以下是程序中存在的核心错误及修复方式:
finalDisplay函数参数类型不匹配
函数声明中teamsOverForty为int类型,但定义时错误写成数组int teamsOverForty[],导致调用时类型冲突。
修复:将函数定义的参数改为int teamsOverForty,与声明保持一致。pointAverage函数未初始化累加变量sum未初始化就直接累加,会导致平均值计算为随机垃圾值。
修复:初始化sum = 0.0f;。savedMax函数逻辑错误
找到更大得分时,错误将索引idx赋值为1而非当前循环的i,导致永远返回第2个元素的索引。同时idx未初始化,存在未定义行为。
修复:初始化idx = 0;,并将idx = 1;改为idx = i;。savedMin函数逻辑错误idx未初始化,若第一个元素为最小值,返回值为垃圾值- 未更新
val的值,导致后续比较始终使用初始的theScore[0],无法正确找到最小值
修复:初始化idx = 0;,并在更新idx时同步更新val = theScore[i];。
fillArrays函数循环条件问题
使用!final.eof()作为循环条件会导致最后一组数据被重复读取,因为eof()仅在读取失败后才会置位。
修复:将循环条件改为读取操作的结果,同时优化ignore的写法避免遗漏换行:while (getline(final, teamWin[i]) && getline(final, teamLose[i]) && (final >> theScore[i])) { final.ignore(numeric_limits<streamsize>::max(), '\n'); i++; }finalDisplay函数输出格式错误
得分最高队伍的输出行缺少等号,得分最低队伍的输出无换行,可读性差。
修复:补全等号,添加换行符:cout << "FINAL SCORE OF WINNERS = " << theScore[maxSavedInfo] << endl; // ... cout << "WINNERS = " << teamWin[minSavedInfo] << endl; cout << "LOSERS = " << teamLose[minSavedInfo] << endl; cout << "FINAL SCORE OF WINNERS = " << theScore[minSavedInfo] << endl;
修正后的完整代码
//LIBRARIES #include <iostream> #include <iomanip> #include <fstream> #include <stdio.h> #include <math.h> #include <cmath> #include <string> #include <cstring> #include <thread> #include <stdexcept> #include <limits> #include <cctype> using namespace std; //STORED ARRAY NAMES AND FUNCTION NAMES int fillArrays (string teamWin[], string teamLose[], float theScore[], ifstream & final); float pointAverage (float theScore[], float numberOfGames); int teamsScoredForty (float theScore[], int gameNum); int savedMax (float theScore[], int gameNum); int savedMin (float theScore[], int gameNum); void printStoredInformation (string teamWin[], string teamLose[], float theScore[], int gameNum); void finalDisplay (float theScore[], string teamWin[], string teamLose[], int teamsOverForty, float averagePoints, int maxSavedInfo, int minSavedInfo); //START OF MAIN int main () { ifstream final; float theScore[100]; string teamWin[100]; string teamLose[100]; int gameNum; float numberOfGames; float averagePoints; int teamsOverForty; int maxSavedInfo; int minSavedInfo; gameNum = fillArrays (teamWin, teamLose, theScore, final); numberOfGames = gameNum; averagePoints = pointAverage (theScore, numberOfGames); teamsOverForty = teamsScoredForty (theScore, gameNum); maxSavedInfo = savedMax (theScore, gameNum); minSavedInfo = savedMin (theScore, gameNum); printStoredInformation (teamWin, teamLose, theScore, gameNum); finalDisplay (theScore, teamWin, teamLose, teamsOverForty, averagePoints, maxSavedInfo, minSavedInfo); return 0; } //FINAL DISPLAY OF INFORMATION void finalDisplay (float theScore[], string teamWin[], string teamLose[], int teamsOverForty, float averagePoints, int maxSavedInfo, int minSavedInfo) { cout << "AVERAGE = " << averagePoints << endl; cout << "TEAMS WHO SCORED OVER 40 POINTS IN ONE GAME = " << teamsOverForty << endl; cout << endl << endl; cout << "TEAM WHO SCORED THE MOST POINTS IN ONE GAME" << endl; cout << "WINNERS = " << teamWin[maxSavedInfo] << endl; cout << "LOSERS = " << teamLose[maxSavedInfo] << endl; cout << "FINAL SCORE OF WINNERS = " << theScore[maxSavedInfo] << endl; cout << endl << endl; cout << "TEAM WHO SCORED THE LEAST POINTS AND STILL WON" << endl; cout << "WINNERS = " << teamWin[minSavedInfo] << endl; cout << "LOSERS = " << teamLose[minSavedInfo] << endl; cout << "FINAL SCORE OF WINNERS = " << theScore[minSavedInfo] << endl; } //INFORMATION STORAGE FOR ARRAYS int fillArrays (string teamWin[], string teamLose[], float theScore[], ifstream & final) { int i = 0; final.open ("superbowl.dat"); while (getline(final, teamWin[i]) && getline(final, teamLose[i]) && (final >> theScore[i])) { final.ignore(numeric_limits<streamsize>::max(), '\n'); i++; } final.close (); return i; } //FUNCTION TO FIND AVERAGE OF THE TEAMS SCORE float pointAverage (float theScore[], float numberOfGames) { float sum = 0.0f; float avg; for (int i = 0; i < numberOfGames; i++) { sum += theScore[i]; } avg = sum / numberOfGames; return avg; } //FUNCTION FOR ALL THE TEAMS WHO SCORED MORE THEN FORTY int teamsScoredForty (float theScore[], int gameNum) { int teamSavedScoreOverForty = 0; for (int i = 0; i < gameNum; i++) { if (theScore[i] > 40) { teamSavedScoreOverForty++; } } return teamSavedScoreOverForty; } //FUNCTION TO FIND WHICH TEAM SCORED MORE THEN ANY OTHER TEAM AND WON int savedMax (float theScore[], int gameNum) { int val = theScore[0]; int idx = 0; for (int i = 1; i < gameNum; i++) { if (val < theScore[i]) { val = theScore[i]; idx = i; } } return idx; } //FUNCTION TO FIND WHICH TEAM SCORED LESS THEN ANY OTHER TEAM AND WON int savedMin (float theScore[], int gameNum) { int val = theScore[0]; int idx = 0; for (int i = 1; i < gameNum; i++) { if (theScore[i] < val) { val = theScore[i]; idx = i; } } return idx; } //FINAL DISPLAY FUNCTION FOR ALL OF THE INFORMATION ABOVE void printStoredInformation (string teamWin[], string teamLose[], float theScore[], int gameNum) { int a = 1; for (int i = 0; i < gameNum; i++) { cout << "SUPER BOWL " << a << endl; cout << "NAME OF WINNING TEAM - " << teamWin[i] << endl; cout << "NAME OF LOSING TEAM - " << teamLose[i] << endl; cout << "TOTAL POINTS SCORED BY WINNERS - " << theScore[i] << endl; cout << endl; a++; } }
内容的提问来源于stack exchange,提问作者John Walker

