istringstream question

Okay so I have an assignment I'm working on where we have to have a program that reads in words from a text file, allows the user to input what word they want to search for, and have it output how many of that word there are in the file

Basically what's going wrong must be in the instr >> filetext; portion of the code. When I have it output the filetext string after each time it reads it in, for some reason it is reading in the last word of each line twice. Does anybody see why it would be doing this? I cannot seem to find it

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int _tmain(int argc, _TCHAR* argv[])
{
	ifstream inf;
	string s;
	string userword;
	string filetext;
	int counter = 0;
	inf.open("words.txt");
	cout << "What word do you want to find?";
	getline(cin, userword);
	while (!inf.eof()){
		getline(inf, s);
		istringstream instr(s);
		cout << s << endl;
		     while ( !instr.eof() ) {
			     instr >> filetext;
			     cout << filetext << endl;
			          if (filetext == userword) {
				     counter++;
			     }
		}
}
Weird, so it actually duplicates the last word of every line except of the last line... the word.txt reads:

The past tense is a grammatical tense
whose principal function is to place
an action or situation in past time.
In languages which have a past tense,
it thus provides a grammatical means of indicating
that the event being referred to took place in the past.
Examples of verbs in the past tense
include the English verbs sang, went and was.

so at the end of every line it goes
"...grammatical tense tense"
"...is to place place"
etc etc until the last line
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//while (!inf.eof()){
//getline(inf, s);
while( getline( inf, s) ) {

    istringstream instr(s);

         //while ( !instr.eof() ) {
             //instr >> filetext;
         while( instr >> filetext ) {

             // ...

         }
}
it's not duplicating the last word. Your loop is running off the end of the stream and you're not checking for that until an iteration later. Calling >> on the past-the-end stream does nothing and the word from the last successful iteration is still sitting in your variable.

Where did you learn to write this "while(! instr.eof())" code? It is wrong. Use while(instr >> filetext) or equivalent
Last edited on
Our professor... she has a PHD in comp science

What do you mean it is wrong?
C++ basics aren't usually required for comp. sci. research.
What would you use instead?
And why is this wrong? I don't understand, it seemed to work fine for most other things I've used it for
Isn't there a way to do this utilizing this method? Cause it seems as though I'm relatively close and as though the issue is just in the while(!instr.eof()) loop.

She did work mostly in data mining and algorithms I know.
Last edited on
> the issue is just in the while(!instr.eof()) loop.

Yes.

> And why is this wrong?

It checks for successful input before (instead of after) the attempted input.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <sstream>
#include <string>

int main()
{
    {
        std::istringstream stm( "one two three four bad " ) ;
        std::string word ;
        int n = 0 ;
        while( !stm.eof() ) // bad
        {
             stm >> word ;
             std::cout << ++n << ". " << word << '\n' ;
        }
    }

    std::cout << "----------------------\n" ;

    {
        std::istringstream stm( "one two three four good " ) ;
        std::string word ;
        int n = 0 ;
        while( stm >> word  ) // good
            std::cout << ++n << ". " << word << '\n' ;
    }
}

http://ideone.com/D6iEcl
JLBorges above already wrote how these loops would normally look, although if you know what functions are being called and why, you could shape the code in a few other ways.
Okay I think I'm getting what you're saying.... sorry I'm still quite new to all this
Changed from a music composition major to this so it's working parts of my brain that have been neglected haha x)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	while (!inf.eof()){
		getline(inf, s);
		istringstream instr(s);
		cout << s << endl;
		while ( !instr.eof() ) {
			instr >> filetext;
			cout << filetext << endl;

			     if (filetext == userword) {
				    counter++;
			}
		}
}



Could you please show me where exactly on my code is wrong? Idk why I still am not making the connection..
Please see comments.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    while (!inf.eof())                  // This is wrong because ...
    {
        getline(inf, s);                // did this getline succeed?
        istringstream instr(s);         // we don't know, but
        cout << s << endl;              // go ahead and use it anyway.
        
        while ( !instr.eof() )          // This is wrong too
        {
            instr >> filetext;          // did this input succeed?
            cout << filetext << endl;   // we don't know, but go ahead anyway

            if (filetext == userword) 
            {
                counter++;
            }
        }
    }


This is how it should look:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
    while (getline(inf, s))
    {
        istringstream instr(s);
        cout << s << endl;
        while (instr >> filetext) 
        {
            cout << filetext << endl;

            if (filetext == userword) 
            {
                counter++;
            }
        }
    }

In the second version, the body of the loop is executed only after a successful input operation.

Checking for eof() in the while loop is wrong for two reasons, first because it checks the outcome before doing the file access. (out of sequence). Second, it is wrong because there are several different error conditions which could occur, and eof() is just one of them.
Hmm so while (getline(inf, s)) essentially executes a getline command until complete and while(instr >> filetext) reads to filetext until complete (by complete meaning end of file)?

I've never used a while loop like this so it's new to me

Thanks again for the help, this is all great
Last edited on
Topic archived. No new replies allowed.