This was one of the first projects that I did, this is through the CS50 course. The project is called inheritance. The purpose of this project was to learn the fundamentals of the C language, memory allocation, pointers, and objects. The end goal was to print out three generations of blood types that were randomly inherited from the parents blood type.
In the beginning there was life, and then it multiplied.
And now for the mess that created the output.
It starts by defining what a person is, that is they have two parents and
two alleles.
Next the number of GENERATIONS that will be created is defined, and an INDENT_LENGTH is defined that will be used to seperate the family members as they are printed to the console. This section finishes by defining the functions.
The main function lays out a clear process of operation, create, print, free. Simple enough.
create_family(int generations) takes in an in integer which in theory will determine the number of generation to output. Apparently I didnt take this into consideration at the time so here is the current state.
It simply checks that there is more than one generation to create then goes ahead and creates
the parents (k for loop, person *p being the parents) and
the grandparent (i for loop, with person *pa being each
grandparent) of the person.
Here is where the assignment of the alleles is done. Each grandparent is given two random alleles.
This is done through the j for loop. Once the grandparents have the alleles this will
determine the parents alleles by the rand() % 2 which will get either 0 or 1.
The allele at the random index is assigned to the parent.
Finally the parents are assigned to the person *c, and the current person is
give random alleles from the parents.
I'm going to do a quick rework on this section.
Jump to Rework
This function is also recursive.
The first if statement handles the last generations non-existent parent.
It then applies the appropriate indentation for the generation.
Finally it prints the current generation and calls the next parent to be printed.
Once again I did not do this very cleanly, in fact it is almost sad how shabby this function looks. I will let you be the final judge though.
This function starts off by creating a list of the full ancestor list of the person *p.
The int i tracks the current generation being freed. The while loop will then
take in p only if it is not already NULL.
Now for the mess...
tmp and tmp1 are assigned to the parents of person *p
This next part gets very muddy. p->parents[1] is assigned to ancestors.
Next we check if the address of list[i] is equal to p, if
it is p is set to NULL otherwise p is freed. This then allows for the next p->parents[0]
to be assigned to p.
The following if statement checks if it is the last generation. If it is, all
of the grandparents of the origonal person that was passed in along with the parents. If its the
first generation the function ends, otherwise it goes back a generation and goes through the function
again.
If it is not the last generation, p->parent[1] is put into the list. These
people in the list will be brought into the function as the p->parent[0] are
freed.
I will also clean this one up.
Jump to Rework
I couldnt handle leaving this in this state considering its going on display so I went through and ironed out the ameteurish and confusing mistakes made. I will run through the major changes.
I wont spend much time on this but this new method takes advantage of recursion. By utilizing the call stack I am able to create generations to any number. I made the operation two seperate functions where the first simply makes sure there is more than one generation to create and the second creates all of the people in the family. I also broke out the process of creating the final generation to create_last_generation(), and the assignment of alleles to inherit_allele(). This was for easier readability, the biggest problem I had with the first implementation, well first of all it didnt even work properly, but also it was crambed up with for loops which made it hard to follow.
I am happy with this one, it reads from top to bottom and does what it should do clear and simple.
I think the output from the print statements will show quite clearly how it works but heres a brief
explanation.
Check for NULL, Check if parents are NULL, free and return if so, if not store parents, free p call
function with parents.