Helper Functions for Genericity
Learn to abstract the concrete handling of data types in order to keep the functions generic.
Introduction
The other essential function we need to write is the printGenericList
function.
We can’t view the contents of the lists, and we can’t check if we are building them correctly or not without a print function.
However, as we will see in this lesson, creating a generic print function isn’t easy. It will have to call printf
with the concrete type of the element.
But the whole point of a generic function is that it doesn’t care about the type of elements.
Printing elements from a generic linked list
To address the above issues, we’ll use a helper function which we will pass to the generic function as an argument. The helper function will be different for each data type:
- For a list of integers, we may write a
printInteger
function, which knows how to print one integer. - For a list of strings, we may write a
printString
function, which knows how to print one string (char
array).
We’ll then pass printInteger
and printString
to printGenericList
, depending on the type of list that we want to print.
Note: We don’t create multiple
printGenericList
functions, as we’ll have a lot of duplicate code. The functions would be identical except for theprintf
call.
The printInteger
function
Let’s look at the printInteger
function defined on line 5. We remember that the type of the value
field of a node is void*
, so the printInteger
function must accept a void*
and convert it back to an int*
(line 12).
We can convert it here because we know that printInteger
will only deal with integers, not other data types.
In other words, printInteger
is not a generic function, and we call it from the printGenericList
function, which is generic.
Nextly, we need to dereference the pointer to get to the actual value. In this example, we chose to print it enclosed in []
(line 13).
The printString
function
Let’s look at the printInteger
function defined on line 6. We remember that the type of the value
field of a node is void*
, so the printString
function must accept a void*
and convert it back to a char*
(line 23)
.
We can convert it here because we know that printString
will only deal with strings (char
arrays), not other data types. In other words, printString
is not a generic function, but we call it from the printGenericList
function, which is generic.
Next, we need to pass the pointer to printf
to print the string. Strings are arrays, meaning their name is a pointer to the first element. The printf
function expects such pointers, so we don’t need to dereference anything.
The printGenericList
function
The function must accept an argument in the form of a function pointer void(*printFunc)(void*)
(line 27). The printFunc
pointer is a pointer to a function that accepts a void*
as an argument and returns void
. This is the type that all concrete print functions (like printInteger
) must follow.
Then, as we iterate over the list to print its elements, we call printFunc
on each element current->value
(line 40).
Finally, we can call the printGenericList
function to print our lists. Please notice the calls in lines 53 and 54. We pass the list and the corresponding print function.
Get hands-on with 1400+ tech skills courses.