1

Why doesn't this code want to load all the values from a text file? It only loads the first object's items correctly but after that it starts going weird. Here is the code:

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;
class Location
{
public:
    Location()
    {
        locName = "No Name";
        locDesc = "No Description";
        locID = 0;
    }

    friend ostream& operator <<(ostream& outs, const Location & showMe)
    {
        // keeping output same as input...
        outs << showMe.locName << endl;
        outs << showMe.locDesc << endl;
        outs << showMe.locID << endl;

        return outs;
    }

    friend istream& operator >>(istream& ins, Location & inLoc)
    {
        getline(ins, inLoc.locName);
        getline(ins, inLoc.locDesc);
        ins >> inLoc.locID;

        return ins;
    }

private:
    string locName;
    string locDesc;
    int locID;
};

int main()
{
    ifstream inFile;

    inFile.open("loc_data.txt");
    if (inFile.fail())
        {
            cout << "\nCould not open the input file!";
            exit(1);
        }

    Location fileLoc[10];
    int i = 0;

    while (inFile.good())
        {
            inFile >> fileLoc[i];
            i++;
        }

    for (int j = 0; j < 10; j++)
        cout << fileLoc[j];

    return 0;
}

The input file is:

Town Hall
Main venue for functions
1
City Park
Outdoor venue
2
Train Station
Commuting point
3
Local Airport
Long distance travel
4

And the output is:

Town Hall
Main venue for functions
1

City Park
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0
No Name
No Description
0

I have a suspucion that getline is responsible for this but do not know enough to be sure, however I would really like to know why this is happening and not just a 'fix'.

1
  • Do you have the file as is ? How do you really know which field ends where ? Commented Sep 2, 2011 at 8:11

3 Answers 3

2

Your first problem is that this line doesn't extract the newline character:

ins >> inLoc.locID;

This means that the getline in for the second Location is extracting the rest of the line after 1 - i.e. an empty string - for the name.

This means that you are quickly getting out of sync with the lines that you want to read.

You should also consider changing your while loop, as it stands you check whether the stream is "good" before extracting a new location but you do not check whether the extraction was successful, you assume that the extraction works.

Sign up to request clarification or add additional context in comments.

2 Comments

Indeed, adding a char temp variable and then using ins.get(temp) after the ins >> inLoc.locID resolved it.
@georgelappies: Or you could use ins.get() or ins.ignore() to ignore one characer or ins.ignore(std::numeric_limits<std::streamsize>::max(), '\n') to ignore everything up to the next newline.
1

This works:

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <sstream>

using namespace std;
class Location
{
public:
    Location()
    {
        locName = "No Name";
        locDesc = "No Description";
        locID = 0;
    }

    friend ostream& operator <<(ostream& outs, const Location & showMe)
    {
        // keeping output same as input...
        outs << showMe.locName << endl;
        outs << showMe.locDesc << endl;
        outs << showMe.locID << endl;

        return outs;
    }

    friend istream& operator >>(istream& ins, Location & inLoc)
    {
        getline(ins, inLoc.locName);
        getline(ins, inLoc.locDesc);
        std::stringstream ss;
        std::string s;
        getline(ins, s);
        ss << s;
        ss >> inLoc.locID;

        return ins;
    }

private:
    string locName;
    string locDesc;
    int locID;
};

int main()
{
    ifstream inFile;

    inFile.open("loc_data.txt");
    if (inFile.fail())
        {
            cout << "\nCould not open the input file!";
            exit(1);
        }

    Location fileLoc[10];
    int i = 0;

    while (inFile.good())
        {
            inFile >> fileLoc[i];
            i++;
        }

    for (int j = 0; j < 10; j++)
        cout << fileLoc[j];

    return 0;
}

Comments

1

I believe the issue is with this line: ins >> inLoc.locID;

The problem is that when you read this value in with the >> operator it is leaving the next line charactor in the buffer, this then causes the read loop to end (as can be seen if you step through it).

To get around this i think you need to purposely empty this charactor from the buffer or use getline and convert the input (with validation i would hope!) to a number from a string.

Hope this helps,

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.