【问题标题】:Why using while(!input.eof()) loop twice not working? [duplicate]为什么使用 while(!input.eof()) 循环两次不起作用? [复制]
【发布时间】:2013-02-16 05:12:52
【问题描述】:

下面几行代码的目的是将输入文本文件中的每个单词(单词用换行符分隔)放到一个字符串向量中,然后将每个单词翻过来,看看这个翻过来的单词是不是包含在输入文件的单词列表中。

我相信我的二分搜索功能和 wordTurn 功能可以正常工作。 我对我的代码做了几个简单的测试,我发现使用 while(!myFile.eof()) 循环两次可能是我的代码不起作用的原因。通过不工作,我的意思是我将输出文件(“pairs.txt”)作为一个空文档(它应该是成对的单词列表)。

也就是说,当我在第二个 while(!myFile.eof()) 循环体中放入一些简单的打印代码时,它没有被打印出来,由此我得出结论,这个循环没有到达。这更有可能,因为它是在我注释掉第一个 while(!myFile.eof()) 循环时打印的。我最初将第一个 while 循环放在 else 主体中,但这没有任何区别。

你认为问题是什么? 我尝试将这两个循环体组合到第二个循环中,它在输出文件中产生了一些东西,但这不是这段代码应该做的,这在逻辑上是不正确的。

任何建议都将不胜感激。

int main(int argc, char* argv[]) {

    vector<string> words;
    ifstream myFile(argv[1]);
    ofstream outputFile("pairs.txt");
    string vocab;
    string s;
    int count;

    while(!myFile.eof()) {                //first while(!myFile.eof()) loop
        getline(myFile, s);
        words.push_back(s);
    }

    if(argc != 2) {
        cout << "Usage: provide the name of one input file after the dictlookupHN executable file." << endl;
        return (1);
    }
    else {
        if(!myFile.is_open()) {
            cerr << "Error: unable to open file " << argv[1] << endl;
            return (1);
        }
        else {
            while(!myFile.eof()) {      //second while(!myFile.eof()) loop
                getline(myFile, vocab);
                string turnedWord = wordTurn(vocab);
                if(binsearch(words, turnedWord) != "") {
                    outputFile << vocab << ":" << turnedWord << endl;
                    count++;
                }
            }
        }

    }
    myFile.close();
    outputFile.close();

    return 0;
}

【问题讨论】:

  • 这里有一篇关于使用 seekg 倒带打开文件的 SO 帖子:stackoverflow.com/questions/5750485/…
  • 它不会工作两次,因为它基本上从不工作。
  • 你的if(!myFile.is_open())不应该直接在你打开文件之后吗?你只需加载它,甚至不用担心参数的数量。好像你放错了一些代码。

标签: c++ iostream


【解决方案1】:

ifstream 类维护流数据的内部偏移量,跟踪它必须从哪里读取,以进行下一个操作。

当这个偏移量到达末尾时,它会停止第一个循环,(eof() 返回 false)。在再次读取之前,您需要将此内部位置重置回文件的开头。

你可以这样说:

myFile.clear(); // clear stream flags and error state
myFile.seekg(0, ios::beg); // reset read position

在第二个循环之前。

编辑:添加了对clear()的调用。

【讨论】:

    【解决方案2】:

    当您完成文件的第一次运行时,文件的查找指针位于文件末尾。如果要再次搜索文件,则需要在第二个 while 循环之前使用 myFile.seekg(0, ios::beg); 重置文件指针。像这样的:

            ...
            else {
                    myFile.seekg(0, ios::beg);
                    while(!myFile.eof()) {      //second while(!myFile.eof()) loop
            ...
    

    这应该可以解决问题。

    【讨论】:

      【解决方案3】:

      如果您想再次读取文件 [一旦您将整个文件读取到最后],您将需要重置错误/失败位,并从头开始。文件结束是一种永久状态,除非采取措施将其重置。

      所以,你需要myFile.clear();myFile.seekg(0, ios_base::beg);

      虽然我感觉在这种特殊情况下您实际上想打开一个不同的文件,但在这种情况下,我建议关闭当前文件并使用不同的变量 - 它们不是很贵,而且它使代码更清晰[特别是如果你称它为明智的,例如vocabFile 而不是 myFile]

      【讨论】:

        【解决方案4】:

        要再次从文件开头读取,请使用:

        myFile.seekg(0, ios::beg);
        

        但请注意,这不是从文件中读取的好方法:

        string vocab;
        while(!myFile.eof()) {
            getline(myFile, vocab);
            ...
        }
        

        它应该是这样的:

        string vocab;
        while(getline(myFile, vocab)) {
            if (vocab.empty())
                continue;               // empty line might be read
            ...
        }
        

        看看:Why does my input seem to process past the end of file?

        【讨论】:

          【解决方案5】:

          第一个循环到达文件末尾,并且在第二次读取之前您没有重置。您需要在第一个循环之后查找文件的开头:myFile.seekg (0, ios::beg); 将为您完成此操作。

          【讨论】:

            【解决方案6】:

            第一个循环到达EOF,即“读取标记”的位置,因此第二个EOF在第二个循环中被读取为第一个。

            很简单,尝试在循环之间关闭和打开文件。

            更好的办法是使用seekg 再次从顶部读取。

            【讨论】:

              【解决方案7】:

              感谢大家提出的所有这些好建议。 他们确实帮助我了解了 ifstream 和 eof 的工作原理。

              我的 TA 的建议是使用 for 循环而不是第二个 while(!myFile.eof()) 循环。我可能正在使用此选项,但当我必须使用两次 eof 时,您的回答会很有帮助。

              谢谢!

                                  while(!myFile.eof()) { 
                                          string s;
                                          getline(myFile, s);
                                          words.push_back(s);
                                  }
              
                                  for(int i=0; i<words.size(); i++) {
                                          //LOOP INV: 
                                          string vocab = words.at(i);
                                          string turnedWord = wordTurn(vocab);
                                          if(binsearch(words, turnedWord) == 1 && turnedWord.length() > 3) {
                                                  outputFile << vocab << ":" << turnedWord << endl;
                                                  count++;
                                          }
              

              【讨论】:

                猜你喜欢
                • 2022-12-12
                • 1970-01-01
                • 2011-04-21
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-12-16
                相关资源
                最近更新 更多