2013-03-01 201 views
1

以下代码行旨在将输入文本文件中的每个单词(用新行分隔的单词)放入一个字符串矢量中,然后将每个单词从里面翻出来,并查看是否包含该单词在输入文件中的单词列表中。为什么使用while(!input.eof())循环两次不起作用?

我相信我的二进制搜索功能和wordTurn功能正常工作。 我对我的代码做了几个简单的测试,并且发现使用while(!myFile.eof())循环两次可能导致我的代码无法正常工作。通过不工作,我的意思是我得到输出文件(“pairs.txt”)作为一个空文件(它应该是一对单词列表)。当我在第二个while(!myFile.eof())循环体中放置一些简单的打印代码时,它没有打印出来,从中我得出这个循环没有达到。这更有可能,因为它在我第一次注释掉(!myFile.eof())循环时打印出来。我最初把第一个while循环放在else的body处,但这没有什么区别。

您认为是什么问题? 我尝试将这两个循环体合并到第二个循环中,并且它在输出文件中生成了一些内容,但这不是代码应该执行的操作,而且这在逻辑上不正确。

任何建议的话将不胜感激。

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; 
} 
+0

有一个SO张贴了解使用seekg倒带打开的文件:http://stackoverflow.com/questions/5750485/ifstream-equivalent-of-file-s-rewind-method – 2013-03-01 16:27:22

+1

它不工作两次,因为它基本上*从来没有工作。* – 2013-03-01 16:29:25

+0

不应该你打开文件后,你的'if(!myFile.is_open())'?你只需加载它,而不必担心参数的数量。好像你错放了一些代码。 – GManNickG 2013-03-01 16:41:11

回答

3

ifstream类在流数据中维护一个内部偏移量,保持跟踪它必须读取的位置,以用于下一个操作。

当这个偏移达到结束时,它停止第一个循环,(eof()返回false)。在重新阅读之前,您需要将此内部位置重置回文件的开头。

你做到这一点的话说:

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

第二循环之前。

编辑:添加致电clear()

0

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

简单来说,尝试关闭并打开循环之间的文件。

更好的主意是使用seekg再次从顶部读取。

0

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

2

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

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

这应该解决问题。

2

如果你想再次读取文件[一旦你已经读完整个文件],你将需要重置坏/失败位,并寻求开始。文件结尾是一个永久状态,除非重做它。

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

虽然我有一种感觉你真的想打开这个特定的情况下,不同的文件,在这种情况下,我会建议关闭当前一个,并使用不同的变量 - 它们不是很昂贵,它使代码更清晰[特别是如果你称之为明智的,例如vocabFile代替myFile]

2

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

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?

0

谢谢大家对这些好建议的话。 他们真的帮助我理解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++; 
          } 
相关问题