Commit 46e9307c authored by Dominik Widhalm's avatar Dominik Widhalm
Browse files

Added example solutions for task 6.15 (ch 6 finished)

parent f8b7dc81
/******************************************************************************
* C PROGRAMMING *
* BASIC EXERCISES - EXAMPLE SOLUTIONS *
* *
* Task_6.15: Ancestor Table *
* Author: Dominik Widhalm *
* Email: dominik.widhalm@technikum-wien.at *
* Date: 2017-09-04 *
* *
******************************************************************************/
/***** INCLUDES ***************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/***** MACROS *****************************************************************/
// Maximum length of strings
#define STRING_MAX 20
// Maximum depth of the ancestor tree
#define TREE_MAX_DEPTH 5
/***** TYPEDEFS ***************************************************************/
/* Enumeration type for function return values */
typedef enum {SUCCESS, FAILED} retval_t;
/* Enumeration type for adding type */
typedef enum {SUBJECT, FATHER, MOTHER} addtype_t;
/* Structure for a tree element */
typedef struct person {
/* Kekule number */
int kekule;
/* Person's first name */
char firstname[STRING_MAX];
/* Person's family name */
char familyname[STRING_MAX];
/* Pointer to the father element */
struct person *father;
/* Pointer to the mother element */
struct person *mother;
} person_t;
/***** FUNCTION PROTOTYPES ****************************************************/
person_t *person_new (addtype_t type, person_t *child);
retval_t person_add_parents (person_t *child);
retval_t person_add_level (person_t *subject);
int person_get_depth (person_t *subject);
void person_print_level (person_t *subject, int level);
void person_print_tree (person_t *subject);
void person_free (person_t *node);
/***** LOCAL FUNCTIONS ********************************************************/
/******************************************************************************
* person_new *
* @brief Function to create a new person. *
* *
* This function creates a new person element, queries his/her name and *
* returns the element's address. *
* *
* @return Pointer to the new element *
******************************************************************************/
person_t *person_new (addtype_t type, person_t *child) {
/* Allocate memory for the new element */
person_t* new = (person_t*)malloc(sizeof(person_t));
/* Check if malloc was successful */
if (new == NULL) {
/* Memory could not be allocated */
return NULL;
}
/* Temporary string for user query */
char query[STRING_MAX];
/* User query text depends on type of new element */
switch(type) {
case SUBJECT:
sprintf(query,"the subject");
break;
case FATHER:
sprintf(query,"%s's father",child->firstname);
break;
case MOTHER:
sprintf(query,"%s's mother",child->firstname);
break;
}
/* Ask the user to enter the person's first name */
printf("Please enter %s's first name: ",query);
/* Read in the user's input */
scanf("%s",new->firstname);
/* Ask the user to enter the person's family name */
printf("Please enter %s's family name: ",query);
/* Read in the user's input */
scanf("%s",new->familyname);
/* Initially set its Kekule number to 0 */
new->kekule = 0;
/* Initially set its parent pointers to NULL */
new->father = NULL;
new->mother = NULL;
/* Return the address of the new element */
return new;
}
/******************************************************************************
* person_add_parents *
* @brief Function to add/create the parents of a given person. *
* *
* This function adds/creates the parent elements of a given person. *
* Thereby also the Kekule numbers are calculated and added. *
* *
* @param child Pointer to the child element *
* @retval SUCCESS Parents were successfully added *
* @retval FAILED Parents could not be added *
******************************************************************************/
retval_t person_add_parents (person_t *child) {
/* Check if the child has a valid address */
if (child == NULL) {
/* No valid child available */
return FAILED;
}
/* Create the child's father */
child->father = person_new(FATHER,child);
/* Check if the element was successfully created */
if (child->father == NULL) {
/* Father element could not be created */
return FAILED;
}
/* Calculate the father's Kekule number */
child->father->kekule = child->kekule * 2;
/* Print a separating space */
printf("\n");
/* Create the child's mother */
child->mother = person_new(MOTHER,child);
/* Check if the element was successfully created */
if (child->mother == NULL) {
/* Mother element could not be created */
return FAILED;
}
/* Calculate the mother's Kekule number */
child->mother->kekule = child->kekule * 2 + 1;
/* Parents were successfully added */
return SUCCESS;
}
/******************************************************************************
* person_add_level *
* @brief Function to add a new level of ancestors. *
* *
* This function adds/creates an entire level of ancestors. To do so, it *
* recursively traverses the current tree and adds parents to each leaf *
* node. *
* *
* @param subject Pointer to the subject (first) element *
* @retval SUCCESS Level was successfully added *
* @retval FAILED Level could not be added *
******************************************************************************/
retval_t person_add_level (person_t *subject) {
/* Check if given subject has a valid address */
if (subject == NULL) {
/* No valid subject available */
return FAILED;
}
/* Check if current node is already a leaf node (determined by mother pointer) */
if (subject->mother == NULL) {
/* Print a separating space */
printf("\n");
/* (Try to) add parents to this leaf node */
return person_add_parents(subject);
} else {
/* Temporary retval variable */
retval_t father, mother;
/* (Try to) add new level recursively */
father = person_add_level(subject->father);
mother = person_add_level(subject->mother);
/* Return the return values */
if ((father == SUCCESS) && (mother == SUCCESS)) {
/* Adding was successfull */
return SUCCESS;
} else {
/* Adding failed */
return FAILED;
}
}
}
/******************************************************************************
* person_get_depth *
* @brief Function to determine the current depth of the tree. *
* *
* This function calculates and returns the current depth of the tree. *
* *
* @param subject Pointer to the subject (first) element *
* @return Current depth of the tree (min = 1) *
******************************************************************************/
int person_get_depth (person_t *subject) {
/* Temporary variable for the depth */
int temp = 1;
/* Temporary pointer to traverse the tree */
person_t* curr = subject;
/* Go down the tree (use father's sides) */
while (curr->father != NULL) {
/* Increase depth counter */
temp++;
/* Go to the next level */
curr = curr->father;
}
/* Return the obtained depth */
return temp;
}
/******************************************************************************
* erson_print_level *
* @brief Function to print all elements of a given level. *
* *
* This function prints all elements of a given level of depth. *
* *
* @param subject Pointer to the subject (first) element *
******************************************************************************/
void person_print_level (person_t *subject, int level) {
/* Check if given subject has a valid address */
if (subject == NULL) {
return;
}
/* Check if desired level has been reached */
if (level == 1) {
/* Print the current element's data */
printf("%02d - %s %s\n",subject->kekule,subject->firstname,subject->familyname);
/* Continue recursively until desired level is reached */
} else if (level > 1) {
/* Call function with the father's side */
person_print_level(subject->father,(level-1));
/* Call function with the mothers's side */
person_print_level(subject->mother,(level-1));
}
/* A void function has nothing to return */
return;
}
/******************************************************************************
* person_print_tree *
* @brief Function to print the current ancestor tree recursively. *
* *
* This function prints the current ancestor tree in list form where the *
* elements are defined by their Kekule number *
* *
* @param subject Pointer to the subject (first) element *
******************************************************************************/
void person_print_tree (person_t *subject) {
/* Check if subject node is valid */
if (subject == NULL) {
/* No more nodes */
return;
}
/* Print the table header */
printf("\n========== ANCESTOR TABLE ==========\n");
/* Get the depth of the current tree */
int depth = person_get_depth(subject);
/* Print the tree level by level */
for (int i=1; i<=depth; i++) {
/* Print generation */
printf("Generation %d:\n",(i-1));
/* Print all elements of current level */
person_print_level(subject,i);
/* Add a newline if it is not the last level */
if (i<depth) {
printf("\n");
}
}
printf("====================================\n\n");
/* A void function has nothing to return */
return;
}
/******************************************************************************
* person_free *
* @brief Function to free the memory of the tree recursively. *
* *
* This function traverses the tree and frees the memory of all nodes *
* contained recursively. *
* *
* @param node Pointer to the current node *
******************************************************************************/
void person_free (person_t *node) {
/* Check if current node is already a NULL pointer */
if (node == NULL) {
/* Nothing to be done here */
return;
}
/* Recursively free the memory of the parents */
person_free(node->father);
person_free(node->mother);
/* Now free the memory of the current node */
free(node);
/* A void function has nothing to return */
return;
}
/***** MAIN ROUTINE ***********************************************************/
int main (void) {
/*** Local Variables ***/
char input='n';
int depth;
/* Create the subject node */
person_t *subject = person_new(SUBJECT,NULL);
/* Check if the subject node could be created */
if (subject == NULL) {
/* Subject node could not be created */
printf("\nERROR: Could not create subject node!\n");
} else {
/* First element (subject) has kekule number = 1 */
subject->kekule = 1;
/* Add new levels as long as the user wants to */
do {
/* Print the current tree */
person_print_tree(subject);
/* Get the current depth of the tree */
depth = person_get_depth(subject);
/* Check if maximum depth is not reached yet */
if (depth >= TREE_MAX_DEPTH) {
/* Maximum depth has been reached */
input = 'n';
} else {
/* Ask the user if he/she wants to add a new level of parents */
printf("Do you want to add a new level (y/n): ");
/* Read in the user's response */
scanf(" %c",&input);
/* Check if user wants to add a new level */
if (input == 'y') {
/* (Try to) add a new level of ancestors */
if (person_add_level(subject) == FAILED) {
/* New level of ancestors could not be created */
printf("\nERROR: Could not create new level of ancestors!\n");
}
}
}
} while (input == 'y');
}
/* Free the allocated memory recursively */
person_free(subject);
/* Notify the user about the termination of the program */
printf("\nThe program will now be terminated...\n");
return 0; /* Return with Success (0) */
}
/******************************************************************************/
# Get the current path(s) (relevant directory on last position)
TASKPATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
CHPATH := $(dir $(TASKPATH:%/=%))
# Variables for text substitution
empty:=
slash:= /
space:= $(empty) $(empty)
task:= task_
ch:= ch_
# Get TASK number
TASK := $(subst $(slash),$(space),$(TASKPATH))
TASK := $(lastword $(TASK))
TASK := $(subst $(task),$(empty),$(TASK))
# Get CH number
CH := $(subst $(slash),$(space),$(CHPATH))
CH := $(lastword $(CH))
CH := $(subst $(ch),$(empty),$(CH))
# Specify SRD directory
SRCDIR = .
# Call superior makefile
include ../../makefile
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment