Is this bad programming?

Steve Summit scs at adam.mit.edu
Thu Aug 9 15:45:56 AEST 1990


In article <1990Aug8.100614.1223 at resam.dk> andrew at resam.dk (Leif Andrew Rump)
worries about keeping error numbers in sync with an array of
error message strings so that the array can be indexed by the
array number.

Whenever I'm serious about making the connection between error
numbers and messages explicit rather than implicit, I do so
quite, er, explicitly:

	#define	FILE_FOOTER_ERROR		1
	#define	DRAW_FOOTER_ERROR		2
	#define	GRAP_FOOTER_ERROR		3
	#define	BASE_FRAME_CREATE_ERROR		4

	struct errmess
		{
		int em_number;
		char *em_text;
		} errmesses[] =
		{
		FILE_FOOTER_ERROR,	"File footer error",
		DRAW_FOOTER_ERROR,	"Draw footer error",
		GRAP_FOOTER_ERROR,	"Grap footer error",
		BASE_FRAME_CREATE_ERROR,"Base_frame creation error",
		};

This essentially just removes the comment delimiters placed
around the implicit subscripts that are usually provided to
remind the programmer what is going on (i.e.

	/*01*/	"File footer error",

in Leif's example).

This setup still has the disadvantages that the two components of
each line of the structure array definition are quite repetetitive
(FILE_FOOTER_ERROR vs. "file footer error"), and every new error
number must be added in two places (another #define and another
row in the table).  A special-purpose preprocessor (perhaps a sed
or awk script) could easily automate the table building, if
appropriate.

Of course, once the array of structures is set up, it's a simple
matter to write a little routine char *errtext(int errnum) which
takes an error number and searches the array, returning
(similarly to the standard library routine strerror) the
corresponding error string, or "Error %d", (with %d filled in, of
course) for the eventual undefined or illegal error.

The scheme has a few other advantages: error numbers can start at
0, 1, or any other number, they can be sparse or negative, and
the existence (and mandated use; nobody can cheat and index on an
array) of the errtext() routine means there's a convenient hook
(namely, the errtext routine itself) for changing things later to
pull error messages out of a file at run time or some other
useful game.

Someone will howl that a linear scan of the error number/string
pairing array would be "too inefficient," but I would point out
that (a) it wouldn't, if there are a reasonable number of error
numbers, and (b) error message printing is not usually a
bottleneck, and (c) you could rewrite the routine to use binary
search (or, God help you, a hash table) if you really wanted to.
(That's another nice thing about a functional interface: you can
always drop in some other implementation, that needs to gain
control to do something, that you wouldn't be able to do if the
"interface" were simply the access by the "caller" of a global
variable or array.)

                                            Steve Summit
                                            scs at adam.mit.edu



More information about the Comp.lang.c mailing list