1

I'm working on another school project, in part of which I need to take the data from a .txt file and convert it to a mixed type vector... that contains two integers and a string. I've tried various ways of doing it, and I have it down to where the .txt file is inputted, and hopefully sent to vectors. My difficulty comes in when I try to do stuff with the vectors. My code segment is as follows (I'll explain what things are for with comments):

bool ReadPeopleFromFile(int argc, char* argv[], vector<Person> &people) {
    Person tmpPrsn;
    int tmpAge;
    string tmpGender;
    int tmpAnualIncome;
    ifstream PeopleFile("dev_people.txt"); // Try to open file
    if (!PeopleFile.is_open()) {
        cout << "Could not open file.\n";
        return true; // indicates error
    }

    cout << "Starting" << endl;
    while (!PeopleFile.eof()) {
        PeopleFile >> tmpAge;
        PeopleFile >> tmpGender;
        PeopleFile >> tmpAnualIncome;
        tmpPrsn.SetData(tmpAge, tmpGender, tmpAnualIncome);
        tmpPrsn.Print();
        people.push_back(tmpPrsn);                                                                  //  Need to look at this!!!
    }
    PeopleFile.close();
    cout << "Finished reading file." << endl;
    return false;
}
//I have a function that gets the user input... I took it out for this post.    
vector<Person> ptntlCstmrs;

// Return people within the given age range.
vector<Person> GetPeopleWithQualifyingCharacteristics(vector<Person> ppl, int AgelowerRange, int AgeupperRange, string DesiredGender, int YIlowerRange, int YIupperRange) {
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned int k = 0;

    vector<Person> pplInRange;
    int age = 0;
    string gender = "";
    int yearlyIncome = 0;
    for (i = 0; i < ppl.size(); ++i) {
        for (j = 0; j < ppl.size(); ++j) {
            for (k = 0; k < ppl.size(); ++k) {
                age = ppl.at(i).GetAge();
                gender = ppl.at(j).GetGender();
                yearlyIncome = ppl.at(k).GetYearlyIncome();
                if ((age >= AgelowerRange) && (age <= AgeupperRange) && (gender == DesiredGender || gender == "Any") && (yearlyIncome >= YIlowerRange) && (yearlyIncome <= YIupperRange)) {
                    ptntlCstmrs.push_back(ppl.at(i));
                }
            }
        } // I know this section is messed up... I can't figure out how to get this part to work. What I'm trying to do is take the input, and filter it based on the user-inputted criteria. Nothing that I have done has worked.
    }
    return pplInRange;
}
int main(int argc, char* argv[]) {
    vector<Person> ptntlCstmrs;
    bool hadError = false;
    int ageLowerRange = 0;
    int ageUpperRange = 0;
    string desiredGender = "";
    int yearlyIncomeLowerRange = 0;
    int yearlyIncomeUpperRange = 0;

    hadError = ReadPeopleFromFile(argc, argv, ptntlCstmrs);
    if (hadError) {
        return 1; // indicates error
    }
    GetUserInput(ageLowerRange, ageUpperRange, desiredGender, yearlyIncomeLowerRange, yearlyIncomeUpperRange);
    ptntlCstmrs = GetPeopleWithQualifyingCharacteristics(ptntlCstmrs, ageLowerRange, ageUpperRange, desiredGender, yearlyIncomeLowerRange, yearlyIncomeUpperRange);
    cout << "\nNumber of potential customers = " << ptntlCstmrs.size() << endl;


}

I included a bunch of this stuff just in case some of my references are off, but I don't think so. It also tells you what I'm working with. I would like help figuring out how to get the criteria to actually sort the vectors, and then print out how many of those vectors are going to work with the user inputted data. Thanks in advance!

Danny
  • 101
  • 10
  • Maybe not your problem, but you should read this: http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – Fantastic Mr Fox Nov 19 '15 at 01:31
  • 2
    I don't understand your usage of triple-nested loops to get the criteria. You're getting person `i`, person `j`, and person `k`'s information. Aren't you supposed to be getting person `i` criteria and see if it fits the criteria? In other words, a single loop on `i`? – PaulMcKenzie Nov 19 '15 at 01:33
  • @PaulMcKenzie That could be... I've tried to structure it that way, but it has failed every time. Can you show me how that would be structured properly? – Danny Nov 19 '15 at 01:38
  • 1
    Just write a single loop and use index `i`. It is simpler than what you attempted to do. – PaulMcKenzie Nov 19 '15 at 01:41
  • Okay, I got that. And my stuff still isn't working. It is indeed simpler, and thanks for pointing that out! (kinda stupid on my part) Any other ideas? – Danny Nov 19 '15 at 02:03
  • @PaulMcKenzie Turns out, you are on the right track. I have everything figured out except the gender evaluation. Here is what it is now: ifstream PeopleFile("dev_people.txt"); while (PeopleFile >> age >> gender >> yearlyIncome); vector pplInRange; for (i = 0; i < ppl.size(); ++i) { age = ppl.at(i).GetAge(); if ((age >= Agelow) && (age <= Ageup) && (DesGen == "Male" || DesGen == "Female" || DesGen == "Any") && (yearlyIncome >= YIlow) && (yearlyIncome <= YIup)) { pplInRange.push_back(ppl.at(i)); } cut the definitions out... Any thoughts on how to get this to work? – Danny Nov 19 '15 at 02:36
  • Got it figured. Thanks for the help! I needed to set my find gender and yearly income the same way I did the get age... whoops. – Danny Nov 19 '15 at 02:50

2 Answers2

1

The credit really goes to @PaulMcKenzie . The problem with the above code is in the following section:

Return people within the given age range.
vector<Person> GetPeopleWithQualifyingCharacteristics(vector<Person> ppl, int AgelowerRange, int AgeupperRange, string DesiredGender, int YIlowerRange, int YIupperRange) {
unsigned int i = 0;
unsigned int j = 0;
unsigned int k = 0;

vector<Person> pplInRange;
int age = 0;
string gender = "";
int yearlyIncome = 0;
for (i = 0; i < ppl.size(); ++i) {
    for (j = 0; j < ppl.size(); ++j) {
        for (k = 0; k < ppl.size(); ++k) {
            age = ppl.at(i).GetAge();
            gender = ppl.at(j).GetGender();
            yearlyIncome = ppl.at(k).GetYearlyIncome();
            if ((age >= AgelowerRange) && (age <= AgeupperRange) && (gender == DesiredGender || gender == "Any") && (yearlyIncome >= YIlowerRange) && (yearlyIncome <= YIupperRange)) {
                ptntlCstmrs.push_back(ppl.at(i));
            }
        }
    } // I know this section is messed up... I can't figure out how to get this part to work. What I'm trying to do is take the input, and filter it based on the user-inputted criteria. Nothing that I have done has worked.
}
return pplInRange;

which needs to be changed to the following:

vector<Person> GetPeopleWithQualifyingCharacteristics(vector<Person> ppl, int Agelow, int Ageup, string DesGen, int YIlow, int YIup) {
    unsigned int i = 0;
    int age = 0;
    string gender = "";
    int yearlyIncome = 0;
    ifstream PeopleFile("dev_people.txt");
    while (PeopleFile >> age >> gender >> yearlyIncome);
    vector<Person> pplInRange;

    for (i = 0; i < ppl.size(); ++i) {
        age = ppl.at(i).GetAge();
        gender = ppl.at(i).GetGender();
        yearlyIncome = ppl.at(i).GetYearlyIncome();
        if ((age >= Agelow) && (age <= Ageup) && (DesGen == gender || DesGen == "Any") && (yearlyIncome >= YIlow) && (yearlyIncome <= YIup)) {
            pplInRange.push_back(ppl.at(i));
        }
    }

    return pplInRange;
}

Now it works fine. Thanks Paul!

Danny
  • 101
  • 10
0

My initial thoughts are that you aren't collecting user input correctly. You send your variables that determine whether or not a Person object is a potential customer off into another function.

By default C++ passes parameters by value -- meaning that when a parameter is passed into a function, a copy of said parameter is made and used throughout that function. When the function comes to a close, the edited parameter is then disposed of and all changes / edits are lost. If you want to grab user input from another method, and have said input saved, make sure to pass your parameters by reference.

Passing by reference essentially tells the machine where that specific parameter is located in memory and allows the program to directly access that piece of memory as opposed to making a copy of the parameter when executing your function. This in turn makes any changes made to parameters permanent!

Hope this helps!

Pacopenguin
  • 194
  • 1
  • 9
  • All you would have to do to pass by reference is in the function header place a '&' before all of your parameter names. As an example: void foo(int &num1, int &num2, int &num3){ ...} By placing the '&' in front of the parameter names, you are signifying that you are passing this parameter by reference. Don't forget to update any function prototypes! – Pacopenguin Nov 19 '15 at 02:38