从文件函数读取的C ++在循环时无法退出

时间:2012-12-20 14:08:31

标签: c++ while-loop eof

  

可能重复:
  End of File in C++

我编写了一个从.txt文件中读取数据的函数,但是当我调用它时,它会一直崩溃。 这是代码:

void beolvas(vector<int> &charge, vector<int> &deliver, vector<Robot*> &robots) {
    string s;
    ifstream f;

    do {
        cout << "Add meg a filenevet" << endl;
        cin >> s;
        f.open(s.c_str());
    } while (!f.good());

    cout << "adatok beolvasasa..." << endl;

    int napok;
    if (!(f >> napok)) throw 1;
    charge.resize(napok);
    deliver.resize(napok);

    for (int i = 0; i<napok; i++) {
        if (!(f>>charge[i])) throw 1;
        if (!(f>>deliver[i])) throw 1;
    }

    string type, name;
    int battery;
    while (!f.eof()) {
        cout << " a ";
        if (f>>type && f>>name && f>>battery) {
            if (type=="Mac") {
                Mac r = Mac(name,battery);
                robots.push_back(&r);
            };
            if (type=="Eco") {
                Eco r = Eco(name,battery);
                robots.push_back(&r);
            };
            if (type=="Pro") {
                Pro r = Pro(name,battery);
                robots.push_back(&r);
            };
        };
    };
}

似乎问题发生在while循环中。如果我想从3行长文本中读取,我在屏幕上得到4个字母a-s(我在打读每一行之前打印一个程序)。

f.eof()不是我需要在这里使用的功能吗?

2 个答案:

答案 0 :(得分:1)

这是从文件中读取的最常见问题之一。检查f.eof()只会告诉您之前的读取是否在文件末尾。因此,在最后一次成功读取之后(你打印了第三个“a”),eof()返回false并且你的循环再次执行,输出一个额外的“a”。

相反,请使用提取行作为while循环的条件:

while (f>>type && f>>name && f>>battery) {
    if (type=="Mac") {
        Mac r = Mac(name,battery);
        robots.push_back(&r);
    }
    if (type=="Eco") {
        Eco r = Eco(name,battery);
        robots.push_back(&r);
    }
    if (type=="Pro") {
        Pro r = Pro(name,battery);
        robots.push_back(&r);
    }
}

这是有效的,因为只要你的一个提取命中文件的末尾,while条件将为false并且循环将不会执行。

如果您想在格式错误的线条后继续播放,我建议您改为使用std::getline

std::string line;
while (std::getline(f, line)) {
  std::stringstream ss(line);
  if (ss >> type && ss >> name && ss >> battery) {
    // ...
  }
}

使用此std::getline方法的原因是因为如果一行的格式正确,您就会遇到问题。您的方法可能会读入typename然后在battery上失败,并且循环的下一次迭代将从同一个地方开始。

您也会遇到一个问题,即您正在将指向具有自动存储持续时间的对象推送到某些向量中。当创建对象的块结束时,指针将指向无效对象。

答案 1 :(得分:0)

这是FAQ。在C / C ++中,只有在尝试读取过去结尾后才会触发文件结束条件。所以,你不能假设输入是feof()== false(因为你可能正好在文件的末尾,但还没有过去它)。在读取操作之后,您应该始终测试有效输入