Як я можу порівняти рядки в C, використовуючи оператор `switch`?


84

У C є switchконструкція, яка дозволяє виконувати різні умовні гілки коду на основі тестового цілого значення, наприклад,

int a;
/* Read the value of "a" from some source, e.g. user input */
switch (a) {
  case 100:
    // Code
    break;
  case 200:
    // Code
    break;
  default:
    // Code
    break;
}

Як можна отримати однакову поведінку (тобто уникати так званої " if- elseдрабини") для рядкового значення, тобто a char *?


Що ви маєте на увазі під терміном "увімкнути"?
kennytm

Будь ласка, переформулюйте так, щоб у питанні було зрозуміло, що ви насправді намагаєтесь зробити (або просите).
Шимон Тот,

8
OP, ймовірно, хоче використовувати рядок як параметр оператора switch. Наскільки мені відомо, це неможливо.
dandan78

Відповіді:


101

Якщо ви маєте на увазі, як написати щось подібне до цього:

// switch statement
switch (string) {
  case "B1": 
    // do something
    break;
  /* more case "xxx" parts */
}

Тоді канонічним рішенням у C є використання сходів if-else:

if (strcmp(string, "B1") == 0) 
{
  // do something
} 
else if (strcmp(string, "xxx") == 0)
{
  // do something else
}
/* more else if clauses */
else /* default: */
{
}

1
Насправді проблема полягає в тому, що у мене вже є перемикач int, а в окремому випадку я маю значення "B1" і "B2", які я хочу використовувати в тому ж перемикачі. Єдиний спосіб - це якось перетворити значення "B1" і "B2" і використовувати їх як int !!?
Ніклас,

2
@Niklas: Це важлива інформація для вашого запитання. Чи можете ви оновити своє запитання та пояснити (якщо можливо за допомогою якогось (псевдо) коду), що ви намагаєтесь зробити?
Барт ван Інген Шенау,

4
@Niklas: Вам слід пояснити своє запитання: як, на землі, "B1" і "B2" можуть бути приватним випадком int?
Едгар Бонет,

1
#define A 1 #define B 2 #define C S1 #define D S2, і ці значення є тим, що я хочу використовувати у своєму комутаторі. Так просто :-)
Ніклас

5
@Niklas: Визначає, що це не рядки. Якщо визначення стосується числа, ви можете використовувати його безпосередньо у своєму комутаторі, як це switch (something) { case A: /*...*/ break; case B: /*...*/ break; }.
Барт ван Інген Шенау,

45

Якщо у вас багато випадків і ви не хочете писати тонну strcmp()дзвінків, ви можете зробити щось на зразок:

switch(my_hash_function(the_string)) {
    case HASH_B1: ...
    /* ...etc... */
}

Потрібно лише переконатися, що у вашої хеш-функції немає колізій всередині набору можливих значень для рядка.


8
"переконайтесь, що ваша хеш-функція не має зіткнень всередині набору можливих значень для рядка." - Чи існує така хеш-функція для алфавіту [a-zA-Z0-9_]? Будь-який приклад?
Арун

8
@ArunSaha: Очевидно, не для довільних комбінацій таких символів.
Едгар Бонет

3
Якщо ви використовуєте ключі рядків фіксованої довжини, ви можете перетворити їх кожен в унікальні цілі числа; ніяких зіткнень неможливо.
інженер

@ArcaneEngineer Гм ... чи не саме ця проблема намагається вирішити питання? Як, лише з урахуванням рядка, ви вибрали б ціле число, щоб відповідати йому? "використовувати перемикач або якщо / ще драбину" Або, можливо, ви маєте на увазі щось дуже коротке, наприклад, 4 символи?
ебіроб

