Переключение оператора в C - PullRequest
6 голосов
/ 20 октября 2011

У меня есть следующие операторы if:

    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;

Это действительно очень долго - около 20 операторов if.Поэтому я хотел бы использовать переключатель.Как бы я преобразовал это, чтобы переключиться, когда у каждого оператора есть различное условие?

Я попробовал кое-что как код ниже, но это не работает:

int registerAddress;

switch(registerAddress) {

case 1 (strcmp(registerName, "zero")):
        regsiterAddress = 00000;
        break;
case 2 (strcmp(registerName, "at")):
        registerAddress = 00001;
        break;
}

Ответы [ 5 ]

8 голосов
/ 20 октября 2011

Вы не можете - switch операторы в C работают только на примитивных типах, а не на строках.Вы могли бы использовать, скажем, хеш-таблицу или дерево поиска для оптимизации соответствия, но только для 20 вариантов, которые могут не стоить проблем.

Что вы можете сделать, чтобы очиститьвверх по коду, создайте таблицу сопоставления:

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

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

и выполните сопоставление следующим образом:

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 */

Фактически, если вы отсортировали таблицу по алфавиту, вы могли бы даже использоватьbsearch() для быстрого сопоставления.

7 голосов
/ 20 октября 2011

Вы можете включить только целые числа, так что это не будет работать.

Если все, что вы делаете, это конвертируете строку в int, сохраняйте информацию в массиве и просматривайте ее.

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;
}
1 голос
/ 06 февраля 2013

Почему бы не использовать?оператор вроде так:

return
    strcmp(registerName, "zero")? 00000:
    strcmp(registerName, "at")  ? 00001:
    strcmp(registerName, "v0")  ? 00010:
    strcmp(registerName, "v1")  ? 00011:
    ...
1 голос
/ 20 октября 2011

В коммутаторе,

switch(number) {

case 1;
case 2;
case 7;
}

Вы в основном говорите, что если число = 1, то случай 1. Если число = 7, случай 7. Итак, вам нужно назначить каждое текстовое значение,в вашем случае "ноль" в "" v0 "и" v1 ", вам нужно было бы поместить их в массив, и в операторе switch вместо switch (число) вы бы переключили целое число, соответствующее индексуколичество текста, который у вас был.Поэтому, если array [3] was = "v0", вы должны присвоить целое число индексному номеру (3), а затем переключиться (целое число).Надеюсь, это помогло.

0 голосов
/ 20 октября 2011

Поскольку switch-case работает только с числами или одиночными символами, я бы использовал такой инструмент, как gperf в GNU, чтобы создать совершенный хэш и включить это значение (за которым следует strcmp() чтобы быть уверенным в точном совпадении).Это должно дать вам желаемое улучшение производительности.

...