Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Duplicate entry while reading from ifstream into vector

3 views
Skip to first unread message

stev...@gmail.com

unread,
Dec 27, 2008, 9:42:21 PM12/27/08
to
Hi,
I'm new at C++, I'm using Stroustrup's book to learn and trying to
finish an exercise on page 505 (#3) and it works except that I am
getting an duplicate string read into a vector and can't figure out
the reason. This is not a homework assignment, I want to learn C++ as
a skill:

#include <fstream>
using std::fstream;
using std::ifstream;
using std::ofstream;

#include <iostream>
using std::cout;
using std::endl;
using std::getline;
using std::ios;

#include <string>
using std::string;

#include <vector>
using std::vector;

int main( int argc, char *argv[] )
{
if(argc != 2) {
cout << "Incorrect number of arguments, should be two,
turkey." << endl;
exit(1);
}

ifstream readFile( argv[1], ios::in );
cout << "argv[1] is " << argv[1] << endl << endl;
if( !readFile) {
cout << "Can't open " << argv[1] << ", exiting." <<
endl;
return 0;
}
else
cout << argv[1] << " opened for reading." << endl <<
endl;

string temp;
vector< string > lw;
//while( readFile && !readFile.eof() ) {
while( !readFile.fail() ) {
readFile >> temp;
cout << "temp is: " << temp << endl;
lw.push_back(temp);
}
readFile.close();
cout << endl;
cout << "Here's the vector." << endl;

for( vector<string>::iterator p = lw.begin(); p != lw.end(); +
+p)
cout << *p << endl;

return 0;
}

When I execute the program, no matter which text file I use, the last
word in the file is duplicated (there's not a duplicated string at the
end of the file), such as if the last word is "dawn," it appears twice
when I output the strings in the while loop and also with the
iterator.

I've tried changing the while loop to use different tests to determine
the end of the file but I get a duplicate line each time.

When the end of file is reached, the while loop should terminate and
not call push_back() again but for some reason, it calls it twice.

I've tried to use an istringstream as well but always end up with the
last word in the file duplicated.

I apologize ahead of time if this is a basic issue but I can't
eliminate the duplicate entry.

Steve

alfps

unread,
Dec 27, 2008, 10:40:36 PM12/27/08
to
On 28 Des, 03:42, steve....@gmail.com wrote:
>
>         string temp;
>         vector< string > lw;
>         //while( readFile && !readFile.eof() ) {
>         while( !readFile.fail() ) {
>                 readFile >> temp;
>                 cout << "temp is: " << temp << endl;
>                 lw.push_back(temp);
>         }

Consider what happens when the input operation (the >>) fails. 'temp'
is not changed. The code proceeds, using the old value, to output
"temp is:" and then to add that old value at the end of the vector.

The idiomatic way to do this relies on implicit conversion to bool:

while( readFile >> temp ) ...

I think that if I were to use iostreams I'd write it more explicitly
(I suspect many people using the idiomatic way don't understand what
it means!), e.g.

for( ;; )
{
readFile >> temp;
if( readFile.fail() ) { break; }
...
}

Then the ugliness of the code reflects the ugliness of the
iostream. :-)


Cheers & hth.,

- Alf

James Kanze

unread,
Dec 28, 2008, 8:33:54 AM12/28/08
to
On Dec 28, 4:40 am, alfps <alf.p.steinb...@gmail.com> wrote:
> On 28 Des, 03:42, steve....@gmail.com wrote:
> > string temp;
> > vector< string > lw;
> > //while( readFile && !readFile.eof() ) {
> > while( !readFile.fail() ) {
> > readFile >> temp;
> > cout << "temp is: " << temp << endl;
> > lw.push_back(temp);
> > }

> Consider what happens when the input operation (the >>) fails.
> 'temp' is not changed. The code proceeds, using the old value,
> to output "temp is:" and then to add that old value at the end
> of the vector.

> The idiomatic way to do this relies on implicit conversion to
> bool:

> while( readFile >> temp ) ...

> I think that if I were to use iostreams I'd write it more
> explicitly (I suspect many people using the idiomatic way
> don't understand what it means!),

You might be right. One of the advantages of the idiomatic way
is that it works, even if you don't understand it.

Of course, some people who do understand it still use it,
precisely because it is the idiomatic way.

> e.g.

> for( ;; )
> {
> readFile >> temp;
> if( readFile.fail() ) { break; }
> ...
> }

That's even worse. I do sort of like:

for ( readFile >> temp ; readFile ; readFile >> temp ) ...

But in the end, the advantage of being idiomatic outweighs the
other advantages.

> Then the ugliness of the code reflects the ugliness of the
> iostream. :-)

The problem is that nothing better has been proposed. (I/O is a
difficult problem, because it involves side effects which may
fail.)

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

0 new messages