'switch'문을 사용하여 C의 문자열을 어떻게 비교할 수 있습니까?


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래더"를 피)을 얻을 수있는 방법은 char *무엇입니까?


"켜기"란 무엇을 의미합니까?
— kennytm

질문이 당신이 실제로하려는 (또는 요구하는) 것을 명확히 할 수 있도록 재구성하십시오.
— Šimon Tóth

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 !!?
— Niklas

2
@Niklas : 이것은 귀하의 질문에 대한 중요한 정보입니다. 질문을 업데이트하고 (가능한 경우 일부 (의사) 코드로) 수행하려는 작업을 설명 할 수 있습니까?
— Bart van Ingen Schenau

4
@Niklas : 질문을 명확히해야합니다. 어떻게 "B1"과 "B2"가 int의 특별한 경우가 될 수 있습니까?
— Edgar Bonet

1
#define A 1 #define B 2 #define C S1 #define D S2 및 이러한 값은 스위치에서 사용하고 싶은 것입니다. 너무 간단합니다 :-)
— Niklas

5
@Niklas : 정의는 문자열이 아닙니다. 정의가 숫자에 대한 것이라면 다음과 같이 스위치에서 직접 사용할 수 있습니다 switch (something) { case A: /*...*/ break; case B: /*...*/ break; }.
— Bart van Ingen Schenau

45

케이스가 많고 많은 strcmp()통화 를 작성하고 싶지 않은 경우 다음과 같이 할 수 있습니다.

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

해시 함수가 문자열의 가능한 값 집합 내에 충돌이 없는지 확인하기 만하면됩니다.


8
"해시 함수가 문자열에 대해 가능한 값 세트 내에 충돌이 없는지 확인하십시오." -알파벳에 대해 그러한 해시 함수가 존재 [a-zA-Z0-9_]합니까? 어떤 예?
— Arun

8
@ArunSaha : 분명히 그러한 문자의 임의 조합 이 아닙니다 .
— Edgar Bonet

3
고정 길이 문자열 키를 사용하는 경우 각각 고유 한 정수로 변환 할 수 있습니다. 충돌이 없습니다.
— 엔지니어

@ArcaneEngineer 음 ... 그게 문제가 해결하려는 정확한 문제가 아닙니까? 문자열 만 주어지면 함께 사용할 정수를 어떻게 고르겠습니까? "스위치 또는 if / else 래더 사용"아니면 4 자처럼 매우 짧은 것을 의미합니까?
— ebyrob

@ebyrob 나는 uint비트가 8 개의 1 바이트 ASCII로 처리되는 2 개의 64 비트와 같이 빠른 작업에서 비교할 수있는 모든 것을 의미했습니다 char. C의 해시 테이블 내에서 키 비교를 위해 이것을 얼마 전에 구현했습니다. 따라서 해싱이나 버킷이 필요하지 않습니다. 문제는 64 비트를 초과해야하는 경우에 발생합니다. 그런 다음 char전체 문자열에서 8 초의 각 세트를 반복 할 때 조건에 대한 비용을 지불 합니다. 루프를 펼치지 않는 한 키의 최대 크기를 알고 있다면. 그것은 좋은 균형을 잡는 행위입니다.
— 엔지니어

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 세트 대신 열거 형을 사용하는 것이 훨씬 더 좋지만 그렇지 않으면 최선을 다할 수 있습니다.
— Craig Ringer

증가가 올바르지 않습니다. lookuptable + i * sizeof (t_symstruct)가 lookuptable [i]와 같지 않습니다.
— asdf

@asdf 이것이 c에서 포인터 산술이 작동하는 방식입니다. sizeof는 암시 적입니다.
— ijustlovemath

20

이 작업을 수행하는 데 선호하는 방법은 해시 함수를 사용하는 것입니다 ( 여기 에서 빌림 ). 이렇게하면 char *로 작업 할 때에도 switch 문의 효율성을 활용할 수 있습니다.

#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);
    }
}

물론이 접근 방식에서는 허용되는 모든 char *에 대한 해시 값이 미리 계산되어야합니다. 나는 이것이 너무 큰 문제라고 생각하지 않습니다. 그러나 switch 문은 상관없이 고정 값에서 작동하기 때문입니다. 해시 함수를 통해 char *를 전달하고 그 결과를 출력하는 간단한 프로그램을 만들 수 있습니다. 이러한 결과는 위에서 한 것처럼 매크로를 통해 정의 할 수 있습니다.


Stack Overflow에 오신 것을 환영합니다. 당신이 보여준 것은 멋지게 제시되고 좋은 아이디어이지만… 다른 답변들과 크게 다르지는 않습니다.이 아이디어에 사소한 변형을 사용하는 몇 가지가 있습니다. 오래된 안정된 질문에 새로운 답변을 추가한다면, 좋은 새로운 정보가 있다는 것을 확신해야합니다. 그것은 대부분주의의 말입니다. 나는 이것에 대해 당신을 하향 투표하지 않을 것입니다.
— Jonathan Leffler

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 () (또는 이와 유사한)에 대한 호출을 숨기는 매크로 집합이 포함되어 있습니다. Linux에서 GCC로만 테스트했지만 다른 환경을 지원하도록 조정할 수 있다고 확신합니다.

편집 : 요청에 따라 여기에 코드 추가

다음은 포함해야하는 헤더 파일입니다.

