Mhm, so, the problem I'm having here is that, once the "while (!boatList.eof())" cycle reads the first line (EDIT: I meant, how should I put it, the first "segment"), it goes on infinite (?) loop reading the other one.

AX 777 Valtis 0 4 500 2007 5.5 -1 50.2 6
 FZ 138 0 4 500 2007 5.5 -1 50.2 6
 FZ 138 0 4 500 2007 5.5 -1 50.2 6
 FZ 138 0 4 500 2007 5.5 -1 50.2 6
 FZ 138 0 4 500 2007 5.5 -1 50.2 6

Notice how, when on infinite loop, only the regNumber changes (and only once), type being omitted completely, and everything else after that is identical to the first one. (Also, there is that strange space before regNumber value)

The code:

Boats loadBoatsFromFile(Boats boats)
{
    int     id;
    string  regNumber;
    string  type;
    int     maxPeople;
    int     maxWeight;
    int     yearMade;
    double  hourPrice;
    int     rentedByClient;
    double  moneyEarned;
    int     timesRented;

    ifstream boatList ("boats.txt");
    while (!boatList.eof())
    {
        getline (boatList, regNumber);
        getline (boatList, type);

        boatList >> id
                 >> maxPeople
                 >> maxWeight
                 >> yearMade
                 >> hourPrice
                 >> rentedByClient
                 >> moneyEarned
                 >> timesRented;

        cout		 << regNumber      << " "
			 << type           << " "
			 << id             << " "
			 << maxPeople      << " "
			 << maxWeight      << " "
			 << yearMade       << " "
			 << hourPrice      << " "
			 << rentedByClient << " "
			 << moneyEarned    << " "
			 << timesRented    << endl;

	if (!boatList.eof()) boats.push_back(createBoat(id, regNumber, type, maxPeople, maxWeight, yearMade, hourPrice, rentedByClient, moneyEarned, timesRented));
    }
    boatList.close();
    return boats;
}

File contents:

AX 777
Valtis
0 4 500 2007 5.5 -1 50.2 6
FZ 138
Baidare
1 2 230 2008 5 -1 20 4

I have another function doing the same thing without getline's, which works as it should, also, I've managed to get around this problem myself by adding another getline at the end of the cycle, but I still want to figure out as to what exactly is wrong here.
I take it, it doesn't jump to another line for some reason, and I'd like to know why as I can't figure it out myself. (=_=)" Thanks in advance. :)

Recommended Answers

All 3 Replies

The problem is that you're combining different types of inputs. getline() reads up to, extracts and discards, the newline character that exists at the end of a line of input. The extraction operator (>>) reads up to, and leaves, the newline character at the end of a line of input leaving the input stream "dirty", but salvageable. When you have this situation, you need to use istream::ignore() to "clean" the stream by getting rid of that dangling newline.

What is happening is the newline that the extraction operator leaves behind gets consumed by the getline (boatList, regNumber); line as valid input. Then, getline (boatList, type); reads what should be the regNumber. Then, boatList >> id tries to read what should be the type. Do you see how they're one (1) line out-of-synch?

This results in a string being read into a numeric dataType. Your stream has now transitioned from "dirty" to "corrupt". Because it's corrupt, it is completely useless to you and can do no further reading which is why your values no longer change. Once you get to this point, more drastic measures are required. This requires the use of ios::good() and ios::clear(), in conjunction with istream::ignore() to correct this situation.

To avoid this situation, I would suggest you use another string, perhaps called "stats" and use another getline. Then, convert stats to a stringstream and extract from the stringstream to your numeric values.

commented: Detailed and not too hard to understand comment on the problem +0

Ahh, so that's what gets eaten by that getline I placed at the end of the cycle. Thank you for a quick reply and explaining it so thoroughly. :)

I've tried implementing .good()/.clear(), but encountered some problems and so dropped the idea, at least for now. It would really be handy to be able to skip "corrupted" segment and jump to reading another one, but, without getting infinite loops, as it happened to me. :'D (I'll try to work this out some other time)

To avoid this situation, I would suggest you use another string, perhaps called "stats" and use another getline. Then, convert stats to a stringstream and extract from the stringstream to your numeric values.

I think I'm going to pass on it this time (still, your suggestion is appreciated nonetheless). Though, I'm curious, extract in what way? With ignore(' ')? Or is there a more fitting function for that?

>>Though, I'm curious, extract in what way? With ignore(' ')? Or is there a more fitting function for that?
A stringstream is another type of I/O stream that works almost just like a file stream except it uses an std::string as a temporary "buffer" in memory instead of a physical file on a disk. It uses the same syntax/operators as other streams, you just need a couple extra steps to set up the string. The link I previously gave you explains it.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.