Your job in this lab is to write the program famtree. Famtree takes a description of people and their relationships to one another on standard input. These descriptions must be in a special format, which will be described below. An example is in the file fam1, which represents a family composed of Bob and Nancy, and their three chidren Frank, Lester and Diana.
Famtree takes such a description, and prints out complete information on all of the people in the file. This consist of, for each person, their sex (if known), their father, mother and children. Therefore fam1output contains valid output of famtree on fam1.
The format of the input file is as follows. Lines must either be blank, or have one of following first words:
The second feature of famtree is that it allows for redundancy, but it infers as much as it can. For example, redundant has a few lines that are redundant. For example, line 3 is redundant because Fred must be male by virtue of being Joe's father. Moreover, line 7 is redundant because line 2 already specified Fred as Joe's father. The file nonredundant is the minimal file specifying the same family.
Getting the output in the correct order is another 20%. Therefore, if you write a program that simply prints out all people in some order, but with the correct information, then you'll get 70%.
You will have a struct for a person (mine is called a Person). That struct will have the following fields:
Your program will work in three phases:
Each time you read a line that has a name (i.e. PERSON, FATHER, MOTHER, FATHER_OF and MOTHER_OF) you test to see if the person with that name is in the people tree. If not, you create the struct and insert it.
Whenever you process a line that needs to create some links (i.e. FATHER, MOTHER, FATHER_OF and MOTHER_OF), you first check to see if the link exists and is correct. If incorrect, you flag an error. If correct, you do nothing. If the link doesn't exist, you should create it in both the parent and the child.
When you're done with this phase, you'll have a red-black tree with all people in it, and all the people will have the correct links to their parents and children.
/* assume that there is an integer field called "visited"
in the Person struct, and that this field is initialized
to zero for all people */
is_descendant(Person *p)
{
if (p->visited == 1) return 0; /* I.e. we've processed this
person before and he/she's ok */
if (p->visited == 2) return 1; /* I.e. the graph is messed up */
p->visited = 2;
for all children of p do {
if is_descendant(child) return 1;
}
p->visited = 1;
return 0;
}
Then you execute a loop that does the following:
/* assume that there is an integer field called "printed"
in the Person struct, and that this field is initialized
to zero for all people */
while toprint is not empty
take p off the head of toprint
if p has not been printed, then
if p doesn't have parents, or if p's parents have been printed then
print p
for all of p's children, put the child at the end of doprint
end if
end if
end while