@ebyrob Я мав на увазі все, що можна порівняти в швидкій операції, наприклад, 2 64-бітні uints, біти яких розглядаються як 8 1-байтових ASCII char. Я реалізував це деякий час тому для порівняння ключів у хеш-таблиці в C. Таким чином, ви викорінюєте необхідність будь-якого хешування або сегментів. Проблема полягає в тому, що вам потрібно перевищити 64 біти; тоді ви сплачуєте вартість умовних умов, коли ви перебираєте кожен набір 8 charс у повному рядку. Якщо ви не розгортаєте цикл, якщо ви знаєте максимальний розмір ключів. Це чудова рівновага.
інженер

39

Це неможливо зробити в C. Існує багато різних підходів. Зазвичай найпростішим є визначення набору констант, що представляють ваші рядки, і пошук по рядку, щоб отримати константу:

#define BADKEY -1
#define A1 1
#define A2 2
#define B1 3
#define B2 4

typedef struct { char *key; int val; } t_symstruct;

static t_symstruct lookuptable[] = {
    { "A1", A1 }, { "A2", A2 }, { "B1", B1 }, { "B2", B2 }
};

#define NKEYS (sizeof(lookuptable)/sizeof(t_symstruct))

int keyfromstring(char *key)
{
    int i;
    for (i=0; i < NKEYS; i++) {
        t_symstruct *sym = lookuptable[i];
        if (strcmp(sym->key, key) == 0)
            return sym->val;
    }
    return BADKEY;
}

/* ... */
switch (keyfromstring(somestring)) {
case A1: /* ... */ break;
case A2: /* ... */ break;
case B1: /* ... */ break;
case B2: /* ... */ break;
case BADKEY: /* handle failed lookup */
}

Звичайно, є більш ефективні способи зробити це. Якщо ваші ключі сортуються, ви можете скористатися двійковим пошуком. Ви також можете використовувати хеш-таблицю. Ці речі змінюють ваші показники за рахунок обслуговування.


7
Набагато приємніше використовувати перелічення замість набору #defines для ключів, але в іншому - про найкраще, що ви можете зробити.
Крейг Рінгер,

збільшення невірно. lookuptable + i * sizeof (t_symstruct) не дорівнює lookuptable [i].
asdf

@asdf Ось як працює арифметика покажчика в c. Розмір неявний.
ijustlovemath

20

Моїм найкращим методом для цього є хеш-функція (запозичена звідси ). Це дозволяє використовувати ефективність оператора switch навіть під час роботи з символами char *:

#include "stdio.h"

#define LS 5863588
#define CD 5863276
#define MKDIR 210720772860
#define PWD 193502992

const unsigned long hash(const char *str) {
    unsigned long hash = 5381;  
    int c;

    while ((c = *str++))
        hash = ((hash << 5) + hash) + c;
    return hash;
}

int main(int argc, char *argv[]) {
    char *p_command = argv[1];
    switch(hash(p_command)) {
    case LS:
        printf("Running ls...\n");
        break;
    case CD:
        printf("Running cd...\n");
        break;
    case MKDIR:
        printf("Running mkdir...\n");
        break;
    case PWD:
        printf("Running pwd...\n");
        break;
    default:
        printf("[ERROR] '%s' is not a valid command.\n", p_command);
    }
}

Звичайно, цей підхід вимагає, щоб хеш-значення для всіх можливих прийнятих символів * були розраховані заздалегідь. Я не думаю, що це надто велика проблема; однак, оскільки оператор switch працює з фіксованими значеннями незалежно. Можна створити просту програму для передачі символів char * через хеш-функцію та виведення результатів. Потім ці результати можна визначити за допомогою макросів, як я це робив вище.


Ласкаво просимо до Stack Overflow. Те, що ви показали, чудово представлене і гарна ідея, але ... але це не все суттєво відрізняється від деяких інших відповідей - є кілька, які використовують незначні варіанти цієї ідеї. Якщо ви додаєте нову відповідь до старого стабільного питання, ви повинні бути дуже впевнені, що маєте хорошу нову інформацію. Це переважно слово обережності; Я, звичайно, не збираюся вас голосувати за це.
Джонатан Леффлер

