You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.txt every time you process a single student in the calculations() 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 when getline() fails (like at EOF).
  • Use std::setw and std::left from <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 counter1 to counter5 are non-static member variables—this means every StudentResult object has its own set of counters. So when you call total() 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 StudentResult objects—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:

  1. Static Counters: The grade counters are now static, so all student objects share the same counts—fixing incorrect and duplicated statistics.
  2. Single total() Call: We only append the grade summary once after all students are processed.
  3. Fixed File Reading: Replaced while(!input.eof()) with while(getline(input, line)) to eliminate the duplicate last line.
  4. Aligned Console Output: Used <iomanip> tools (setw, left) to create clean, consistent columns for the header.
  5. Improved Percentage Calculation: Cast Final_score to float to avoid integer division, and added a TOTAL_MARKS constant for easy adjustment.
  6. Removed Redundant Reads: No longer reading the entire file after each student—only read once at the end.

内容的提问来源于stack exchange,提问作者Arooba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 19:58:11