J.Jay
J.Jay

Reputation: 249

Typedef enum to string in C

I have error typedefs as follows.

typedef enum {  Connection_Error
    , Parity_Error
    , Data_Read_Error 
     } error_t;

And I have a function returning the "error_t". I would like to change the enum to string (preferably without using switch(case)).

Eg.

char str[20];
str = function_to_convert_to_string (error_t);

Something like that. Any suggestions?

Upvotes: 0

Views: 1682

Answers (1)

Dai
Dai

Reputation: 154995

The C language does not have any built-in provision for storing symbol-names as strings in the output binary program (unlike Java and C# which have the .ToString() method) so you must manually do this in your code - fortunately it's made easier with the preprocessor's ability to convert symbols to string-literals ("stringification").

Note that typedef enum { ... } name is unnecessary, and avoid using _t as a suffix as it is reserved by the POSIX specifications.

Try this:

enum errorType {
    Connection_Error,
    Parity_Error,
    Data_Read_Error
};

#define ERRMSG( ARG ) \
case ARG: \
    return "Error: " #ARG ".";

char* getErrorMessage(errorType e) {
    switch(e) {
        ERRMSG( Connection_Error )
        ERRMSG( Parity_Error )
        ERRMSG( Data_Read_Error )
        default: exit(1); // or some other error handler
    }
}

Note how you see the enum is manually listed twice in code: first in the enum definition, and again in the switch block. For small enums this is fine, but if your enum list is large or changes frequently you'll want to adopt a DRY approach. You can simplify it by listing all of the enums in their own text file, like so:

ErrorTypeEnum.inc

 ENTRY( Connection_Error )
 ENTRY( Parity_Error )
 ENTRY( Data_Read_Error )

ErrorTypeEnum.h

 #define ENTRY(NAME) NAME,
 enum errorType {
 #include "ErrorTypeEnum.inc"
     _Last
 }
 #undef ENTRY

The _Last entry is needed because of the trailing comma, also provides a means to get the count f elements because _Last will have a numeric value equal to the last ENTRY + 1.

ErrorTypeEnum.c

char* getErrorMessage(errorType e) {
    switch(e) {
#define ENTRY(NAME) case NAME: return "Error: " #NAME ".";
#include "ErrorTypeEnum.inc"
        default: exit(1); // or some other error handler
#undef
    }
}

Further

You can expand upon this by adding other values to the ENTRY macro, such as custom human-readable error messages (instead of using stringification). That is an exercise left up to the reader :)

Upvotes: 1

Related Questions