16

Я думаю, що найкращий спосіб зробити це - відокремити "розпізнавання" від функціональності:

struct stringcase { char* string; void (*func)(void); };

void funcB1();
void funcAzA();

stringcase cases [] = 
{ { "B1", funcB1 }
, { "AzA", funcAzA }
};

void myswitch( char* token ) {
  for( stringcases* pCase = cases
     ; pCase != cases + sizeof( cases ) / sizeof( cases[0] )
     ; pCase++ )
  {
    if( 0 == strcmp( pCase->string, token ) ) {
       (*pCase->func)();
       break;
    }
  }

}

8

Я опублікував файл заголовка для здійснення перемикання на рядки в C. Він містить набір макросів, які приховують виклик strcmp () (або подібний), щоб імітувати поведінку, подібну до перемикача. Я протестував його лише на GCC в Linux, але я впевнений, що його можна адаптувати для підтримки інших середовищ.

РЕДАГУВАТИ: додано сюди код за запитом

Це файл заголовка, який ви повинні включити:

#ifndef __SWITCHS_H__
#define __SWITCHS_H__

#include <string.h>
#include <regex.h>
#include <stdbool.h>

/** Begin a switch for the string x */
#define switchs(x) \
    { char *__sw = (x); bool __done = false; bool __cont = false; \
        regex_t __regex; regcomp(&__regex, ".*", 0); do {

/** Check if the string matches the cases argument (case sensitive) */
#define cases(x)    } if ( __cont || !strcmp ( __sw, x ) ) \
                        { __done = true; __cont = true;

/** Check if the string matches the icases argument (case insensitive) */
#define icases(x)    } if ( __cont || !strcasecmp ( __sw, x ) ) { \
                        __done = true; __cont = true;

/** Check if the string matches the specified regular expression using regcomp(3) */
#define cases_re(x,flags) } regfree ( &__regex ); if ( __cont || ( \
                              0 == regcomp ( &__regex, x, flags ) && \
                              0 == regexec ( &__regex, __sw, 0, NULL, 0 ) ) ) { \
                                __done = true; __cont = true;

/** Default behaviour */
#define defaults    } if ( !__done || __cont ) {

/** Close the switchs */
#define switchs_end } while ( 0 ); regfree(&__regex); }

#endif // __SWITCHS_H__

І ось як ви ним користуєтесь:

switchs(argv[1]) {
    cases("foo")
    cases("bar")
        printf("foo or bar (case sensitive)\n");
        break;

    icases("pi")
        printf("pi or Pi or pI or PI (case insensitive)\n");
        break;

    cases_re("^D.*",0)
        printf("Something that start with D (case sensitive)\n");
        break;

    cases_re("^E.*",REG_ICASE)
        printf("Something that start with E (case insensitive)\n");
        break;

    cases("1")
        printf("1\n");
        // break omitted on purpose

    cases("2")
        printf("2 (or 1)\n");
        break;

    defaults
        printf("No match\n");
        break;
} switchs_end;

Я відредагував приклад не додавши "перерву", а виділивши той факт, що ви можете його опустити
Андреа Каррон

1
це приємніше! Перш ніж я використовую "sscanf" для збігу, вивчив "regex.h", що надзвичайно стосується випадків рядків :)
LinconFive

Яке гарне рішення, добре читається та набагато більше функціональних можливостей порівняно з вимикачем / корпусом - Дякую! Не забудьте "switchs_end:" після закриття дужки.
Ахім,

6

Існує спосіб швидшого пошуку рядків. Припущення: оскільки ми говоримо про оператор switch, я можу припустити, що значення не будуть змінюватися під час виконання.

Ідея полягає у використанні qsort та bsearch C stdlib.

Я буду працювати над кодом xtofl.

struct stringcase { char* string; void (*func)(void); };

void funcB1();
void funcAzA();

struct stringcase cases [] = 
{ { "B1", funcB1 }
, { "AzA", funcAzA }
};

struct stringcase work_cases* = NULL;
int work_cases_cnt = 0;

// prepare the data for searching
void prepare() {
  // allocate the work_cases and copy cases values from it to work_cases
  qsort( cases, i, sizeof( struct stringcase ), stringcase_cmp );
}

// comparator function
int stringcase_cmp( const void *p1, const void *p2 )
{
  return strcasecmp( ((struct stringcase*)p1)->string, ((struct stringcase*)p2)->string);
}

// perform the switching
void myswitch( char* token ) {
  struct stringcase val;
  val.string=token;
  void* strptr = bsearch( &val, work_cases, work_cases_cnt, sizeof( struct stringcase), stringcase_cmp );
  if (strptr) {
    struct stringcase* foundVal = (struct stringcase*)strptr;
    (*foundVal->func)();
    return OK;
  }
  return NOT_FOUND;
}

6

Щоб додати до відповіді Phimueme вище, якщо у вашому рядку завжди два символи, ви можете побудувати 16-розрядний int з двох 8-розрядних символів - і ввімкнути його (щоб уникнути вкладених операторів switch / case).


Якщо ви справді бажаєте To add to Phimueme's answer above, тоді сміливо використовуйте функцію коментарів. :)
Onion-Knight

3
@Onion: Ви зауважите, що в даний час MikeBrom не має репутації коментувати інші публікації, крім своїх власних, та відповіді на власні запитання. Тим не менш, @Mike "вгорі" слизький в SO, оскільки немає надійного порядку сортування. Краще посилатись на відповідь типу "... у відповіді Фімуме ..." (хоча ця відповідь видаляється зараз, і посилання корисне лише для користувача з репутацією понад 10 тис .).
dmckee --- кошеня екс-модератора

3

Ми не можемо вийти зі сходів if-else, щоб порівняти рядок з іншими. Навіть звичайний комутатор також є внутрішньою драбиною if-else (для цілих чисел). Ми можемо лише хотіти імітувати комутатор для рядка, але ніколи не можемо замінити сходи if-else. Найкращий з алгоритмів порівняння рядків не може уникнути використання функції strcmp. Засіб порівняння символів за символами, поки не буде знайдено невідповідність. Тож використання сходів if-else та strcmp неминуче.

ДЕМО

І ось найпростіші макроси для імітації корпусу комутатора для рядків.

#ifndef SWITCH_CASE_INIT
#define SWITCH_CASE_INIT
    #define SWITCH(X)   for (char* __switch_p__ = X, int __switch_next__=1 ; __switch_p__ ; __switch_p__=0, __switch_next__=1) { {
    #define CASE(X)         } if (!__switch_next__ || !(__switch_next__ = strcmp(__switch_p__, X))) {
    #define DEFAULT         } {
    #define END         }}
#endif

І ви можете використовувати їх як

char* str = "def";

SWITCH (str)
    CASE ("abc")
        printf ("in abc\n");
        break;
    CASE ("def")              // Notice: 'break;' statement missing so the control rolls through subsequent CASE's until DEFAULT 
        printf("in def\n");
    CASE ("ghi")
        printf ("in ghi\n");
    DEFAULT
        printf("in DEFAULT\n");
END

Вихід:

in def
in ghi
in DEFAULT

Нижче вкладено використання SWITCH:

char* str = "def";
char* str1 = "xyz";

SWITCH (str)
    CASE ("abc")
        printf ("in abc\n");
        break;
    CASE ("def")                                
        printf("in def\n");
        SWITCH (str1)                           // <== Notice: Nested SWITCH
            CASE ("uvw")
                printf("in def => uvw\n");
                break;
            CASE ("xyz")
                printf("in def => xyz\n");
                break;
            DEFAULT
                printf("in def => DEFAULT\n");
        END
    CASE ("ghi")
        printf ("in ghi\n");
    DEFAULT
        printf("in DEFAULT\n");
END

Вихід:

in def
in def => xyz
in ghi
in DEFAULT

Ось зворотний рядок SWITCH, де ви можете використовувати змінну (а не константу) у реченні CASE:

char* str2 = "def";
char* str3 = "ghi";

SWITCH ("ghi")                      // <== Notice: Use of variables and reverse string SWITCH.
    CASE (str1)
        printf ("in str1\n");
        break;
    CASE (str2)                     
        printf ("in str2\n");
        break;
    CASE (str3)                     
        printf ("in str3\n");
        break;
    DEFAULT
        printf("in DEFAULT\n");
END

Вихід:

in str3

"Навіть звичайний комутатор також є внутрішньою драбиною if-else (для цілих чисел)", що не відповідає дійсності. Якщо можливо, компілятор створить таблицю переходів, яка буде набагато ефективнішою. Дивіться stackoverflow.com/a/14067661/4990392
Дада

2

Зазвичай я це роблю.

void order_plane(const char *p)
{
    switch ((*p) * 256 + *(p+1))
    {
        case 0x4231 : /* B1 */
        {
           printf("Yes, order this bomber.  It's a blast.\n");
           break;
        }

        case 0x5354 : /* ST */
        {
            printf("Nah.  I just can't see this one.\n");
            break;
        }

        default :
        {
            printf("Not today.  Can I interest you in a crate of SAMs?\n";
        }
    }
}

Цікаво. Не вистачає (можливо, на вибір) захисного кодування. І я захоплююся додатковими брекетами на випадок. Робить код набагато читабельнішим (хоча я віддаю перевагу єгипетським фігурним дужкам для випадку).
Даріуш,

1
До речі, ви можете використовувати константні вирази у мітках регістрів. case 'B'<<8+'1':я б зрозумів це, я думаю, ніж 0x4231.
Йенс

Я б використав макрос. #define twochar(a) (((uint16_t)a[1]<<8)|a[0])
v7d8dpo4,

1

Ось як ви це робите. Ні, не дуже.

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>


 #define p_ntohl(u) ({const uint32_t Q=0xFF000000;       \
                     uint32_t S=(uint32_t)(u);           \
                   (*(uint8_t*)&Q)?S:                    \
                   ( (S<<24)|                            \
                     ((S<<8)&0x00FF0000)|                \
                     ((S>>8)&0x0000FF00)|                \
                     ((S>>24)&0xFF) );  })

main (void)
{
    uint32_t s[0x40]; 
    assert((unsigned char)1 == (unsigned char)(257));
    memset(s, 0, sizeof(s));
    fgets((char*)s, sizeof(s), stdin);

    switch (p_ntohl(s[0])) {
        case 'open':
        case 'read':
        case 'seek':
            puts("ok");
            break;
        case 'rm\n\0':
            puts("not authorized");
            break;
        default:
            puts("unrecognized command");  
    }
    return 0;
}

3
Я не думаю, що це стандартний С.
Йохан Котлінський

2
Макрос підтримує змішану ендіанність або функцію, як вправу для читача.

2
Це стандарт C, але не портативний. Порядок байтів багатобайтового символу є "залежним від реалізації" і не повинен відображати порядок байтів машин. Я використав це один раз і згорів: на Solaris SPARC (big endian) GNU-C 3.4 використовує інший порядок байтів, ніж Sunstudio 12.
Патрік Шлютер,

@tristopia Ви, звичайно, маєте рацію (наскільки це можливо, після спроби зробити щось подібне по-справжньому). Ось чому нам слід використовувати всі замість B.

Чому ви вбили свій рахунок?

1

Якщо це двобайтовий рядок, ви можете зробити щось на зразок цього конкретного прикладу, коли я вмикаю коди мови ISO639-2.

    LANIDX_TYPE LanCodeToIdx(const char* Lan)
    {
      if(Lan)
        switch(Lan[0]) {
          case 'A':   switch(Lan[1]) {
                        case 'N': return LANIDX_AN;
                        case 'R': return LANIDX_AR;
                      }
                      break;
          case 'B':   switch(Lan[1]) {
                        case 'E': return LANIDX_BE;
                        case 'G': return LANIDX_BG;
                        case 'N': return LANIDX_BN;
                        case 'R': return LANIDX_BR;
                        case 'S': return LANIDX_BS;
                      }
                      break;
          case 'C':   switch(Lan[1]) {
                        case 'A': return LANIDX_CA;
                        case 'C': return LANIDX_CO;
                        case 'S': return LANIDX_CS;
                        case 'Y': return LANIDX_CY;
                      }
                      break;
          case 'D':   switch(Lan[1]) {
                        case 'A': return LANIDX_DA;
                        case 'E': return LANIDX_DE;
                      }
                      break;
          case 'E':   switch(Lan[1]) {
                        case 'L': return LANIDX_EL;
                        case 'N': return LANIDX_EN;
                        case 'O': return LANIDX_EO;
                        case 'S': return LANIDX_ES;
                        case 'T': return LANIDX_ET;
                        case 'U': return LANIDX_EU;
                      }
                      break;
          case 'F':   switch(Lan[1]) {
                        case 'A': return LANIDX_FA;
                        case 'I': return LANIDX_FI;
                        case 'O': return LANIDX_FO;
                        case 'R': return LANIDX_FR;
                        case 'Y': return LANIDX_FY;
                      }
                      break;
          case 'G':   switch(Lan[1]) {
                        case 'A': return LANIDX_GA;
                        case 'D': return LANIDX_GD;
                        case 'L': return LANIDX_GL;
                        case 'V': return LANIDX_GV;
                      }
                      break;
          case 'H':   switch(Lan[1]) {
                        case 'E': return LANIDX_HE;
                        case 'I': return LANIDX_HI;
                        case 'R': return LANIDX_HR;
                        case 'U': return LANIDX_HU;
                      }
                      break;
          case 'I':   switch(Lan[1]) {
                        case 'S': return LANIDX_IS;
                        case 'T': return LANIDX_IT;
                      }
                      break;
          case 'J':   switch(Lan[1]) {
                        case 'A': return LANIDX_JA;
                      }
                      break;
          case 'K':   switch(Lan[1]) {
                        case 'O': return LANIDX_KO;
                      }
                      break;
          case 'L':   switch(Lan[1]) {
                        case 'A': return LANIDX_LA;
                        case 'B': return LANIDX_LB;
                        case 'I': return LANIDX_LI;
                        case 'T': return LANIDX_LT;
                        case 'V': return LANIDX_LV;
                      }
                      break;
          case 'M':   switch(Lan[1]) {
                        case 'K': return LANIDX_MK;
                        case 'T': return LANIDX_MT;
                      }
                      break;
          case 'N':   switch(Lan[1]) {
                        case 'L': return LANIDX_NL;
                        case 'O': return LANIDX_NO;
                      }
                      break;
          case 'O':   switch(Lan[1]) {
                        case 'C': return LANIDX_OC;
                      }
                      break;
          case 'P':   switch(Lan[1]) {
                        case 'L': return LANIDX_PL;
                        case 'T': return LANIDX_PT;
                      }
                      break;
          case 'R':   switch(Lan[1]) {
                        case 'M': return LANIDX_RM;
                        case 'O': return LANIDX_RO;
                        case 'U': return LANIDX_RU;
                      }
                      break;
          case 'S':   switch(Lan[1]) {
                        case 'C': return LANIDX_SC;
                        case 'K': return LANIDX_SK;
                        case 'L': return LANIDX_SL;
                        case 'Q': return LANIDX_SQ;
                        case 'R': return LANIDX_SR;
                        case 'V': return LANIDX_SV;
                        case 'W': return LANIDX_SW;
                      }
                      break;
          case 'T':   switch(Lan[1]) {
                        case 'R': return LANIDX_TR;
                      }
                      break;
          case 'U':   switch(Lan[1]) {
                        case 'K': return LANIDX_UK;
                        case 'N': return LANIDX_UN;
                      }
                      break;
          case 'W':   switch(Lan[1]) {
                        case 'A': return LANIDX_WA;
                      }
                      break;
          case 'Z':   switch(Lan[1]) {
                        case 'H': return LANIDX_ZH;
                      }
                      break;
        }
      return LANIDX_UNDEFINED;
    }

