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:

char *entryroom = NULL;
I added this case to the main if/else chain in parsedatafile:
	else if(strcmp(av[0], "entrypoint") == 0)
		{
		struct room *roomp;
		if(ac < 2)
			{
			fprintf(stderr, "missing entry room name\n");
			continue;
			}
		/* don't bother to look up yet; just save name */
		entryroom = chkstrdup(av[1]);
		}
I added this code at the end of parsedatafile:
if(entryroom != NULL)
	{
	struct room *roomp = findroom(entryroom);
	if(roomp != NULL)
		setentryroom(roomp);
	else	fprintf(stderr, "can't find entry room %s\n", entryroom);
	}
Finally, I added the new setentryroom function in rooms.c:
void
setentryroom(struct room *roomp)
{
entryroom = roomp;
}

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.

This page by Steve Summit // Copyright 1995-9 // mail feedback