为什么使用while(!input.eof())循环两次不工作

Why using while(!input.eof()) loop twice not working?

本文关键字:循环 两次 工作 eof while input 为什么      更新时间:2023-10-16

下面的代码行旨在将输入文本文件中的每个单词(单词由新行分隔)放入字符串向量中,然后将每个单词从内到外翻过来,并查看这个翻过来的单词是否包含在输入文件中的单词列表中。

我相信我的二进制搜索函数和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;
}

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

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

你可以这样做:

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

在第二个循环之前。

编辑:增加呼叫clear()

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

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

这应该能解决问题。

如果您想要再次读取文件[一旦您读取了整个文件的末尾],您将需要重置坏/失败位,并查找到开始。文件结束是一个永久状态,除非做了一些事情来重置它。

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

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

如果要重新从文件开头读取,请使用:

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
    ...
}

看一下:为什么我的输入似乎超过了文件的末尾?

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

第一个循环到达EOF,这是"read marker"的位置,因此第二个EOF在第二个循环中被读取为第一个。

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

谢谢大家的忠告。他们真的帮助我理解了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++;
                            }