LANIDX_ * - це постійні цілі числа, що використовуються для індексації в масивах.


0

Припускаючи невелику ендіанність та розмір (char) == 1, ви могли б це зробити (щось подібне запропонував MikeBrom).

char* txt = "B1";
int tst = *(int*)txt;
if ((tst & 0x00FFFFFF) == '1B')
    printf("B1!\n");

Це може бути узагальнено для випадку BE.


2
Не робіть цього! Це може спричинити виняток "вирівнювання даних". Не гарантується, що char * txt вказує на адресу, яка відповідає вимогам вирівнювання int.
харпер

@R він про це просив. @harper це не так для x86.
ruslik

Ніклас не просив x86. І оскільки ви згадали про великий ендіанський випадок, ви не займаєтесь виключно середовищем x86. Так що '
Харпер

Крім того, багатобайтові символи не обов'язково в машинному порядку байтів. Дивіться мій коментар до відповіді jbcreix.
Патрік Шлютер,

0

Покажчики функцій - чудовий спосіб зробити це, наприклад

result = switchFunction(someStringKey); //result is an optional return value

... це викликає функцію, яку ви встановили за допомогою рядкового ключа (одна функція в кожному випадку):

setSwitchFunction("foo", fooFunc);
setSwitchFunction("bar", barFunc);

