这是我第一次使用EOF和/或文件,而我遇到的问题是我的代码挂起,我相信这是因为我的EOF循环次数太多了。
我从文件中输入,并以这种方式动态创建对象,并在文件运行后挂起。
while( !studentFile.eof() )
{
cout << "38\n";
Student * temp = new Student();
(*temp).input( studentFile );
(*sdb).insert( (*temp) );
}
这段代码是有问题的代码。 cout&gt;&gt; “38 \ n” 个;是行号和我认为它多次循环的原因。
该文件仅包含4个学生的数据,但38个出现5次,这就是我认为它循环次数太多的原因;一旦它获得最后一位数据,它似乎没有注册文件已经结束,并再次循环,但没有数据输入所以我的代码挂起。
我该如何解决这个问题?我的逻辑是否正确?
谢谢。
答案 0 :(得分: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之前阅读。
答案 1 :(得分:3)
其他人已经指出了你注意到的问题的细节。
然而,您应该意识到还有更多您尚未注意到的问题。一个是相当明显的内存泄漏。循环的每次迭代都会执行: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 :(得分:0)
您需要在对流执行操作后立即检查流状态位。您不显示代码,但看起来(*temp).input(studentFile)
正在从流中读取。在执行读取后调用eof()
(或其他状态检查),但在处理之前使用您(尝试)读取的数据调用。