【问题标题】:How does one correctly pass on ofstream object?如何正确传递 ofstream 对象?
【发布时间】:2025-05-25 17:10:02
【问题描述】:

我正在编写代码来输入学生和成绩对象,对它们进行排序,计算平均 gpa,然后将它们输出到文件中。我目前的问题是我的学生对象的输出是在我对它们进行排序并打印它们之后给出的,但是一旦我这样做,代码似乎并没有离开循环。我有一个打印功能,我在其中传递了一个 ofstream。从调试中,我知道 outstream 对象读取了所有内容,但随后它似乎冻结了,并且没有向其中输出任何其他内容。有人可以告诉我我是否错误地通过引用传递,或者我是否需要做其他事情?代码中标出了编译器没有继续执行的错误。

抱歉,有关更多信息,以下是运行内容的片段

output code in text file

请注意“通过它”如何只显示一次。我知道打开文件并输出不是问题,因为它确实输出了正确的东西。此外,为了更正,编译器实际上编译一切都很好。在运行时终端停止,没有更多的输出。

#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <string>
#include "Grade.h"
#include "Student.h"

using namespace std;

const double A_NUM = 4.0, B_NUM = 3.0, C_NUM = 2.0, D_NUM = 1.0, E_NUM = 0.0, B_PLUSSNUM = 3.4, C_PLUSSNUM = 2.4, D_PLUSSNUM = 1.4;
const double A_MINUSNUM = 3.7, B_MINUSNUM = 2.7, C_MINUSNUM = 1.7, D_MINUSNUM = 0.7;
const int FIRST_INDEX= 0;
const int START_NUM = 0;
const int LESS_ONE = 1, ABOVE_ONE = 1;
const int START_GRADE = 0;

void calcgrades(vector<Grade>& grades)//function that calculates gpa based on letter grades
{
    const string A = "A", A_MINUS = "A-", B_PLUSS = "B+", B = "B", B_MINUS = "B-", C_PLUSS = "C+", C = "C", C_MINUS = "C-", D_PLUSS = "D+", D = "D", D_MINUS = "D-", E = "E";
    int counter = START_NUM;//used to keep track of current student and current total grade
    double current_grade = START_NUM;

    for(int i = 0; i < grades.size();i++)
    {

        //while loop to get the student's current total grade if the next student id is different than the first one.
        while(i < grades.size()-LESS_ONE && grades[i].getid() == grades[i+ABOVE_ONE].getid())
        {
            if (grades[i].getgrade() == A)
            {
                current_grade == A_NUM + current_grade;
            }
            if (grades[i].getgrade() == B)
            {
                current_grade == B_NUM + current_grade;
            }
            if (grades[i].getgrade() == C)
            {
                current_grade == C_NUM + current_grade;
            }
            if (grades[i].getgrade() == D)
            {
                current_grade == D_NUM + current_grade;
            }
            if (grades[i].getgrade() == E)
            {
                current_grade == E_NUM + current_grade;
            }
            if (grades[i].getgrade() == B_PLUSS)
            {
                current_grade == B_PLUSSNUM + current_grade;
            }
            if (grades[i].getgrade() == C_PLUSS)
            {
                current_grade == C_PLUSSNUM + current_grade;
            }
            if (grades[i].getgrade() == D_PLUSS)
            {
                current_grade == D_PLUSSNUM + current_grade;
            }
            if (grades[i].getgrade() == A_MINUS)
            {
                current_grade == A_MINUSNUM + current_grade;
            }
            if (grades[i].getgrade() == B_MINUS)
            {
                current_grade = B_MINUSNUM + current_grade;
            }
            if (grades[i].getgrade() == C_MINUS)
            {
                current_grade = C_MINUSNUM + current_grade;
            }
            if (grades[i].getgrade() == D_MINUS)
            {
                current_grade = D_MINUSNUM + current_grade;
            }

        }


        if (grades[i+ABOVE_ONE].getid() !=  grades[i].getid() || i == grades.size()-LESS_ONE)
        {

            //computes the average if the currentid is not equal to the nextid
            double avggpa = current_grade/counter;

            grades[i].newgpa(avggpa);
            counter = START_NUM;//resets counter for a new student to get his gpa
        }

        counter++;
    }
}



