1

On the following lines of code is intended to put every words in the input text file(words are separated by new lines) to a vector of strings, then to turn each word inside out, and to see if this turned word is contained in the list of words in the input file.

I believe my binary search function and wordTurn function works fine. I did several simple tests on my code, and I found out using while(!myFile.eof()) loop twice might be the cause for my code not working. By not working I mean I get the output file("pairs.txt") as an empty document(it is supposed to be a list of pairs of words).

That is, when I put some simple print code in the second while(!myFile.eof()) loop body, it did not get printed out, from which I concluded this loop is not reached. This is more likely, since it printed when I commented out the first while(!myFile.eof()) loop. I originally placed the first while loop at the else body, but this made no difference.

What do you think is the problem? I tried combining those two loop body into the second loop, and it produces something in the output file, but this was not what this code was supposed to do, and this was logically not correct.

Any words of advice would be greatly appreciated.

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;
}
Paul R
  • 195,989
  • 32
  • 353
  • 519
Eric Na
  • 2,381
  • 5
  • 18
  • 49
  • there is a SO post about rewinding an open file using seekg here: http://stackoverflow.com/questions/5750485/ifstream-equivalent-of-file-s-rewind-method – David Hope Mar 01 '13 at 16:27
  • 1
    It doesn't work twice because it basically *never works.* –  Mar 01 '13 at 16:29
  • Shouldn't your `if(!myFile.is_open())` be directly after you open the file? And you just load it without even worrying about the number of arguments. Seems like you misplaced some code. – GManNickG Mar 01 '13 at 16:41

7 Answers7

3

The ifstream class maintains an internal offset into the stream data, keeping track where it has to read from, for the next operation.

When this offset reaches the end, it stops the first loop, (eof() returns false). You need to reset this internal position back to the beginning of the file, before reading again.

You do that by saying:

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

before the second loop.

Edit: Added call to clear().

utnapistim
  • 24,817
  • 3
  • 41
  • 76
2

What is happening is that the seek pointer for the file is at the end of the file when you complete the first run through the file. If you want to seek through the file again, you will need to reset the file pointer using myFile.seekg(0, ios::beg); before the second while loop. Something like this:

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

That should fix the problem.

2

If you want to read the file again [once you have read the entire file to the end] you will need to reset the bad/fail bits, and also seek to the start. End of file is a permanent state unless something is done to reset it.

So, you need myFile.clear(); and myFile.seekg(0, ios_base::beg);

Although I have a feeling you actually want to open a different file in this particular case, in which case, I would recommend closing the current one, and using a different variable - they aren't very expensive, and it makes the code clearer [particularly if you call it something sensible, e.g. vocabFile instead of myFile]

Mats Petersson
  • 119,687
  • 13
  • 121
  • 204
2

To read from the beginning of your file again, use:

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

But note, that this is not a good way of reading from a file:

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

This is how it should look like:

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

Have a look at: Why does my input seem to process past the end of file?

LihO
  • 37,789
  • 9
  • 89
  • 156
0

the first loop reached EOF, thats the position of "read marker", so the second EOF is readed as first in the second loop.

As simple, try to close and open file between loop.

Better idea is to use seekg to read from top again.

l0v3
  • 827
  • 6
  • 21
0

The first loop reaches the end of file, and you're not resetting before the second read. You need to seek to the start of the file after the first loop: myFile.seekg (0, ios::beg); will do this for you.

Jack Aidley
  • 17,045
  • 6
  • 35
  • 66
0

Thank you everyone for all of these words of good advice. They really helped me understand how the ifstream and eof work.

My TA's advice was to use for loop instead of the second while(!myFile.eof()) loop. I might be using this option, but your answers will be of great help when I have to use eof twice.

Thank you!

                    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++;
                            }
Eric Na
  • 2,381
  • 5
  • 18
  • 49