c++ EOF 运行了太多次?
Posted
技术标签:
【中文标题】c++ EOF 运行了太多次?【英文标题】:c++ EOF running one too many times? 【发布时间】:2012-01-04 09:07:18 【问题描述】:这是我第一次使用 EOF 和/或文件,我遇到了代码挂起的问题,我认为这是因为我的 EOF 循环了太多次。
我从一个文件中输入,并以这种方式动态创建对象,一旦文件运行它就会挂起。
while( !studentFile.eof() )
cout << "38\n";
Student * temp = new Student();
(*temp).input( studentFile );
(*sdb).insert( (*temp) );
这段代码就是有问题的代码。 cout >> "38\n";是行号,也是我认为它因循环一个太多次而挂起的原因。
该文件仅包含 4 个学生的数据,但 38 出现了 5 次,这就是我认为它循环了太多次的原因;一旦它得到最后一点数据,它似乎并没有注册文件已经结束,并再次循环,但没有数据输入,所以我的代码挂起。
我该如何解决这个问题?我的逻辑对吗?
谢谢。
【问题讨论】:
Why is iostream::eof inside a loop condition considered wrong? 的可能重复项 【参考方案1】:其他人已经指出了你注意到的问题的细节。
但是,您应该意识到还有更多您尚未注意到的问题。一个是相当明显的内存泄漏。循环的每次迭代都会执行:Student * temp = new Student();
,但您永远不会执行匹配的delete
。
C++ 使内存管理比其他一些语言(例如 Java)简单得多,后者要求您使用new
使用的每个对象。在 C++ 中,您可以定义一个对象并使用它:
Student temp;
temp.input(studentFile);
这简化了代码并消除了内存泄漏 - 您的 Student
对象将在每次迭代结束时自动销毁,并在下一次迭代开始时创建(概念上)新的/不同的对象。
虽然这并不是真正的错误本身,但仍然可以简化很多。由于sdb
指向的任何东西显然都有insert
成员函数,因此您可以像标准容器一样使用它(实际上它可能成为,尽管这两种方法都无关紧要)。要整理代码,首先要为 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,因此您根本不必像开始时那样处理问题(即使您想要导致它们,这也不容易)。
【讨论】:
谢谢!有点难以理解,但我设法让它工作。将来会很高兴知道这一点。【参考方案2】:这是因为 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 之前阅读。
【讨论】:
【参考方案3】:您需要在对流执行操作后立即检查流状态位。您没有显示代码,但似乎(*temp).input(studentFile)
正在从流中读取。调用eof()
(或其他状态检查)在执行读取但在处理您(尝试)读取的数据之前。
【讨论】:
以上是关于c++ EOF 运行了太多次?的主要内容,如果未能解决你的问题,请参考以下文章
C++ Monte Carlo 集成:如何在不求和结果的情况下多次运行代码?