-
Family tree
So I've built a simple code that basically function as a family tree, but there's always an issue when it comes to marrying two people or printing the cousins. PLEASE HELP :(
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_NAME_LENGTH 50
typedef struct Person {
char name[MAX_NAME_LENGTH];
int age;
struct Person *spouse;
struct Person *child;
} Person;
// Function prototypes
void addHead(Person ** family);
void marry(Person ** family);
void addOffspring(Person ** family);
void printFamily(Person ** family);
void yearsPass(Person ** family);
void countPeople(Person ** family);
void printCousins(Person ** family);
void printCousinsRecursive(Person * person, int targetDegree,
int currentDegree);
void printSiblings(Person * sibling, int targetDegree, int currentDegree);
void freeFamily(Person ** family);
int main()
{
int choice;
Person *family = NULL;
do {
printf("Choose an option:\n");
printf("0. Exit\n");
printf("1. Add a head\n");
printf("2. Marry two people\n");
printf("3. Add an offspring\n");
printf("4. Print family top-down\n");
printf("5. Years pass\n");
printf("6. Count people\n");
printf("7. Print cousins\n");
scanf("%d", &choice);
switch (choice) {
case 0:
break;
case 1:
addHead(&family);
break;
case 2:
marry(&family);
break;
case 3:
addOffspring(&family);
break;
case 4:
printFamily(&family);
break;
case 5:
yearsPass(&family);
break;
case 6:
countPeople(&family);
break;
case 7:
printf("Cousins:\n");
printCousins(&family);
printf("\n");
break;
default:
printf("Invalid option\n");
break;
}
} while (choice != 0);
freeFamily(&family);
return 0;
}
void freeFamily(Person ** family)
{
Person *current = *family;
while (current != NULL) {
Person *nextPerson = current->child;
// Free the current person
free(current);
// Move to the next person
current = nextPerson;
}
// Set the family pointer to NULL
*family = NULL;
}
void addHead(Person ** family)
{
char name[MAX_NAME_LENGTH];
int age;
getchar();
printf("Enter a name:\n");
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = '\0';
// Check if the name is already taken
if (*family != NULL && strcmp((*family)->name, name) == 0) {
printf("The name is already taken\n");
return;
}
printf("Enter age:\n");
scanf("%d", &age);
// Create a new person
Person *head = (Person *) malloc(sizeof(Person));
strcpy(head->name, name);
head->age = age; // Store the entered age
head->spouse = NULL;
head->child = NULL;
// Set the new person as the family head
*family = head;
}
void marry(Person ** family)
{
getchar();
char name1[MAX_NAME_LENGTH], name2[MAX_NAME_LENGTH];
printf("Enter the name of the first person:\n");
fgets(name1, sizeof(name1), stdin);
name1[strcspn(name1, "\n")] = '\0';
printf("Enter the name of the second person:\n");
fgets(name2, sizeof(name2), stdin);
name2[strcspn(name2, "\n")] = '\0';
// Find the first person
Person *person1 = *family;
while (person1 != NULL && strcmp(person1->name, name1) != 0)
person1 = person1->child;
// Find the second person
Person *person2 = *family;
while (person2 != NULL && strcmp(person2->name, name2) != 0)
person2 = person2->child;
// Check if both persons were found
if (person1 == NULL || person2 == NULL) {
printf("One of the persons does not exist\n");
return;
}
// Check if one of them is already married
if (person1->spouse != NULL || person2->spouse != NULL) {
printf("Invalid marriage\n");
return;
}
// Check if they have a common previous head (same family)
Person *commonHead = *family;
while (commonHead != NULL
&& (commonHead->child == NULL
|| (commonHead->child != person1 && commonHead->child != person2)))
commonHead = commonHead->child;
if (commonHead != NULL) {
printf("Invalid marriage\n");
return;
}
// Check if one of them is under the age of 18
if (person1->age < 18 || person2->age < 18) {
printf("Invalid marriage\n");
return;
}
// Update the spouse pointers
person1->spouse = person2;
person2->spouse = person1;
printf("%s and %s are now married\n", person1->name, person2->name);
}
void addOffspring(Person ** family)
{
getchar();
char parent1[MAX_NAME_LENGTH], parent2[MAX_NAME_LENGTH],
offspring[MAX_NAME_LENGTH];
printf("Enter the name of the first parent:\n");
fgets(parent1, sizeof(parent1), stdin);
parent1[strcspn(parent1, "\n")] = '\0';
printf("Enter the name of the second parent:\n");
fgets(parent2, sizeof(parent2), stdin);
parent2[strcspn(parent2, "\n")] = '\0';
printf("Enter offspring's name:\n");
fgets(offspring, sizeof(offspring), stdin);
offspring[strcspn(offspring, "\n")] = '\0';
// Find the first parent
Person *person1 = *family;
while (person1 != NULL && strcmp(person1->name, parent1) != 0)
person1 = person1->child;
// Find the second parent
Person *person2 = *family;
while (person2 != NULL && strcmp(person2->name, parent2) != 0)
person2 = person2->child;
// Check if both parents were found
if (person1 == NULL || person2 == NULL) {
printf("One of the parents does not exist\n");
return;
}
// Check if the parents are married
if (person1->spouse != person2 || person2->spouse != person1) {
printf("The parents are not married\n");
return;
}
// Check if the offspring's name is already taken
Person *existingPerson = *family;
while (existingPerson != NULL) {
if (strcmp(existingPerson->name, offspring) == 0) {
printf("The name is already taken\n");
return;
}
existingPerson = existingPerson->child;
}
// Create a new offspring
Person *newOffspring = (Person *) malloc(sizeof(Person));
strcpy(newOffspring->name, offspring);
newOffspring->spouse = NULL;
newOffspring->child = NULL;
// Set the new offspring's parents
newOffspring->child = person1->child;
person1->child = newOffspring;
printf("%s was born\n", newOffspring->name);
}
void printFamily(Person ** family)
{
char name[MAX_NAME_LENGTH];
printf("Enter the name of the person:\n");
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = '\0';
// Find the person
Person *person = *family;
while (person != NULL && strcmp(person->name, name) != 0)
person = person->child;
// Check if the person was found
if (person == NULL) {
printf("Person not found\n");
return;
}
// Print the person and their family
printf("%s (%d)", person->name, person->age);
if (person->spouse != NULL) {
printf(" - %s (%d)\n", person->spouse->name, person->spouse->age);
Person *child = person->child;
while (child != NULL) {
printf("\t%s (%d)\n", child->name, child->age);
child = child->child;
}
} else {
printf("\n");
}
}
void yearsPass(Person ** family)
{
int years;
printf("Enter number of years:\n");
scanf("%d", &years);
// Traverse the family tree and add years to each person's age
Person *current = *family;
while (current != NULL) {
current->age += years;
current = current->child;
}
}
void countPeople(Person ** family)
{
int count = 0;
// Traverse the family tree and count the number of people
Person *current = *family;
while (current != NULL) {
count++;
current = current->child;
}
// Print the count of people
if (count == 1) {
printf("There is one person\n");
} else {
printf("There are %d people\n", count);
}
}
void printCousins(Person ** family)
{
char name[MAX_NAME_LENGTH];
int degree;
printf("Enter the name of the person:\n");
scanf("%s", name);
printf("Enter degree:\n");
scanf("%d", °ree);
// Find the person
Person *person = *family;
while (person != NULL && strcmp(person->name, name) != 0)
person = person->child;
// Check if the person was found
if (person == NULL) {
printf("Person not found\n");
return;
}
// Print the person
printf("%s\n", person->name);
// Print cousins of the specified degree
printCousinsRecursive(person, degree, 1);
}
void printCousinsRecursive(Person * person, int targetDegree, int currentDegree)
{
if (currentDegree > targetDegree)
return;
Person *current = person;
while (current != NULL) {
if (current->spouse != NULL) {
printSiblings(current->spouse->child, targetDegree, currentDegree);
}
current = current->child;
}
}
void printSiblings(Person * sibling, int targetDegree, int currentDegree)
{
while (sibling != NULL) {
if (currentDegree <= targetDegree) {
printf("%s\n", sibling->name);
printCousinsRecursive(sibling, targetDegree, currentDegree + 1);
}
sibling = sibling->child;
}
}
-
So what's the minimum number of things you type in for it to all go wrong.
Sure, we could stare at the code for an hour or two (not likely), or we could just run the code (using a debugger) and a known test case which breaks it.