【问题标题】:While loop not reading entire ifstream file虽然循环不读取整个 ifstream 文件
【发布时间】:2018-10-05 15:21:03
【问题描述】:

我的 ReadFile 函数没有读取我的整个文件。该文件包含多行信息,每行都与一名学生有关。

函数(或者可能是 while 循环)正在读取前两条记录,然后退出循环。它正在正确读取所有内容,但为什么它不继续读取整个文件(其中有 13 条记录)?

我已经尝试过while(!infile.eof()),但该程序甚至无法运行。

这是我的 ReadFile 块:

void ReadFile() {// Reads data file into array

    ifstream infile;

    infile.open(cTextFileName);

    if (!infile.good()) {
        cout << "Cant find text data file!" << endl;
        exit(1);
    }

    int i = 0;
    int status;
    //bool endOfFile = infile.eof();

    infile >> gRecs[i].StudentNo;

    while (infile) {
        infile >> gRecs[i].FirstName;
        infile >> gRecs[i].LastName;
        infile >> gRecs[i].NumSubjects;
        //cout << "ENTERED WHILE LOOP" << endl;

        for (int j = 0; j < gRecs->NumSubjects; j++) {
            infile >> gRecs[i].Subjects[j].Code;
            infile >> status;

            if (status == 0) {
                gRecs[i].Subjects[j].Status == eEnrolled;
            } else if (status == 1) {
                gRecs[i].Subjects[j].Status == eProvisional;
            } else {
                gRecs[i].Subjects[j].Status == eWithdrawn;
            }


            infile >> gRecs[i].Subjects[j].Mark;

        }

        i++;
        infile >> gRecs[i].StudentNo;
    }

    gNumRecs = i;
    infile.close();
    infile.clear();

    cout << gNumRecs << " Records read!" << endl;
}

【问题讨论】:

  • 您将不得不展示文件的格式。你们中的一个输入操作不正确,导致读取操作失败,从而导致循环失败。
  • 这里是文本文件。 pastebin.com/CCN59Dm9
  • 那么在调试代码时会发生什么?
  • 这并没有解决问题,而是养成使用有意义的值初始化对象的习惯,而不是默认初始化它们并稍后分配值。即,将ifstream infile; infile.open(whatever)' 更改为ifstream infield(whatever);。并且不需要对infile.close() 的调用;析构函数会这样做。最后,在您关闭文件后调用 infile.clear() 不会完成任何操作。

标签: c++ fileinputstream


【解决方案1】:
for (int j = 0; j < gRecs->NumSubjects; j++) {

应该是

for (int j = 0; j < gRecs[i].NumSubjects; j++) {

【讨论】:

  • 这行得通。但我不明白为什么索引需要在那里。我们只是循环直到达到主题数。前 2 条记录的循环运行良好,但后来却没有,所以我很困惑
  • 如果没有索引,您实际上是在访问数组的第一个元素,这对于第一条记录是正确的,但不适用于以下记录。
  • 换句话说 gRecs->NumSubjects 与 gRecs[0].NumSubjects 相同,所以你在第一个很幸运,但之后就错了。
  • 但是为什么第二条记录能正确存储呢?
  • 您必须向我们展示类定义才能弄清楚。
【解决方案2】:

在我看来,这个问题的最佳解决方案就是完全避免它。

我将编写一个仅读取单个记录的函数,而不是尝试读取整个文件的单个函数。然后重复调用该函数,直到读取整个文件。为了适应标准库其余部分的工作方式,读取单个记录的函数应命名为operator&gt;&gt;。它应该接收一个istream 的引用和一个对记录的引用,并在完成后返回对istream 的引用。

std::istream &operator>>(std::istream &is, gRec &record) {
    is >> record.FirstName;
    is >> record.LastName;
    is >> record.NumSubjects;
    for (int i=0; i<record.NumSubjects; i++) {
        is >> record.subjects[i].code;

        int raw_status;
        is >> raw_status;
        record.subject[i].status = cvt_status(raw_status);
        is >> record.mark;
    }
    return is;
}

就个人而言,我可能会从那里进行一些更改。我会创建一个StatusSubjectSchedule,每个都定义了自己的operator&gt;&gt; 以从文件中读取自己:

class Status {
    enum class status { enrolled, provisional, withdrawn } s;

    friend std::istream &operator>>(std::istream &is, Status &s) { 
        int i;
        is >> i;
        switch (i) { 
            case 1: s.s = status::enrolled;    break;
            case 2: s.s = status::provisional; break;
            case 3: s.s = status::withdrawn;   break;
        }
        return is;
    }
};

class Subject {
    int code;
    Status status;
    int mark;
public:
    friend std::istream &operator>>(std::istream &is, Subject &s) { 
        return is >> s.code >> s.status >> s.mark;
    }
};

class Schedule {
    std::vector<Subject> classes;
public:
    friend std::istream &operator>>(std::istream &is) {
        int num;
        is >> num;
        for (int i=0; i<num; i++) {
            Subject temp;
            is >> temp;
            classes.push_back(temp);
       }
       return is;
    }
};

那么记录会是这样的:

class Record {
    std::string FirstName, LastName;
    Schedule classes;
public:
    std::istream &operator>>(std::istream &is, Record &r) {
        return is >> r.FirstName >> r.LastName >> r.classes;
    }
};

最后,读取一个完整的学生记录文件将是这样的:

std::ifstream infile("filename");
std::vector<Record> records{std::istream_iterator<Record>(infile), {}};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    相关资源
    最近更新 更多