Gen.c

/* GEN.C - Demonstration of data structures, simulating an geneology program
**
** This program demonstrates linked lists, trees, and recursion, to simulate 
** a program that would store family geneology information.

**
** Mario Giannini
*/
#include <stdio.h>
#include <stdlib.h>

struct _tagPERSON {
	char Name[65];
	char Sex;
	struct _tagPERSON * Mom, * Dad;
	/* Note: the Younger/Older is a linked list of persons */
	struct _tagPERSON * SiblingYounger, * SiblingOlder;
	struct _tagPERSON * Spouse;
	struct _tagPERSON * Children;
	struct _tagPERSON * Next;  /* Provides easy searching/deleting ability */
	};

typedef struct _tagPERSON PERSON;

PERSON * World;

/*** Makes one new PERSON (dynamically), with no relations */
PERSON * CreatePerson( char * Name, int Sex )
{
	PERSON * New;
	
	if( (New = calloc(1,sizeof(PERSON))) == NULL )
		return(NULL);

	strcpy(New->Name,Name);
	New->Sex = Sex;
	/* Add new person to the world of persons */
	New->Next = World;
	World = New;
	return(New);
}

/**** Marries two persons by connecting them via Spouse pointer */
void Marry( PERSON * Bride, PERSON * Groom )
{
	if( Bride->Spouse != NULL || Groom->Spouse!=NULL || Bride==Groom )
		printf("Sorry, can't marry %s to %s\n", Bride->Name, Groom->Name );
	else
	{
		Bride->Spouse = Groom;
		Groom->Spouse = Bride;
	}
}

/**** Creates a new person for a person (and their spouse) **/
PERSON * HasBaby( PERSON * Person, char * Name, int Sex )
{
	PERSON * New;
	
	if( (New = CreatePerson(Name,Sex)) == NULL )
		return(NULL);
	
	if( Person->Children != NULL )  /* Not first child, add to the list... */
	{
		New->SiblingOlder = Person->Children; 
		New->SiblingOlder->SiblingYounger = New; /* My older sibling's younger sibling is me */
	}

	/* New child appears at head of children list */
	Person->Children = New;
	Person->Spouse->Children = New;

	/* Determine of this person as the Mom or Dad of baby */
	New->Mom = Person->Sex=='F' ? Person : Person->Spouse;
	New->Dad = Person->Sex=='M' ? Person : Person->Spouse;
	return(New);
}

/** Displays person data **/
void ShowPerson( PERSON * Person )
{
	PERSON * PersonList;
	printf("Stats for %s:\n", Person->Name );

	printf("\tMom: %s\n", Person->Mom ? Person->Mom->Name : "N/A" );
	printf("\tDad: %s\n", Person->Dad ? Person->Dad->Name : "N/A" );

	if( Person->Spouse != NULL )
		printf("\tMarried to %s\n", Person->Spouse->Name );
	else
		printf("\tIs not married\n");

	if( Person->SiblingYounger == NULL && Person->SiblingOlder == NULL )
		printf("\tHas no siblings\n");
	else
	{
		/* First, go back in the sibling list, to the youngest */
		for( PersonList = Person; PersonList->SiblingYounger!=NULL; PersonList = PersonList->SiblingYounger )
			;

		/* Then list all the siblings, except this person */
		for( ; PersonList!=NULL; PersonList = PersonList->SiblingOlder )
			if( PersonList != Person )
				printf("\tHas a %s named %s\n", PersonList->Sex=='M'?"brother":"sister", PersonList->Name);
	}

	if( Person->Children == NULL )
		printf("\tHas no children\n");
	else
	{
		/* List all the children */
		for( PersonList=Person->Children; PersonList!=NULL; PersonList = PersonList->SiblingOlder )
				printf("\tHas a %s named %s\n", PersonList->Sex=='M'?"son":"daughter", PersonList->Name);
	}
}

/** We can't live forever */
void NukeEm( void )
{
	PERSON * PersonList = World, * LastPerson;

	while( PersonList )
	{
		LastPerson = PersonList;
		PersonList = PersonList->Next;
		printf("About to delete %s\n", LastPerson->Name );
		free( LastPerson );
	}
}

void main( void )
{
	PERSON * Mom, * Dad, * Baby, * BabysHubby, * GrandSon;

	Mom = CreatePerson("Edith", 'F' );
	Dad = CreatePerson("Archie", 'M' );
	Marry( Mom, Dad );

	Baby = HasBaby( Mom, "Gloria", 'F' );
	HasBaby( Mom, "Bozo", 'M' );

	BabysHubby = CreatePerson( "Meathead", 'M' );
	Marry( Baby, BabysHubby );

	GrandSon = HasBaby( Baby, "Joey", 'M' );

	ShowPerson( Baby );
	ShowPerson( BabysHubby );

	NukeEm( );
}