Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

This is a tough one. Could really use some quality help. Most of the text in her

ID: 3576040 • Letter: T

Question

This is a tough one. Could really use some quality help. Most of the text in here is description of what the program should look like. Thanks in advance.

Write a C++ program named ftree that builds a family tree based on simple descriptions of relationships between people.

Your program will read the relationship specification in from cin and ultimately print out the information on cout using a specific format. The input format uses a series of keyword and value pairs on each line to describe how a person is related to other people:

PERSON: This specifies a person by name. All following keyword/value pairs are applied to this person, until another PERSON line is encountered.

SEX: Must be either "M" to mean male or "F" to mean female.

FATHER: This specifies the father of the current person. It implies that the father is a male. A person can only have one father.

MOTHER: This specifies the mother of the current person. It implies that the mother is a female. A person can only have one mother.

FATHER_OF: This specifies that the current person is the father of the given person. It implies that the current person is a male. A person may have any number of children.

MOTHER_OF: This specifies that the current person is the mother of the given person. It implies that the current person is a female. A person may have any number of children.

Note that names do not contain spaces, so every name is a single string. For example names such as "Bob" or "Frank" are ok, but not "Billy Bob" or "James Clerk Maxwell".

Use the example below

PERSON Bob

FATHER_OF Frank

FATHER_OF Lester

FATHER_OF Diana

PERSON Nancy

MOTHER_OF Frank

MOTHER_OF Lester

MOTHER_OF Diana

PERSON Diana

SEX F

PERSON Frank

SEX M

PERSON Lester

SEX M

This example defines five people. Bob and Nancy are the Father and Mother, respectively, of Diana, Frank, and Lester. Bob, Frank, and Lester are males, and Nancy and Diana are females.

Your ftree program must read this data in and build the necessary data structures to track all of the information about each person. After all information has been read in, ftree should print out the data for each person using the following format:

A line showing the person's name.

The word Sex: followed by the person's sex, which is printed as Male, Female, or unknown.

The word Father: followed by the person's father's name, or unknown if they don't have a father.

The word Mother: followed by the person's mother's name, or unknown if they don't have a mother.

The word Children: followed by a space separated list of all children of the person, or none if they have no children.

A blank line before the next person's entry.

The output order should be alphabetic based on the person's name. Here is an example:

Bob

Sex:     Male

Father:   unknown

Mother:   unknown

Children: Frank Lester Diana

Diana

Sex:     Female

Father:   Bob

Mother:   Nancy

Children: none

Frank

Sex:     Male

Father:   Bob

Mother:   Nancy

Children: none

Lester

Sex:     Male

Father:   Bob

Mother:   Nancy

Children: none

Nancy

Sex:     Female

Father:   unknown

Mother:   unknown

Children: Frank Lester Diana

As you read through the input, you must do error checking to look for impossible relationships. Moreover, you must be sure to include all explicit and implicit information and relationships. For example, if A is said to be B's father, then that means that A is male, even if A doesn't have a SEX entry. If A is later said to be C's mother, then that is an error and the offending line should be ignored. Finally, a person may not have their own PERSON entry in the input, but if the existence of the person is implied in another person's entry you should create the person automatically. For example, consider this input:

PERSON Fred

SEX M

FATHER Sam

