L. Zeda L. Zeda - 3 months ago 9
C Question

Could I use preprocessor to make this one clearer?

I was writing a little source file function for my Pic32 and I got stucked on one thing.
It's basically an utility that should store incomming

char
data into buffer and then, if
'\r'
is recieved, it compares the buffer against list of commands (in array
names
), and if match is found, the index of the item is returned.

This part is from header:

#define NAMECNT 6
static const char names[NAMESCNT][10] = { // 6commands, max 10 char each
"korr", // 1
"adc", // 2
"fft", // 3
"data", // 4
"pr", // 5
"prsc"}; // 6

/* functions */
extern int comm(char cdata);


At the main file, there is one big switch:

switch( comm(recieved_ch) ){
case 1: foo1(); break;
case 2: foo2(); break;
...
}


Now, for the better clarity, I wanted to use instead of 1, 2, ... the original names (like
case KORR: case ADC:
) so I wrote deffinitions for each one of them

#define KORR 1
#define ADC 2


But I don't like that solution, because I want to use this source file in more projects and there is gonna be different list of commands for each. Is there any way how to do this?
Best thing would be to create the array names in preprocessor, but I doubt that's even possible. I was thinking about using enum type (which would have same items as list of commands
names
), but I am not sure how would that go.

Answer

You can use X-macros to build an enum and fill the array, then you can use the enum values in the switch:

#define VARS \
    X(korr) \
    X(adc)  \
    X(fft)  \
    X(data) \
    X(pr)   \
    X(prsc)

static const char names[][10] = {   // 6commands, max 10 char each
#define X(name) #name,
    VARS
#undef X
};

enum evars {dummy /* 0 */,
#define X(name) name, 
    VARS
#undef X
};

extern int comm(char cdata);

int main(void)
{
    char x = 1;

    switch (comm(x)) {
        case korr:
            printf("korr");
            break;
        case adc:
            printf("adc");
            break;
        /* ... and so on */
    }
    return 0;
}

The expansion of X is:

static const char names[][10] = {

 "korr", "adc", "fft", "data", "pr", "prsc",

};

enum evars {dummy,

 korr, adc, fft, data, pr, prsc,

};

Edit: As pointed out by @5gon12eder, you don't need to hardcode 6 in the first dimension of the array (you can leave it unspecified).