1

这是我第一次使用 EOF 和/或文件,我遇到了代码挂起的问题,我相信这是因为我的 EOF 循环了太多次。

我正在从一个文件中输入,并以这种方式动态创建对象,并且一旦文件运行它就会挂起。

        while( !studentFile.eof() )
    {
        cout << "38\n";
        Student * temp = new Student();
        (*temp).input( studentFile );

        (*sdb).insert( (*temp) );           
    }

这段代码就是有问题的代码。cout >> "38\n"; 是行号,也是我认为它挂在循环一个太多次的原因。

该文件仅包含 4 个学生的数据,但 38 出现了 5 次,这就是我认为它循环了太多次的原因;一旦它得到最后一点数据,它似乎没有记录文件已经结束,并再次循环,但没有数据输入,所以我的代码挂起。

我该如何解决?我的逻辑正确吗?

谢谢你。

4

3 回答 3

3

这是因为 EOF 标志仅您尝试读取但未获取数据后设置。所以它会去

Test for EOF -> No EOF
Try to read one line -> Good, read first line
Test for EOF -> No EOF
Try to read one line -> Good, read second line
Test for EOF -> No EOF
Try to read one line -> Good, read third line
Test for EOF -> No EOF
Try to read one line -> Good, read fourth line
Test for EOF -> No EOF
Try to read one line -> EOF

但是到 时Try to read one line -> EOF,您已经在while第五次迭代的主体中,这就是为什么您看到循环运行 5 次的原因。因此,您需要在检查 EOF 之前阅读。

于 2011-11-23T00:54:15.817 回答
3

其他人已经指出了您注意到的问题的细节。

但是,您应该意识到,还有更多您尚未注意到的问题。一个是相当明显的内存泄漏。循环的每次迭代都会执行: Student * temp = new Student();,但你永远不会执行匹配的delete.

C++ 使内存管理比其他一些语言(例如,Java)简单得多,后者要求您处理new所使用的每个对象。在 C++ 中,您可以定义一个对象并使用它:

Student temp;

temp.input(studentFile);

这简化了代码并消除了内存泄漏——您的Student对象将在每次迭代结束时自动销毁,并在下一次迭代开始时创建(概念上)新的/不同的对象。

虽然它本身并不是一个真正的错误,但即使这样仍然可以简化很多。由于任何sdb点显然都有一个insert成员函数,因此您可以像标准容器一样使用它(它实际上可能,尽管这两种方式都无关紧要)。为了整理代码,首先为 a 编写一个提取运算符Student

std::istream &operator>>(std::istream &is, Student &s) {
    s.input(is);
    return is;
}

然后您可以将数据从流中复制到集合中:

std::copy(std::istream_iterator<Student>(studentFile),
          std::istream_iterator<Student>(),
          std::inserter(*sdf));

请注意,这会自动正确处理 EOF,因此您根本不必像开始时那样处理问题(即使您引起它们,也不容易)。

于 2011-11-23T01:12:44.157 回答
0

您需要在对流执行操作后立即检查流状态位。您没有显示代码,但似乎(*temp).input(studentFile)正在从流中读取。在读取之后但处理您(尝试)读取的数据之前调用eof()(或其他状态检查) 。

于 2011-11-23T00:58:13.397 回答