This input defines two people: Fred and Sam. Both Fred and Sam are males (Fred explicitly so, Sam because he is Fred's father). Sam is Fred's father, and Fred is one of Sam's children.

The most important thing about ftree is to deal with this inference in robust fashion. Always include as much information as possible based on the given input, and always check every value before updating anything to be sure it does not conflict with previous information. Specifically, you should check all of this information as you read in the data:

A person cannot have two fathers or two mothers.

A father cannot be female, and a mother cannot be male.

A person's sex cannot be changed once set to either male or female.

If you detect any of these errors, you should print a warning to the user and skip that line of input. The rest of the data should be read in as normal, i.e., do not exit or stop reading because of an error of this sort. Be careful not to update any of your data structures until you are sure that there are no errors with the line. Also note that it is perfectly ok to specify repeated data so long as it does not conflict with the current information. For example:

PERSON Sam

FATHER_OF Fred

SEX M

PERSON Fred

SEX M

FATHER Sam

PERSON Sam

FATHER_OF Fred

SEX M

There is a lot of redundant information in this input, but there are no errors. Everything given is self-consistent so your ftree program should not flag any errors.

Finally, your program must check for the existence of cycles in the family tree. If a cycle is detected, that means that at least one person is his or her own descendant, which is impossible. You should check for cycles one time after all the input has been read, and if there is a cycle, print out an error message explaining what happened and then exit (this is the only time you should exit the program early).

There are many pieces you will need to accomplish this program. First, you will need a person class that represents one person. Clearly the person class needs the following member variables:

Name (string)

Sex (string)

Father (person pointer)

Mother (person pointer)

Children (STL list of person pointers)

Extra variables for the cycle check

You need to write your own person class that has all of these values along with appropriate methods to get and set each one of the variables.

As you read in the input lines, you will build an STL map that contains all of the people. The key values should be strings (the name of the person) and mapped values should be pointers to your person class (person pointers). That makes it easy to search for values by name in the map, which you will do often. Every time you read a line of input you will potentially add/update one or two person objects, and you have to do all the error checking to be sure that nothing is conflicting. If everything is ok, then you'll update the person objects with the name relationship information.

Note that your ftree program reads the input from cin, not from a file. Of course, you'll want to use files to store your test input cases so that you don't have to type everything in every time you run it. Recall that you can redirect the contents of a file to be cin for a program with the < operator on the command line. For example: $./ftree < test0

Explanation / Answer

main.cpp


#include <iostream>
#include "Person.hpp"
#include <map>

int main(int argc, const char * argv[]) {

    string in;
    string name, pName;
    map<string, Person> people;
    map<string, Person>::iterator it, pIt;
  
    while(cin >> in) {
      
        cin >> name;
        if (in == "PERSON") {
          
            pName = name; // Keep track of what person is currently being evaluated
          
            people.insert(pair<string, Person>(name, *new Person(name, "")));
          
        } else if (in == "FATHER_OF") {
          
            // If child exists make pName their father
            // Else create child and set their father to pName
            if((it = people.find(name)) != people.end()) {
              
                pIt = people.find(pName);
              
                if (pIt->second.getSex() == "M" || pIt->second.getSex() == "") {
                  
                    // Check to make sure you aren't assigning a person to be its own father
                    if(pIt->second.getName() != it->second.getName()){
                      
                        it->second.setFather(&pIt->second); // Set the childs father
                        pIt->second.addChild(&it->second); // Add child into fathers children list
                      
                        // Assign the father's sex if it's currently unassigned
                        if(pIt->second.getSex() == "")
                            pIt->second.setSex("M");
                      
                    } else {
                        printf(FYEL("Warning["%s"]: "%s" cannot be their own father "), in.c_str(), pName.c_str());
                    }
                  
                } else {
                    printf(FYEL("Warning["%s"]: "%s" is a female "), in.c_str(), name.c_str());
                }
            }
            else {
              
                // Create a new person
                people.insert(pair<string, Person>(name, *new Person(name, "")));
                it = people.find(name);
                pIt = people.find(pName);
              
                it->second.setFather(&pIt->second); // Assign pName as their father
                pIt->second.addChild(&it->second); // Add child into fathers children set
              
                // Assign the fathers sex if it's currently unassigned
                if(pIt->second.getSex() == "")
                    pIt->second.setSex("M");
              
            }

        } else if (in == "FATHER") {
          
            // If name exists, set name as pName's father
            // Else create person(name) and set pName's father as person(name)
            if((it = people.find(name)) != people.end()) {
                pIt = people.find(pName);
              
                // Make sure pName doesn't already have a father
                if (pIt->second.getFather() == nullptr){
                  
                    // Make sure the fathers sex isn't female
                    if (it->second.getSex() == "M" || it->second.getSex() == "") {
                        pIt->second.setFather(&it->second);
                        it->second.addChild(&pIt->second);
                        it->second.setSex("M");
                    } else {
                        printf(FYEL("Warning["%s"]: "%s" is a female "), in.c_str(), name.c_str());
                    }
                  
                } else {
                    printf(FYEL("Warning["%s"]: "%s" already has a father "), in.c_str(), pName.c_str());
                }
            } else {
                pIt = people.find(pName);
              
                // Make sure the pName doesn't already have a father
                if(pIt->second.getFather() == nullptr){
                    people.insert(pair<string, Person>(name, *new Person(name, "M")));
                    it = people.find(name);
                    pIt->second.setFather(&it->second);
                    it->second.addChild(&pIt->second);
                } else {
                    printf(FYEL("Warning["%s"]: "%s" already has a father "), in.c_str(), pName.c_str());
                }
              
            }
          
        } else if (in == "MOTHER_OF") {
          
            // If child exists make pName the mother
            // Else create child and set father to pName
            if((it = people.find(name)) != people.end()) {
              
                pIt = people.find(pName);
                if (pIt->second.getSex() == "F" || pIt->second.getSex() == "") {
                  
                    // Check to make sure you aren't assigning a person to be its own mother
                    if (pIt->second.getName() != it->second.getName()) {
                  
                        it->second.setMother(&pIt->second);
                        pIt->second.addChild(&it->second); // Add child into mothers children set
                  
                        // Assign the mothers sex if it's currently unassigned
                        if(pIt->second.getSex() == "")
                            pIt->second.setSex("F");
                  
                    } else {
                        printf(FYEL("Warning["%s"]: "%s" cannot be their own mother "), in.c_str(), pName.c_str());
                    }
                } else {
                    printf(FYEL("Warning["%s"]: "%s" is a male "), in.c_str(), pName.c_str());
                }
            } else {
              
                // Create a new person
                people.insert(pair<string, Person>(name, *new Person(name, "")));
              
                it = people.find(name);
                pIt = people.find(pName);
              
                it->second.setMother(&pIt->second); // Assign pName as their mother
                pIt->second.addChild(&it->second); // Add child into mothers children set
              
                // Assign the mothers sex if it's currently unassigned
                if(pIt->second.getSex() == "")
                    pIt->second.setSex("F");
          
            }
          
        } else if (in =="MOTHER") {
          
            // If name exists, set name as pName's mother
            // Else create person(name) and set pName's mother as person(name)
            if((it = people.find(name)) != people.end()) {
              
                pIt = people.find(pName);
              
                // Make sure pName doesn't already have a mother
                if (pIt->second.getMother() == nullptr){
                  
                    // Make sure the mothers sex isn't male
                    if (it->second.getSex() == "F" || it->second.getSex() == "") {
                        pIt->second.setMother(&it->second);
                        it->second.addChild(&pIt->second);
                        it->second.setSex("F");
                    } else {
                        printf(FYEL("Warning["%s"]: "%s" is a male "), in.c_str(), name.c_str());
                    }
                  
                } else {
                    printf(FYEL("Warning["%s"]: "%s" already has a mother "), in.c_str(), pName.c_str());
                }
          
            } else {
                pIt = people.find(pName);
              
                // Make sure the pName doesn't already have a mother
                if(pIt->second.getMother() == nullptr) {
                  
                    // Create a new person
                    people.insert(pair<string, Person>(name, *new Person(name, "F")));
                    it = people.find(name);
                  
                    pIt->second.setMother(&it->second); // Assign the newly created person as pNames mother
                    it->second.addChild(&pIt->second); // Add pName to the newly created persons children set
                } else {
                    printf(FYEL("Warning["%s"]: "%s" already has a mother "), in.c_str(), pName.c_str());
                }
            }
          
        } else if (in == "SEX") {
          
            if((it = people.find(pName)) != people.end()) {
                it->second.setSex(name);
            }
          
        } else {
            printf(FRED("Error:    input: "%s" name: "%s" pName: "%s" "), in.c_str(), name.c_str(), pName.c_str());
        }
    }
  
    for (it = people.begin(); it != people.end(); it++) {
        it->second.Print();
    }

    return 0;
}

Person.hpp

#ifndef Person_hpp
#define Person_hpp

#include <stdio.h>
#include <string>
#include <set>
#include <list>
#include "colors.h"

#endif /* Person_hpp */

using namespace std;

class Person {
  
public:
    Person(string name, string sex);
    void Print();
  
    // Setters
    void setName(string name);
    void setSex(string sex);
    void setFather(Person* father);
    void setMother(Person* mother);
    void addChild(Person* child);
  
    // Getters
    string getName();
    string getSex();
    Person* getFather();
    Person* getMother();

private:
    string name;
    string sex;
    Person* father;
    Person* mother;
    list<Person> children;
};

Person.cpp

// Eric Lange
// COMP 4472

#include "Person.hpp"
#include <iostream>

// Constructor
Person::Person(string name, string sex):
    name(name),
    sex(sex)
{}


// Getters
string Person::getName() {
    return name;
}

string Person::getSex() {
    return sex;
}

Person* Person::getFather() {
    return father;
}

Person* Person::getMother() {
    return mother;
}


// Setters
void Person::setName(string name) {
    this->name = name;
}

void Person::setSex(string sex) {
    this->sex = sex;
}

void Person::setFather(Person* father) {
    this->father = father;
}

void Person::setMother(Person* mother){
    this->mother = mother;
}

void Person::addChild(Person* child) {
    children.push_back(*child);
}


void Person::Print() {
    printf(FWHT(" %s "), name.c_str());
  
    printf(FYEL(" Sex: "));
    if(sex == "M") {
        printf(FBLU("Male "));
    } else if (sex == "F") {
        printf(FMAG("Female "));
    } else {
        printf(FRED("unknown "));
    }

    printf(FYEL(" Father: "));
    if(father == nullptr) {
        printf(FRED("unknown "));
    } else {
        printf(FWHT("%s "), father->name.c_str());
    }

    printf(FYEL(" Mother: "));
    if(mother == nullptr) {
        printf(FRED("unknown "));
    } else {
        printf(FWHT("%s "), mother->name.c_str());
    }
  
    printf(FYEL(" Children: "));
    if(children.empty()) {
         printf(FRED("none "));
    } else {
  
        list<Person>::iterator it;
      
        for(it = children.begin(); it != children.end(); it++) {
          printf(FWHT("%s "), it->getName().c_str());
        }
      
        printf(" ");
    }
}


colors.h

#ifndef _COLORS_
#define _COLORS_

/* FOREGROUND */
#define RST ""
#define KRED ""
#define KGRN ""
#define KYEL ""
#define KBLU ""
#define KMAG ""
#define KCYN ""
#define KWHT ""

#define FRED(x) KRED x RST
#define FGRN(x) KGRN x RST
#define FYEL(x) KYEL x RST
#define FBLU(x) KBLU x RST
#define FMAG(x) KMAG x RST
#define FCYN(x) KCYN x RST
#define FWHT(x) KWHT x RST

#define BOLD(x) "" x RST
#define UNDL(x) "" x RST

#endif /* _COLORS_ */

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote