We want to define a C++ type
list that works like:
To display a list:
- Display "("
- Display the list items separated by spaces
- Display ")"
Here is the code structure. Note the use of another forward
declaration.
Being able to dereference
listItem pointers using
"
->" instead of "
." is possible through the
use of:
Without
typedefs, code involving pointers can be hard to
read. Here is
displayItems without using the ADT or the
typedef:
Being able to use operations like
isEmpty,
car,
and
cdr from the
list abstract data type (ADT)
makes list processing easier than without them.
Here is
displayItems without using the ADT:
To display the items, we can use recursion or iteration along
with operations from our
list ADT.
A recursive approach (although it generates an iterative process):
An iterative approach:
Accessing lists through
car and
cdr is simply a
matter of using the "
->" member operator on a
list variable, which is a pointer to a
listItem.
Note the use of the C++
throw statement to indicate an
error:
Error handling in C++ is accomplished with the
throw
statement and the
try ... catch statement combination.
- If during the execution of code contained in a try
statement a throw statement is executed, the code
contained in a catch statement is executed.
- Typically, a throw statement is executed when an
error (or "exception") occurs, and the catch statement
"handles" the error.
Here is an example of handling an error that occurs when trying
to take the
car of an empty list:
The
throw statement in the body of the
car
procedure causes the
catch statement to be executed with
the output:
Error: Taking car of an empty list
Note: The
catch statement specifies a typed variable
to receive the value thrown by the
throw statement. In this
case, a
string is thrown and displayed to standard output.
To add an integer
i to the beginning of a list
lst:
- Create a new listItem struct
- Set the struct's item member to i
- Set the struct's rest member to lst
The process is the same for empty and nonempty lists.
Suppose we want to cons 5 onto an empty list:
-
Create a pointer to a new item:
-
Set its members:
Suppose we want to cons 1 onto the list (2 3 4 5):
-
Create a pointer to a new item:
-
Set its members:
Null pointers are represented in C++ through the
nullptr
keyword.
So to create an empty list we return
nullptr, and to
test a list for emptiness we check for
nullptr:
Lists are constructed by linking together list items.
Here is the structure of our example:
lst is a pointer to a
listItem struct whose
item member is
1 and whose
rest member is
a pointer to another
listItem.
The last
listItem's
rest member is a
null pointer,
or pointer to nothing, indicating an empty list.
For simplicity, we will restrict the elements of lists to integers.
To implement lists, we define a
listItem type that
simulates a Racket
cons whose
car
is an integer and whose
cdr is a pointer to another list
item:
Note that a
list is simply a pointer to a
listItem.
Operation |
Result |
makeList() |
returns an empty list |
cons(item, list) |
adds an item to the beginning of a list
and returns the new list |
car(list) |
returns the first element of a list; throws an error
if the list is empty |
cdr(list) |
returns the tail of a list (all but the first
element); throws an error if the list is empty |
isEmpty(list) |
returns true if the list is empty, false
otherwise |
display(list) |
displays the list as "( ... )" |