int main(int argc, char* argv[])
{
    string student_file, grades_file, idnum, name, address, pnum, course, gletter;

    //creates student and grade objects from respective classes
    vector<Student> students;
    vector<Grade> grades;


    student_file = argv[1];

    //reads in information from file to import into student objects
    ifstream sfile;

    sfile.open(student_file);




    while(getline(sfile, idnum))//gets the student information from student file
    {
        getline(sfile, name);
        getline(sfile, address);
        getline(sfile, pnum);

        //creates student objects to import info. into, and inserts into students vector
        Student s(idnum, name, address, pnum);
        students.push_back(s);

    }

    sfile.close();

    //opens information from the grade file
    grades_file = argv[2];

    //reads from file to import into grades objects
    ifstream gfile;

    gfile.open(grades_file);

    //gets the grade information from the grades file
    while(getline(gfile, course))
    {
        getline(gfile, idnum);
        getline(gfile, gletter);

        //creates grade objects to import info, and inserts into grades vector
        Grade g(course, idnum, gletter, START_GRADE);
        grades.push_back(g);
    }

    gfile.close();

    //reads the query file
    string query_file;
    query_file = argv[3];

    ifstream qfile;

    qfile.open(query_file);

    //reads from query file
    //creates vector to store each student number
    vector<string> query_nums;
    string incheck;

    while(getline(qfile, incheck))
    {
        query_nums.push_back(incheck); 
    }

    qfile.close();

    //sorts the information for the students
    sort(students.begin(), students.end());


    //sorts the information for the grades
    sort(grades.begin(), grades.end());

    ofstream outtxt;

    string out_file = argv[4];

    outtxt.open(out_file);

    //outputs the student information, sorted now.
    for(int i = 0; i < students.size();i++)
    {
        students[i].print(outtxt);

        outtxt << "got through it";
    }

    //compiler did not get past here!
outtxt << "We're here!";

    //outputs the grades with student id's, now sorted
    for (int i = 0; i < grades.size(); i++)
    {
        grades[i].print(outtxt);
        outtxt << "\n\n" << "some output!";
    }


    //calculates the average gpa for every student
    calcgrades(grades);



    for(int i = 0; i < query_nums.size(); i++)//goes through each query number to check first
    {
        for (int j = 0; j < students.size(); j++)//after, goes through each student object
        {
            if (query_nums[i] == students[j].getid())
            {
                //finds the gpa in the grades class that matches the student id
                for (int k = 0; k < grades.size(); k++)
                {
                    if (grades[k].getid() == query_nums[i])//
                    {
                        //outputs the resulting id, avg gpa, and name of matching students
                        outtxt << grades[i].getid() << "\tthere is nothinghere" << grades[i].getgpa() << "\t" << students[i].getname();

                    }
                }

            }
        }
    }

    outtxt.close();

return 0;

}

具有打印功能的学生课

class Student
{

private:
    string idnum;
    string name;
    string address;
    string pnum;

public:

    //defines constructor
    Student(string idnum,string name,string address,string pnum);


    //prints each student info
    void print(ofstream& out);

    string getname();

    string getid();

    bool operator < (Student s) const {
    return idnum < s.idnum;
  }


};

学生cpp文件

#include "Student.h"
#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>

using namespace std;

//Student constructor, used to make student objects
    Student::Student(string id,string nm,string add,string pnumber)
{
    idnum = id;
    name = nm;
    address = add;
    pnum = pnumber;
}

    void Student::print(ofstream& out)
    {
        out << name << endl << idnum << endl << pnum << endl << address << endl;
    }

    string Student::getname()
    {
        //returns the student name
        return name;
    }


    string Student::getid()
    {
        return idnum;
    }

【问题讨论】:

标签: c++ parameter-passing ofstream


【解决方案1】:

在回答有关如何正确传递 ofstream 对象的问题时,您正确传递了它。

那么为什么它不起作用?从您的代码中可以观察到的内容来看,它应该可以正常工作。我建议在这些代码行中调试输出文件名:

ofstream outtxt;

string out_file = argv[4];

outtxt.open(out_file);

在调用 open 函数后通过检查 ios::fail 标志来验证 open 函数是否成功。

打开后试试这样的:

if (ios::fail)
    cout << "fail";

我希望这会有所帮助。

已编辑:可能还有其他问题,但是 calcgrades() 函数在最后一次 for 循环迭代中存在访问冲突,在 while 循环之后,在这个 if 语句处:

    if (grades[i+ABOVE_ONE].getid() !=  grades[i].getid() || i == grades.size()-LESS_ONE)

【讨论】:

  • 我知道打开文件并输出不是问题,因为它确实输出了正确的内容。请参阅上面的附加图片^
  • @RickGiovanini 在跳过“students[i].print(outtxt);”之后,调试器在第二个循环中显示什么?
  • 对不起,我知道这可能是题外话,但我真的没有调试器。我必须使用 ubuntu 和 sublime 文本以及终端来上课,而且我不知道如何轻松地将其与 Visual Studio 对齐(主要是 argv 和 char 等)。所以,这可能也是我最大的问题之一。有什么想法吗?
  • @RickGiovanini,也尝试在每次写入后添加这一行(仅用于调试)并查看输出文件中是否显示更多行:outtxt.flush();
  • 更多的成功,但还不够!感谢你目前的帮助。当我在循环中的“通过它”文本之后放置刷新时,代码又添加了 1 个“通过它”。我也把同花顺放在循环的外面,但它没有达到“我们在这里!”