Duplicate entry while reading from ifstream into vector

Discussion in 'C++' started by steve.cpp@gmail.com, Dec 28, 2008.

  1. Guest

    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::eek:fstream;

    #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
    , Dec 28, 2008
    #1
    1. Advertising

  2. alfps Guest

    On 28 Des, 03:42, 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
    alfps, Dec 28, 2008
    #2
    1. Advertising

  3. James Kanze Guest

    On Dec 28, 4:40 am, alfps <> wrote:
    > On 28 Des, 03:42, 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:
    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
    James Kanze, Dec 28, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Darrel
    Replies:
    5
    Views:
    814
    darrel
    Dec 6, 2004
  2. Row
    Replies:
    0
    Views:
    471
  3. Dr. Len
    Replies:
    4
    Views:
    1,167
    Alex Vinokur
    Jul 21, 2004
  4. Replies:
    8
    Views:
    1,898
    Csaba
    Feb 18, 2006
  5. omariqbalnaru
    Replies:
    3
    Views:
    444
    David Harmon
    Nov 23, 2006
Loading...

Share This Page