#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;

"휴식"을 추가하는 것이 아니라 생략 할 수 있다는 사실을 강조하여 예제를 편집했습니다
— Andrea Carron

1
그게 더 좋습니다! 일치하기 위해 "sscanf"를 사용하기 전에 "regex.h"를 배웠습니다. 문자열
— 대소 문자

스위치 / 케이스와 비교할 때 얼마나 아름다운 솔루션이고 가독성이 좋으며 훨씬 더 많은 기능을 제공합니다. 감사합니다! 닫는 대괄호 뒤에 "switchs_end :"를 잊지 마세요.
— Achim

6

문자열 검색을 더 빠르게 수행 할 수있는 방법이 있습니다. 가정 : 우리는 switch 문에 대해 이야기하고 있기 때문에 런타임 동안 값이 변경되지 않는다고 가정 할 수 있습니다.

아이디어는 C stdlib의 qsort 및 bsearch를 사용하는 것입니다.

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의 대답에 추가하려면 문자열이 항상 두 문자 인 경우 두 개의 8 비트 문자에서 16 비트 int를 빌드하고 스위치 / 케이스 문이 중첩되지 않도록 스위치를 켤 수 있습니다.


을 정말로 원한다면 To add to Phimueme's answer above주석 기능을 사용하십시오. :)
— Onion-Knight

3
@Onion : MikeBrom은 현재 자신의 게시물과 자신의 질문에 대한 답변 이외의 게시물에 댓글을 달 수있는 명성이 없습니다. 즉, @Mike "위"는 신뢰할 수있는 정렬 순서가 없기 때문에 미끄 럽습니다. "... Phimueme의 답변 ..." 과 같은 답변에 연결하는 것이 더 좋습니다 (해당 답변은 지금 삭제되고 링크는 평판이 10k 이상인 사용자에게만 적합합니다).
— dmckee --- 전 중재자 새끼 고양이

3

문자열을 다른 문자열과 비교하기 위해 if-else 래더를 벗어날 수 없습니다. 일반 switch-case도 내부적으로 if-else 래더 (정수용)입니다. 문자열에 대한 switch-case 만 시뮬레이션하고 싶을 수도 있지만 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

"일반적인 switch-case조차도 내부적으로 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";
        }
    }
}

흥미 롭군. 방어적인 코딩이 부족합니다 (아마 선택에 따라). 그리고 나는 경우에 대비하여 추가 중괄호에 감탄합니다. 코드를 훨씬 더 읽기 쉽게 만듭니다 (대소 문자로 이집트 중괄호를 선호하지만).
— Dariusz

1
BTW, 케이스 레이블에 상수 표현식을 사용할 수 있습니다. case 'B'<<8+'1':제 생각에는 0x4231보다 더 명확 해집니다.
— Jens 2013 년

매크로를 사용합니다. #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
나는이 표준 C. 생각하지 않는다
— 요한 Kotlinski

2
매크로가 혼합 엔디안을 지원하도록하거나 기능은 독자를위한 연습으로 남겨집니다.

2
표준 C이지만 휴대용은 아닙니다. 멀티 바이트 문자의 바이트 순서는 '구현 종속성'이며 시스템 바이트 순서를 반영 할 필요가 없습니다. 나는 그것을 사용 한 번 태워있어 : 솔라리스 SPARC (빅 엔디안) 선 스튜디오 (12)에 비해 GNU-C 3.4을 사용하는 다른 바이트 순서에
— 패트릭 Schlüter

@tristopia 물론 당신이 맞습니다 (실제로 이와 같은 일을 시도한 후에 할 수있는 것처럼). 이것이 우리 모두가 대신 B를 사용해야하는 이유입니다.

왜 계정을 죽였습니까?

1

2 바이트 문자열이면 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

작은 엔디안과 sizeof (char) == 1이라고 가정하면 그렇게 할 수 있습니다 (이와 같은 것은 MikeBrom이 제안했습니다).

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

BE의 경우 일반화 할 수 있습니다.


2
하지마! 이로 인해 "데이터 정렬"예외가 발생할 수 있습니다. char * txt가 int의 정렬 요구 사항과 일치하는 주소를 가리키는 것은 보장되지 않습니다.
— harper

@R 그는 그것을 요구했습니다. @harper x86의 경우가 아닙니다.
— ruslik

Niklas는 x86을 요구하지 않았습니다. 그리고 빅 엔디안 사례를 언급 했으므로 x86 환경 만 다루지는 않습니다. 그래서 '
— 하퍼

또한, 멀티 바이트 문자는 반드시 머신 바이트 순서가 아닙니다. jbcreix 답변에 대한 내 의견을 참조하십시오.
— Patrick Schlüter

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

[EXPLAINED 모드]

예를 들어 : 나는 많은 메뉴를 가지고 있으며, 첫 번째 메뉴의 각 선택은 두 번째 메뉴로 이동하고 두 번째 메뉴와 세 번째 메뉴와 동일하지만 옵션이 다르므로 사용자가 끝까지 선택했음을 알 수 있습니다. 예 :

메뉴 1 : 1 ==> 메뉴 2 : 4 ==> 메뉴 3 : 2 (...) 선택은 142. 기타 경우 : 111,141,131,122 ...

해결책 : 첫 번째는 a에, 두 번째는 b에, 세 번째는 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)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.