C 从文件功能读取循环时无法退出

C++ reading from file function failing to exit while cycle

本文关键字:退出 循环 读取 文件 功能      更新时间:2023-10-16

可能的重复:
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);
            };
        };
    };
}

似乎问题出现在当时的循环中。如果我想从3行长文本中阅读,我会在屏幕上收到4个字母A-S(我在阅读每一行之前就打印了一个。

)。

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

这是从文件读取的最常见问题之一。检查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条件将是错误的,并且循环不会执行。

如果您想在格式不佳的线路后继续,我建议您使用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上失败,并且循环的下一个迭代将从同一位置开始。

您还将对将指针推向具有自动存储持续时间的对象的事实有问题。当创建对象结束的块时,指针将指向无效的对象。

这是一个常见问题。在C/C 中,只有在您尝试读取过去末端之后才能触发文件末端条件。因此,您不能从feof()== false中假设输入可用(因为您可以正好处于文件的末尾,但是尚未过去)。您应始终测试有效输入读取操作。