Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
master-embedded-systems
c-exercise-solutions public
Commits
46e9307c
Commit
46e9307c
authored
Sep 04, 2017
by
Dominik Widhalm
Browse files
Added example solutions for task 6.15 (ch 6 finished)
parent
f8b7dc81
Changes
2
Hide whitespace changes
Inline
Side-by-side
ch_6/task_15/main.c
0 → 100644
View file @
46e9307c
/******************************************************************************
* 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
(
"
\n
ERROR: 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
(
"
\n
ERROR: 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
(
"
\n
The program will now be terminated...
\n
"
);
return
0
;
/* Return with Success (0) */
}
/******************************************************************************/
ch_6/task_15/makefile
0 → 100644
View file @
46e9307c
# 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
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment