Перамыкач Справа ў C ++

Як я магу параўнаць масіў паўкокс ў C ++ з дапамогай перамыкача-справа? Вось частка майго кода:

char[256] buff;
switch(buff){
case "Name": printf("%s",buff);
             break;
case "Number": printf("Number "%s",buff);
               break;
defaul : break
}

Я атрымліваю паведамленне пра памылку: «Памылка: колькасць пераключэння не з'яўляецца цэлым лікам» Як я магу вырашыць гэта?

1
Вы не робіце. заявы выпадку патрабуюць пастаяннага інтэгральнага значэння.
дададзена аўтар Captain Obvlious, крыніца
Мой першапачатковы каментар не зусім дакладна. Вы можаце зрабіць гэта, выкарыстоўваючы constexpr хэш-функцыі ў C ++ 11. Глядзіце мой адказ ніжэй.
дададзена аўтар Captain Obvlious, крыніца

10 адказы

Калі вам сапраўды патрэбен перамыкач заяву, вам трэба будзе канвертаваць бафф зменную ў цэлы лік. Каб зрабіць гэта, вы маглі б выкарыстоўваць хэш-функцыю або станд :: Карта .

The easy approach would be to make a std::map containing the keys you want to use in the switch associated with unique int values. You would get something like:

std::map switchmap;
...
switch(switchmap.find(std::string(buff))->second){
...
}

<�Код> станд :: Карта падыход вельмі чытаны і не павінна выклікаць шмат блытаніны.

9
дададзена
+1 Аптымальная стратэгія, хоць я асабіста аддаю перавагу выкарыстоўваць «пералічэнне».
дададзена аўтар Guilherme Nascimento, крыніца
Мне гэта падабаецца. Верагодна, за яго ўзровень хатняга задання разумення, але гэта вырашае праблему і выкарыстоўвае перамыкач заява - прыемна!
дададзена аўтар Michael Dorgan, крыніца
@MooingDuck на практыцы, так. Я абраў для сцісласці тут, каб праілюстраваць асноўную ідэю. Гэта патрабуе крыху паліроўкі перад разгортваннем.
дададзена аўтар Marc Claesen, крыніца
Верагодна, лепш за ўсё дадаць праверку, што .find() гэта не канец итератора перад разнаймення яго.
дададзена аўтар Mooing Duck, крыніца

У C ++ выпадак сцвярджэнні патрабуюць пастаяннага цэлалікавых значэнне і не можа быць выкарыстана з велічынямі, вылічаным падчас выканання. Аднак, калі вы выкарыстоўваеце C ++ 11 вы можаце выкарыстоўваць constexpr функцыі для генерацыі выпадак значэнне сынтэзаваным , выкарыстоўваючы радкі з выпадкі заяву.

Гэта выкарыстоўвае хэш-функцыю, якая прымае паказальнік на радок, і генеруе значэнне ў падчас кампіляцыі замест выканання. Калі больш чым адзін радок стварае такое ж значэнне (хэш сутыкнення), вы атрымаеце паведамленне пра памылку знаёмага аб некалькіх аператараў выпадку, выкарыстоўваючы тое ж значэнне.

constexpr unsigned int djb2Hash(const char* str, int index = 0)
{
    return !str[index] ? 0x1505 : (djb2Hash(str, index + 1) * 0x21) ^ str[index];
}

<�Код> djb2Hash функцыя можа быць затым выкарыстаны непасрэдна як у перамыкача і <�Код> выпадку заявы. Існуе адзін нюанс, аднак, хэш-функцыя можа у выніку сутыкнення падчас выканання. Верагоднасць гэтага залежыць галоўным чынам ад якасці хэш-функцыі. Рашэнне, прадстаўленае тут не спрабуе вырашыць гэтую праблему (але можа ў будучыні).

void DoSomething(const char *str)
{
    switch(djb2Hash(str))
    {
        case djb2Hash("Hello"): SayHello(); break;
        case djb2Hash("World"): SayWorld(); break;
    }
}

Гэта працуе вельмі добра, але можна лічыць непрыгожа . Вы можаце спрасціць гэта далей, абвясціўшы пэўны карыстальнік литерала, які апрацоўвае выклік функцыі хэшавання.

// Create a literal type for short-hand case strings
constexpr unsigned int operator"" _C ( const char str[], size_t size)
{
    return djb2Hash(str);
}

void DoSomething(const char *str)
{
    switch(djb2Hash(str))
    {
        case "Hello"_C: SayHello(); break;
        case "World"_C: SayWorld(); break;
    }
}

Гэта забяспечвае больш інтуітыўнае выкарыстанне радкоў у перамыкачы справаздачнасці, але таксама можа разглядацца трохі заблытанымі з-за вызначаным карыстальнікам літаральным.

[Edit: Паведамленні нататка пра час выканання хэш-калізій. Многае Прэстыжнасць R. Martinho Fernandes для прывядзення яго да майго увазе!]

3
дададзена
Кропка вы не можаце працаваць яго з яе.
дададзена аўтар R. Martinho Fernandes, крыніца
Сутыкнення падчас кампіляцыі не самая вялікая праблема. Сутыкнення падчас выканання ёсць. <�Код> DoSomething ( "CollidesWithHello") ?
дададзена аўтар R. Martinho Fernandes, крыніца
@ R.MartinhoFernandes выкарыстоўваючы станд :: Карта на крыніцу значэнне ўмовы будзе вырашыць гэтую праблему. Я не асабліва захоплены ідэяй, але пакуль гэта, здаецца, прыдатны кампраміс, каб пазбегнуць сутыкненняў падчас выканання.
дададзена аўтар Captain Obvlious, крыніца
@ R.MartinhoFernandes Так, сутыкненне, тое, што адбываецца з условнога можа адбыцца - не зусiм атрымала працаваць гэты аспект яго яшчэ. Я буду абнаўляць адказ адзначыць, што.
дададзена аўтар Captain Obvlious, крыніца
Я працаваў яго тут: stackoverflow.com/пытанні/4165131/см-ўключэнне для нон-INTEG & ZWNJ; ERS/& hellip; . Хітрасць заключаецца ў тым, што вы павінны праверыць роўнасць у выпадку з супалі радкі, выпадак "Мір" _C: калі (зЬгстр (вул, "Мір")) {SayWorld (); перапынак;} . Гэта робіць радок-перамыкач макрас, які значна больш прывабным.
дададзена аўтар redwizard792, крыніца

Вы проста не можаце выкарыстоўваць масіў як выраз у размеркавальнай канструкцыі.

3
дададзена
Так, вы можаце: асмальваецца ЬиМ [256]; Перамыкач (BUF [0]) {} ...
дададзена аўтар Michael Dorgan, крыніца
Я выкарыстоўваю масіў у размеркавальнай канструкцыі. Проста паўторна слова ваш адказ крыху і я шчаслівая з ім. Як ёсць, гэта гучыць, як любое выкарыстанне масіва на ўсіх Verboten.
дададзена аўтар Michael Dorgan, крыніца
І голас змяніўся :)
дададзена аўтар Michael Dorgan, крыніца
Як вы хочаце, адрэдагаваныя.
дададзена аўтар Paul Griffiths, крыніца
Дзякую вам, сэр :)
дададзена аўтар Paul Griffiths, крыніца
Вы ўсё яшчэ карыстаецеся прамыя сімвалы ў камутатары. Выкарыстанне масіваў і выкарыстанне элементаў масіва, не тое ж самае.
дададзена аўтар Paul Griffiths, крыніца

Вы не можаце выкарыстаць не цэлалікавых тып у размеркавальным заяве. Ваша праблема будзе патрабаваць нешта накшталт:

char buff[256];
if(!strcmp(buf, "Name") printf("%s",buff);
if(!strcmp(buf, "Number") printf("%s",buff);

Для таго, каб атрымаць вынікі, якія вы шукаеце - у асноўным кучу калі заявы замяніць выключальнік.

1
дададзена
копія паста з яго коды - выпраўлена.
дададзена аўтар Michael Dorgan, крыніца
<�Код> сімвал [256] станоўчы эфект; не з'яўляецца дапушчальным сінтаксісам.
дададзена аўтар Nik Bougalis, крыніца

Вы можаце часткова зрабіць "радок" параўнаць.

Ніжэй канкрэтна не задавальняе запыт (як C не будзе ездзіць, што поні), і гэта элегантны код, але варыяцыя на яго можа атрымаць вас праз вашыя патрэбы. Я не рэкамендую вам зрабіць гэта, калі вам навучанне C/C ++, але гэтая канструкцыя добра зарэкамендавала сябе ў абмежаванай асяроддзі праграмавання.
(Я выкарыстоўваю яго ў пас праграмавання, дзе STRLEN (бафф) == 1 або 2 і SizeOf (INT) == 2).

Let's assume sizeof(int) == 4 and strlen(buff) >= 3.

char buff[256];
// buff assignment code is TBD.
// Form a switch 4-byte key from the string "buff".
// assuming a big endian CPU.
int key = (buff[0] << 3*8) | (buff[1] << 2*8) | (buff[2] << 1*8) | (buff[3] << 0*8);
// if on a little endian machine use:
// int key = (buff[0] << 0*8) | (buff[1] << 1*8) | (buff[2] << 2*8) | (buff[3] << 3*8);
switch (key) {
 //Notice the single quote vs. double quote use of constructing case constants.
  case 'Name': printf("%s",buff);         break;
  case 'Numb': printf("Number \"%s\"",buff); break;
  default : ;
}
0
дададзена

Як кажа памылка, перамыкач працуе толькі для цэлых лікаў. Самае простае дазвол выкарыстоўваць ланцужок , калі ... інакш, калі ... тэсты.

Аднак, выкарыстоўваючы сімвал масіў, а не радкі нязручна, так як вам трэба вёрткія функцыі C-стылі, каб параўнаць іх. Я прапаную вам выкарыстоўваць зЬй :: радок замест гэтага.

std::string buff;
if (buff == "Name") {
   //deal with name
} else if (buff == "Number") {
   //deal with number
} else {
   //none of the above
}

Больш складаныя падыходы, магчыма адлюстраванне радкоў у колькасці для выкарыстання ў перамыкач або функторов для выкліку, магчыма, і можа быць больш эфектыўным, калі ў вас ёсць вялікая колькасць выпадкаў; але вы павінны атрымаць простую версію працу, перш чым турбавацца аб такіх аптымізацый.

0
дададзена

Вы не можаце выкарыстоўваць перамыкач непасрэдна для гэтай сітуацыі.

Typically, you'd want to use a std::map (or std::unordered_map) to store the action to associate with each input. You might (for example) use a std::map, and then store the addresses of functions/function objects in the map, so your final construct would be something like:

std::map funcs;
funcs["Name"] = [](std::string const &n) {std::cout <<  n;};
funcs["Number"] = [](std::string const &n) {std::cout << "Number: " << n;};

// ...
auto f = funcs[buff];
f(buff);
// or combine lookup and call: funcs[buff](buff);

Два заўвагі: па-першае, вы, верагодна, сапраўды хочаце выкарыстоўваць карта :: знайсці для другой часткі, так што вы можаце выявіць, калі/калі радок, якую вы шукаеце, няма на карце.

Па-другое, як ён стаіць, ваш код, здаецца, не мае асаблівага сэнсу - вы абодва ўключэння аматарам і раздрукоўвання аматарам 's значэнне, так (для прыклад), калі аматарам ўтрымлівае Нумар , ваш выхад будзе «Нумар Нумар». Я мяркую, што вы збіраецеся выкарыстоўваць бафф і некаторыя іншыя зменнай, якая ўтрымлівае значэнне, якое вы клапоціцеся аб.

0
дададзена

У C ++ вы можаце выкарыстоўваць перамыкач -случае толькі з цэлымі лікамі ( сімвал , Int , ...), але не з з-радкоў (< код> сімвал * )

У вашым выпадку вы павінны выкарыстоўваць, калі-то-яшчэ канструкт

if (strcmp(buff, "Name") == 0) {
    ...
} else if (...) {
    ...
}
0
дададзена

У адрозненне ад многіх іншых моў, якія дазваляюць радкі і іншыя параўнання аб'ектаў, якія будуць выкарыстоўвацца ў размеркавальным-выпадку, C ++ патрабуе, каб базавая значэнне быць цэлым лікам. Калі вы хочаце выкарыстоўваць больш складаныя тып аб'ектаў, вы павінны будзеце выкарыстоўваць, калі яшчэ-калі канструкт.

0
дададзена

Вы спрабуеце зрабіць нешта мы ўсе вельмі дорага б мы маглі, але не ў C/C ++ :) Справа ў размеркавальным заяве павінны быць цэлымі значэннямі. Адзін просты альтэрнатывай з'яўляецца пералік, якое адпавядае набору радкоў, якія вы хочаце, каб дзейнічаць далей.

0
дададзена
Мы не <�я> усе </я> хачу гэтага.
дададзена аўтар Nik Bougalis, крыніца