Изявление Switch в C

Имам следните 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;
}

person darksky    schedule 20.10.2011    source източник
comment
Между другото, strcmp(a, b) връща нула (което се оценява като false в булев контекст), когато a е равно на b.   -  person rczajka    schedule 20.10.2011
comment
О, да - трябва да добавя '== 0'   -  person darksky    schedule 20.10.2011


Отговори (5)


Не можете да 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() за бързо съвпадение.

person Ilmari Karonen    schedule 20.10.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;
}
person nos    schedule 20.10.2011
comment
Ще бъде ли това по-ефективно от 20-те if-изявления, които имам? - person darksky; 20.10.2011
comment
@Nayefc Вероятно ще бъде приблизително същото, но единственият начин да разберете със сигурност е да тествате. Все пак отнема много по-малко място. - person ughoavgfhw; 20.10.2011
comment
Ако това нарасне до много стойности, запазете ги в сортиран ред и направете двоично търсене вместо линейно търсене, за да намерите съвпадението. - person nos; 20.10.2011
comment
Не трябва ли операторът if да бъде: if(strcmp(name, fooMapping[i].name) == 0) -- an i вместо 0? - person darksky; 20.10.2011
comment
Не расте - има константа n = 20. Трябва ли да се придържам към двоичния? Вече използвам двоично търсене за нещо подобно. - person darksky; 20.10.2011

В превключвател,

switch(number) {

case 1;
case 2;
case 7;
}

вие всъщност казвате, че ако число = 1, тогава случай 1. Ако число = 7, случай 7. Така че това, което трябва да направите, е да присвоите всяка текстова стойност, във вашия случай "нула""при""v0" и "v1" , ще трябва да ги поставите в масив и в командата switch вместо switch(number) ще превключите цяло число, което ще съответства на индексния номер на текста, който имате. Така че, ако array[3] беше = "v0", бихте присвоили цяло число на индексния номер (3) и след това switch(integer). Надявам се това да е помогнало.

person Gabriel    schedule 20.10.2011

Защо не използвате ? оператор така:

return
    strcmp(registerName, "zero")? 00000:
    strcmp(registerName, "at")  ? 00001:
    strcmp(registerName, "v0")  ? 00010:
    strcmp(registerName, "v1")  ? 00011:
    ...
person Udo Klein    schedule 05.02.2013

Тъй като switch-case работи само с числа или единични знаци, бих използвал инструмент като gperf на GNU за да създадете перфектен хеш и да включите тази стойност (последвана от strcmp(), за да сте сигурни точно съвпадение). Това трябва да ви даде желаното подобрение на производителността.

person Raymond Hettinger    schedule 20.10.2011