下面的代码行旨在将输入文本文件中的每个单词(单词由新行分隔)放入字符串向量中,然后将每个单词从内到外翻过来,并查看这个翻过来的单词是否包含在输入文件中的单词列表中。
我相信我的二进制搜索函数和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++;
}