6

I have the following if-statements:

    if (strcmp(registerName, "zero"))
            return 00000;
    else if (strcmp(registerName, "at"))
        return 00001;
    else if (strcmp(registerName, "v0"))
        return 00010;
    else if (strcmp(registerName, "v1"))
        return 00011;

It's actually really long - about 20 if-statements. Therefore, I would like to use a switch. How would I convert that to switch when each statement has a different condition?

I tried something as the code below, but it does not work:

int registerAddress;

switch(registerAddress) {

case 1 (strcmp(registerName, "zero")):
        regsiterAddress = 00000;
        break;
case 2 (strcmp(registerName, "at")):
        registerAddress = 00001;
        break;
}
darksky
  • 20,411
  • 61
  • 165
  • 254

5 Answers5

7

You can't — switch statements in C only work on primitive types, not on strings. You could use, say, a hash table or a search tree to optimize the matching, but for only 20 options that may not be worth the trouble.

What you could do, to clean up the code, is set up a mapping table:

struct str2Num {
    char *str;
    int num;
};

const struct str2Num registerMap[] = {
    { "zero", 00000 },
    { "at", 00001 },
    { "v0", 00010 },
    { "v1", 00011 },
    { NULL, 0 }  /* end marker */
};

and do your matching like this:

int i;
for (i = 0; registerMap[i].str != NULL; i++) {
    if (strcmp(registerName, registerMap[i].str) == 0) {
        return registerMap[i].num;
    }
}
/* handle no-match case here */

In fact, if you sorted the table alphabetically, you could even use bsearch() for fast matching.

Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
7

You can only switch on integers, so this will not work.

If all you're doing is converting a string to an int, store the info in an array and look through it.

struct {
   const char *name;
   int value;
} fooMapping[] = {
     {"zero",0},
     {"at",1}
      ....
};

int foo2value(const char *name)
{
     size_t i;
     for(i = 0; i < sizeof fooMapping/sizeof fooMapping[0]; i++) {
          if(strcmp(name, fooMapping[i].name) == 0) 
             return fooMapping[i].value;

     }
    return -1;
}
nos
  • 223,662
  • 58
  • 417
  • 506
  • Would that be more efficient than the 20 if-statements I have? – darksky Oct 20 '11 at 17:09
  • @Nayefc It would probably be about the same, but the only way to know for sure is to test. It does take much less space though. – ughoavgfhw Oct 20 '11 at 17:11
  • If this grows to a lot of values, store them in sorted order and do a binary search instead of a linear search to find the match. – nos Oct 20 '11 at 17:16
  • Shouldn't the if-statement be: `if(strcmp(name, fooMapping[i].name) == 0) ` -- an i instead of 0? – darksky Oct 20 '11 at 17:35
  • It doesn't grow - it's at a constant of n = 20. Should I stick with binary? I am already using binary search for something similar. – darksky Oct 20 '11 at 17:37
1

Why not use the ? operator like so:

return
    strcmp(registerName, "zero")? 00000:
    strcmp(registerName, "at")  ? 00001:
    strcmp(registerName, "v0")  ? 00010:
    strcmp(registerName, "v1")  ? 00011:
    ...
Udo Klein
  • 6,784
  • 1
  • 36
  • 61
1

In a switch,

switch(number) {

case 1;
case 2;
case 7;
}

you are basically saying, if number = 1, then case 1. If number = 7, case 7. So what you need to do is assign each text value, in your case "zero""at""v0" and "v1", you would need to put these into an array, and in the switch statement, instead of switch(number) you would switch an integer that would correspond with the index number of whichever text you had. So if array[3] was = "v0", you would assign an integer to the index number (3) and then switch(integer). Hope this helped.

Gabriel
  • 3,039
  • 6
  • 34
  • 44
0

Since switch-case only works with numbers or single chars, I would use a tool like GNU's gperf to create a perfect hash and switch on that value (followed by a strcmp() to be certain of an exact match). That ought to give you the desired performance improvement.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485