2013-03-01 248 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++; 
          }