illia illia - 2 months ago 8
C++ Question

Reading unknown number of strings followed by doubles into a vector

So, I want need to open a file which contains football team names followed by other data. Example would be:

Leicester City 38 12 13
West Ham 38 14 15
Schalke04 40 16 17


Then, I read that data into a vector of object type(I have "Team.h"). Problem is, some teams contain only 1 string as a name, others have 2 or more, some even have numbers in the name(i.e.Schalke04). So, how do I open a file and read info in vector correctly?

#ifndef TEAM_H
#define TEAM_H

#include <string>

using namespace std;

class Team
{
public:
Team();
Team(string, double, double, double);
string getName();
double getn1();
double getn2();
double getn3();

private:
string name;
double n1;
double n2;
double n3;

};
#endif


Team.cpp

#include "Team.h"

Team::Team()
{

}

Team::Team(string n, double N1, double N2, double N3)
{
name = n;
n1 = N1;
n2 = n2;
n3 = N3;
}

string Team::getName()
{
return name;
}

double Team::getn1()
{
return n1;
}

double Team::getn2()
{
return n2;
}

double Team::getn3()
{
return n3;
}


Usually reading in vector would look like this

inFile >> name >> n1 >> n2 >> n3;
Team newTeam(name, n1, n2, n3);
teams.push_back(newTeam) //vector<Team>teams declared earlier


UPD:My search method(not good)

string homeTeam;
Team ht;
for (Team team: newTeams)
{
if(team.getName() == homeTeam)
{
ht = team;
}
}

Answer

If you can change Team.h and Team.cpp consider adding

friend istream &operator>>(istream &input, Team &t);
friend ostream &operator<<(ostream &output, Team &t);

for reading data from input stream to object of Team class and output whole object to the output stream.

I mean the following:

Team.h

#ifndef TEAM_H
#define TEAM_H

#include <string>

using namespace std;

class Team
{
public:
    Team();
    Team(string, double, double, double);
    string getName();
    double getn1();
    double getn2();
    double getn3();
    friend istream &operator>>(istream &input, Team &t);
    friend ostream &operator<<(ostream &output, Team &t);
private:
    string name;
    double n1;
    double n2;
    double n3;

};
#endif

Team.cpp (only new lines based on answer to related question)

istream &operator>>(istream &input, Team &t)
{
    while (!input.eof() && input.good())
    {
        string s;
        string name;
        getline(input, s);
        if (input.bad() || s.length() == 0)
        {
            input.setstate(ios::badbit); // for case of empty line
            return input;
        }
        istringstream ss(s);
        string str;
        bool notNumber;
        do{
            ss >> t.n1;
            notNumber = ss.fail();
            if (notNumber)
            {
                ss.clear();
                ss >> str;
                //if(name.length() > 0) name.append(" "); // uncomment this if you want spaces in name
                name.append(str);
            }
        } while (notNumber && !ss.eof());
        if (name.length() == 0)
            continue;
        t.name = name;
        if (notNumber)
        {
            input.setstate(ios::badbit);
            return input;
        }
        ss >> t.n2;
        ss >> t.n3;
        if (ss.fail())
        {
            input.setstate(ios::badbit);
            return input;
        }
        return input;
    }
    return input;
}

ostream &operator<<(ostream &output, Team &t)
{
    output << t.getName() << " " << t.getn1() << " " << t.getn2() << " " << t.getn3();
    return output;
}

And usage will be like that:

// reading data from file
vector<Team> dataTable;
while (!inFile.eof() && !inFile.bad())
{
    Team tmp;
    inFile >> tmp;
    if (!inFile.fail())
        dataTable.push_back(tmp);
    else
        inFile.clear();
}
// print data stored in table
for (vector<Team>::iterator i = dataTable.begin(); i != dataTable.end(); i++)
{
    cout << *i << endl;
}
Comments