Використовуйте вже існуючу реалізацію хеш-карти / таблиці / словника, таку як khash, поверніть цей покажчик на функцію всередині switchFunction()і виконайте його (або просто поверніть його switchFunction()та виконайте самостійно). Якщо реалізація карти цього не зберігає, просто використовуйте uint64_tзамість цього, який ви відповідно приводите до покажчика.


@ eri0o Якщо ви вважали це гідним, чому б не підтримати його? Оригінального прихильника давно немає.
Інженер,

-2

Привіт, це простий і швидкий спосіб, якщо у вас є такий випадок:

[ШВИДКИЙ режим]

int concated;
char ABC[4]="";int a=1,b=4,c=2;            //char[] Initializing
ABC<-sprintf(ABC,"%d%d%d",a,b,c);          //without space between %d%d%d
printf("%s",ABC);                          //value as char[] is =142
concated=atoi(ABC);                        //result is 142 as int, not 1,4,2 (separeted)

//now use switch case on 142 as an integer and all possible cases

[ПОЯСНЕНИЙ режим]

наприклад: у мене багато меню, кожен вибір у 1-му меню виводить вас у 2-е меню, те саме, що у 2-му та 3-му меню. але Параметри різні, щоб ви знали, що користувач вибрав остаточно. приклад:

меню 1: 1 ==> меню 2: 4 ==> меню 3: 2 (...) вибір - 142. інші випадки: 111,141,131,122 ...

розчин: зберігати перше 1-е в a, 2-е в b, 3-е на c. a = 1, b = 4, c = 2

 char ABC[4]="";
 ABC<-sprintf(ABC,"%d%d%d",a,b,c);              //without space between %d%d%d
 printf("%s",ABC);                              //value as char[]=142

      //now you want to recover your value(142) from char[] to int as  int value 142

 concated=atoi(ABC);                            //result is 142 as int, not 1,4,2 (separeted)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.