C++学生成绩统计程序文件读写异常及重复统计问题求助
Hey there, let's work through fixing your C++ student grade program issues step by step. I've gone through your code and identified the root causes for each problem you're facing:
Problem 1: Messy Console Output & Duplicate Last Line When Reading File
What's wrong:
- You're reading and printing the entire
Record.txtevery time you process a single student in thecalculations()method. This means after the first student, you print their data, then after the second student, you print both students' data again—leading to duplicated, messy output. - Using
while(!input.eof())is a common pitfall: the EOF flag is only set after you attempt to read past the end of the file. So when you reach the last line,getline()will fail, but you'll still print the previously read line one extra time. - Tabs (
\t) don't guarantee consistent alignment, especially if names or numbers vary in length.
Fix:
- Move the file reading/console output logic to after all students have been processed and written to the file.
- Replace the EOF check with
while(getline(input, str))—this loop stops automatically whengetline()fails (like at EOF). - Use
std::setwandstd::leftfrom<iomanip>to create clean, aligned columns in the console.
Problem 2: Duplicate Grade Count Entries in Record.txt
What's wrong:
- You're calling
total()twice in your main loop (once per student). Each call appends the grade counts to the file, hence the duplicates. - The
counter1tocounter5are non-static member variables—this means everyStudentResultobject has its own set of counters. So when you calltotal()on the first student, it only counts that student's grade, and the second call counts only the second student's grade (with the first student's counters reset to 0).
Fix:
- Make the counters static member variables so they're shared across all
StudentResultobjects—this way, every student's grade increments the same global counters. - Call
total()only once after processing all students, not in a loop.
Problem 3: Incorrect Percentage Calculation (Bonus Fix)
Your current percentage calculation percentage = (Final_score*100)/100 does nothing useful—it just returns Final_score. I assume you intended to calculate the percentage based on the total possible marks (e.g., if sessional is out of 20, mids 30, finals 50, total 100). I've adjusted this in the fixed code to use a total of 100 (you can tweak this if your actual total marks are different).
Fixed Complete Code
#include<iostream> #include<string> #include<fstream> #include<iomanip> // For setw and left formatting using namespace std; class StudentResult{ private: int sessional; int mids; int finals; int Final_score; float percentage; char grade; string Fname; string Lname; // Make counters static to share across all objects static int counter1, counter2, counter3, counter4, counter5; string str; public: StudentResult(){} void setter() { cout<<"Enter first name: "; cin>>Fname; cout<<"Enter Last name: "; cin>>Lname; cout<<"Enter sessional marks: "; cin>>sessional; cout<<"Enter mids marks: "; cin>>mids; cout<<"Enter finals marks: "; cin>>finals; } void calculations() { Final_score = sessional + mids + finals; // Adjust total marks here if your actual total is different (e.g., 100 is assumed) const int TOTAL_MARKS = 100; percentage = (static_cast<float>(Final_score) / TOTAL_MARKS) * 100; // Use else if to avoid redundant checks if(percentage >= 80 && percentage <= 100) { grade='A'; counter1++; } else if(percentage >=71 && percentage <80) { grade='B'; counter2++; } else if(percentage >=61 && percentage <=70) { grade='C'; counter3++; } else if(percentage >=50 && percentage <=60) { grade='D'; counter4++; } else if(percentage >=0 && percentage <=49) { grade='F'; counter5++; } // Write only this student's data to the file ofstream output("Record.txt", ios::app); if(!output) { cout<<"Error opening file for writing!"<<endl; return; } // Write with tab separation and formatted percentage output<<Fname<<"\t"<<Lname<<"\t"<<sessional<<"\t"<<mids<<"\t"<<finals<<"\t"<<fixed<<setprecision(2)<<percentage<<"\t"<<grade<<"\n"; output.close(); } void total() { ofstream output("Record.txt", ios::app); if(!output) { cout<<"Error opening file for writing totals!"<<endl; return; } output<<"\n--- Grade Summary ---\n"; output<<"Total number of students who secured A grade: "<<counter1<<"\n"; output<<"Total number of students who secured B grade: "<<counter2<<"\n"; output<<"Total number of students who secured C grade: "<<counter3<<"\n"; output<<"Total number of students who secured D grade: "<<counter4<<"\n"; output<<"Total number of students who secured F grade: "<<counter5<<"\n"; output.close(); } // Static method to reset counters (useful if you run the program multiple times) static void resetCounters() { counter1 = counter2 = counter3 = counter4 = counter5 = 0; } }; // Initialize static member variables outside the class int StudentResult::counter1 = 0; int StudentResult::counter2 = 0; int StudentResult::counter3 = 0; int StudentResult::counter4 = 0; int StudentResult::counter5 = 0; int main(){ // Reset counters in case of multiple runs (safe practice) StudentResult::resetCounters(); StudentResult array[2]; for(int i=0 ; i < 2 ; i++) { cout<<"\nEnter details for Student "<<i+1<<":\n"; array[i].setter(); } for(int i=0 ; i < 2 ; i++) { array[i].calculations(); } // Call total() ONCE after all students are processed array[0].total(); // Now read and print the file to console with aligned formatting cout<<"\n--- Record.txt Contents ---\n"; ifstream input("Record.txt"); if(!input) { cout<<"Error opening file for reading!"<<endl; return 1; } // Print header with aligned columns cout<<left<<setw(15)<<"First Name"<<setw(15)<<"Last Name"<<setw(12)<<"Sessional"<<setw(10)<<"Mids"<<setw(10)<<"Finals"<<setw(12)<<"Percentage"<<setw(8)<<"Grade"<<endl; cout<<"----------------------------------------------------------------------------------------\n"; string line; // Use getline in the loop condition to avoid duplicate last line while(getline(input, line)) { cout<<line<<endl; } input.close(); return 0; }
Key Changes Explained:
- Static Counters: The grade counters are now static, so all student objects share the same counts—fixing incorrect and duplicated statistics.
- Single
total()Call: We only append the grade summary once after all students are processed. - Fixed File Reading: Replaced
while(!input.eof())withwhile(getline(input, line))to eliminate the duplicate last line. - Aligned Console Output: Used
<iomanip>tools (setw,left) to create clean, consistent columns for the header. - Improved Percentage Calculation: Cast
Final_scoretofloatto avoid integer division, and added aTOTAL_MARKSconstant for easy adjustment. - Removed Redundant Reads: No longer reading the entire file after each student—only read once at the end.
内容的提问来源于stack exchange,提问作者Arooba
相关产品推荐
相关产品推荐

