Assignment #6 Answers

Intermediate C Programming

UW Experimental College

Assignment #6 ANSWERS

Exercise 2.
Modify io.c to recognize a new entrypoint line
in the data file.

Here is the code I added to io.c.
Rather than calling findroom right away,
and face the possibility of the room not being defined yet,
I chose to just stash the name of the room away
(as a string),
and then try looking it up after the data file had been
completely read.
I added this declaration at the beginning of
parsedatafile:

Exercise 3.
Think about what it would take
to use the cmdtab structure,
and the findcmd function,
to streamline the code that processes lines in the data file.

It would initially seem straightforward to take each case in the
if/else chain,
break it out to a separate function,
build a table
(an array of struct cmdtab)
linking the first words on lines in the data file
to the new functions for parsing those lines,
and finally call findcmd
(after reading each line)
to decide which function to call.

The first problem you might face, though,
would be breaking up the old parsedatafile function.
It contains a number of local variables
(especially currentroom and currentobject)
which several of the parsing cases need access to.
Once you broke those parsing cases out into separate functions,
they'd need access to the (formerly local) variables somehow.
You'd probably have to make them global,
although you could restrict them to the source file io.c
by declaring them static.

The next problem you'd face would be deciding which information
to pass to the broken-out functions.
Most of them use the av array to inspect the various
arguments and other words which appeared on the line they're parsing,
but for at least one way I wrote the long description reading code,
it needed to use the original
copy of the complete data file input line
(that is, the line array),
the copy that hadn't been
broken apart by getwords.
The obvious information to pass to each parsing function is
the ac count and the av array
(which are, not coincidentally,
quite similar to the argc and argv with which
main is traditionally called).
Would you have to pass along the unbroken line to all functions,
for the benefit of just the one or two that needed it?
(Remember, all the functions must accept the same argument list,
because one function call, using the function pointer in the
func field of the matching struct cmdtab
entry, will be calling all of them.)

Finally, once you decided what information to pass to each
individual line parsing function,
you'd discover (if you've got strict prototype checking turned on
in your compiler, and if you used cmdtab.c and
cmdtab.h as they appeared in last week's handout),
that the compiler doesn't want you to create an array of
struct cmdtab with the func fields pointing
at your shiny new functions,
because the func field
(again, as it appeared in last week's handout),
is specifically a pointer to a function accepting
a struct actor *,
a struct object *,
and a struct sentence *,
which is almost certainly not
the set of data
you chose to pass to each data file parsing function.
You'd either have to revert the declaration of the func
field to

int (*func)();

(as it was on the disk)
and turn off strict prototype checking,
or write a second whole version of struct cmdtab and
a second whole version of findcmd that used
func fields with a different prototype,
or play some
(fairly ugly)
games with function pointer casts.