Search code examples
c++ifstream

C++ Creating an object from text file


First let me start by saying thank you to the people who post on here often, I have gained a ton of knowledge searching this site the past few years.

Okay, this question has been asked before but I have a slight twist which I can not get working.

Here is my structure.

struct person
{
    string Sex;
    string Name;
    string Match;
    int phoneNumber;
    int numInterests;
    vector<string> interests;
};

The assignment is designed as a "Dating Program" which matches people of opposite sex with similar interests.

Here is an example text file following this format:

"Sex" "Name" "Phone Number" "Number of Interests" "List of interests" "Match (if a match is found)"

M Tyler 1234567890 3 soccer football tv Jess
F Lyns 1234567890 3 hockey sex movies
F Jess 1234567890 3 soccer football tv Tyler
M Taylor 1234567890 3 hockey sex movies

In that example file, there is a match for Jess and Tyler. Here is my function thus far...

void LoadClients(std::ifstream &file,vector<person>& peps)
{
    string sex,name,interests,line, match;
    double phone,ni;
    person p;
    for(int i=0;i<maxPeople("Clients.mf"); i++){
        file>>sex>>name>>phone>>ni;
        p.Sex = sex;
        p.Name = name;
        p.phoneNumber = phone;
        p.numInterests = ni;
        for (int i=0; i<ni; i++){
            file >> line;
            p.interests.push_back(line);
        }
        file >> match;
        p.Match = match;
        peps.push_back(p);

       // person p;
        //istringstream iss( line );
    }

};

Function compiles but does not read correctly at all. Here's the rest of my work, in case you want to see it...

int maxPeople(const char* file)///Just returns the number of lines in the file
{
    ifstream inFile(file);
    int c = count(istreambuf_iterator<char>(inFile),
            istreambuf_iterator<char>(), '\n');
    return c;
}
int main()
{
    int numberOfClients=maxPeople("Clients.mf");
    ifstream file("Clients.mf");

    vector<person> peps;
    LoadClients(file,peps);

    return 0;
}

My function LoadClients was modeled after an elegant answer I found here: Reading a string and integers

All I am asking for is how to get this function to create a vector or array of people from the text file.

The final program will have additional functions "NewClient", "UnMatch", "PrintMatched", and "PrintSingles" but I think I can handle these. Any and all tips are HIGHLY welcomed :)

Thanks for reading!

EDIT1: Using this format.

void LoadClients(std::ifstream &file,vector<person>& peps)  
{  
    person p;  
    string line;  
    while( getline( file, line ) )  
    {  
        istringstream iss( line );  
        iss >> p.Sex >> p.Name >> p.phoneNumber >> p.numInterests;  
        for(int i=0;i<p.numInterests;i++){  
            string interest;  
            iss >> interest;  
            p.interests.push_back(interest);  
        }  

    }  
}; 

I decided to skip the "match" for now. I am getting a segmentation error when I access the objects from main.

ifstream file("Clients.mf");

vector<person> peps;
LoadClients(file,peps);
for(int i=0; i<numberOfClients;i++){
    cout << peps[0].Name;
}

Solution

  • BTW, it's not a good idea for sex to be a string, unless you'ld like your program to handle aliens... And you may have issues with your int phoneNumbers. And numInterests is redundant if you have interests.size(). So you may do...

    struct Person {
        enum class Gender {
            Unknown,
            Male,
            Female,
        };
    
        Gender gender;
        std::string name;
        std::string match;
        std::string phoneNumber;
        std::vector<std::string> interests;
    };
    

    Now, to the problem. The function should look like (no checking and C++11!)...

    static Person::Gender readGender(std::ifstream &input) {
        char ch;
        input >> ch;
        switch(ch) {
            case 'M':
                return Person::Gender::Male;
    
            case 'F':
                return Person::Gender::Female;
    
            default:
                return Person::Gender::Unknown;
        }
    }
    
    void LoadClients(std::ifstream &file, std::vector<person> &out) {
        for(int i = 0; i < maxPeople("Clients.mf"); i++) {
            Person p;
            unsigned numInterests;
    
            p.gender = readGender(file);
            file >> p.name;
            file >> p.phoneNumber;
            file >> numInterests;
            for(unsigned i = 0; i < numInterests; i++){
                std::string interest;
                file >> interest;
    
                p.interests.push_back(interest);
            }
    
            file >> p.match;
            out.push_back(p);
        }
    }
    

    Edit: You should have a means for the program to differentiate whether there is a match or not, otherwise undefined frustation will seek you!

    Edit: Invalidated previous comment due to comments from the OP.

    Edit: Fixed some pitfalls according to comments.