¿Cómo puedo comparar cadenas en C usando una instrucción "switch"?

84

En C hay una switchconstrucción que permite ejecutar diferentes ramas condicionales de código basadas en un valor entero de prueba, por ejemplo,

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

¿Cómo es posible obtener el mismo comportamiento (es decir, evitar el llamado " if- elseescalera") para un valor de cadena, es decir, a char *?

Niklas
fuente
¿Qué quieres decir con "encender"?
kennytm
Reformule de modo que la pregunta aclare lo que está intentando hacer (o preguntando).
Šimon Tóth
8
El OP probablemente quiera usar una cadena como parámetro de una declaración de cambio. Hasta donde yo sé, esto no es posible.
dandan78

Respuestas:

101

Si te refieres a cómo escribir algo similar a esto:

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

Entonces, la solución canónica en C es usar una escalera if-else:

if (strcmp(string, "B1") == 0) 
{
  // do something
} 
else if (strcmp(string, "xxx") == 0)
{
  // do something else
}
/* more else if clauses */
else /* default: */
{
}
Bart van Ingen Schenau
fuente
1
En realidad, el problema es que ya tengo un interruptor en int y en un caso especial tengo el valor "B1" y "B2" que quiero usar en el mismo interruptor. La única forma es convertir de alguna manera los valores "B1" y "B2" y usarlos como int !!?
Niklas
2
@Niklas: Esta es información importante para tu pregunta. ¿Puede actualizar su pregunta y explicar (si es posible con algún (pseudo) código) lo que está tratando de hacer?
Bart van Ingen Schenau
4
@Niklas: Deberías aclarar tu pregunta: ¿cómo diablos podrían "B1" y "B2" ser un caso especial de un int?
Edgar Bonet
1
#define A 1 #define B 2 #define C S1 #define D S2 y estos valores son los que quiero usar en mi switch. Tan simple :-)
Niklas
5
@Niklas: las definiciones no son cadenas. Si la definición es para un número, puede usarlo directamente en su conmutador de esta manera switch (something) { case A: /*...*/ break; case B: /*...*/ break; }.
Bart van Ingen Schenau
45

Si tiene muchos casos y no quiere escribir un montón de strcmp()llamadas, puede hacer algo como:

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

Solo debe asegurarse de que su función hash no tenga colisiones dentro del conjunto de valores posibles para la cadena.

Edgar Bonet
fuente
8
"asegúrese de que su función hash no tenga colisiones dentro del conjunto de valores posibles para la cadena". - ¿Existe tal función hash para el alfabeto [a-zA-Z0-9_]? ¿Algún ejemplo?
Arun
8
@ArunSaha: Obviamente no para combinaciones arbitrarias de tales caracteres.
Edgar Bonet
3
Si usa claves de cadena de longitud fija, puede convertirlas cada una en enteros únicos; no es posible colisiones.
Ingeniero
@ArcaneEngineer Um ... ¿no es ese el problema exacto que la pregunta está tratando de resolver? ¿Cómo, dada solo la cadena, elegirías un número entero para acompañarlo? "usa un interruptor o escalera if / else" ¿O quizás te refieres a algo muy corto como 4 caracteres?
ebyrob
@ebyrob Me refería a cualquier cosa comparable en una operación rápida, como 2 s de 64 bits uintcuyos bits se tratan como 8 ASCII de 1 byte char. Implementé esto hace un tiempo, para comparaciones de claves dentro de una tabla hash en C. De esta manera, erradica la necesidad de cualquier hash o cubos. El problema surge cuando es necesario superar los 64 bits; luego paga el costo de los condicionales a medida que recorre cada conjunto de 8 chars en la cadena completa. A menos que desenrolle el bucle, si conoce el tamaño máximo de las teclas. Es un buen acto de equilibrio.
Ingeniero
39

No hay forma de hacer esto en C. Hay muchos enfoques diferentes. Normalmente, lo más simple es definir un conjunto de constantes que representen sus cadenas y hacer una búsqueda por cadena para obtener la constante:

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

Por supuesto, existen formas más eficientes de hacer esto. Si mantiene sus claves ordenadas, puede utilizar una búsqueda binaria. También podrías usar una tabla hash. Estas cosas cambian su rendimiento a expensas del mantenimiento.

pedestal
fuente
7
Es mucho más agradable usar una enumeración en lugar de un conjunto de #defines para las claves, pero por lo demás es lo mejor que puede hacer.
Craig Ringer
el incremento es incorrecto. lookuptable + i * sizeof (t_symstruct) no es igual a lookuptable [i].
asdf
@asdf Así es como funciona la aritmética de punteros en c. El tamaño de está implícito.
ijustlovemath
20

Mi método preferido para hacer esto es a través de una función hash (tomada de aquí ). Esto le permite utilizar la eficiencia de una declaración de cambio incluso cuando se trabaja con 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);
    }
}

Por supuesto, este enfoque requiere que los valores hash para todos los posibles caracteres aceptados * se calculen de antemano. No creo que esto sea un gran problema; sin embargo, dado que la instrucción switch opera en valores fijos independientemente. Se puede hacer un programa simple para pasar char * a través de la función hash y generar sus resultados. Estos resultados se pueden definir a través de macros como lo hice anteriormente.

Matthew Rasa
fuente
Bienvenido a Stack Overflow. Lo que ha mostrado está muy bien presentado y es una buena idea, pero ... pero no es tan distintivamente diferente de algunas de las otras respuestas, hay varias que usan variantes menores en esta idea. Si agrega una nueva respuesta a una pregunta estable anterior, debe estar muy seguro de que tiene buena información nueva. Eso es principalmente una palabra de precaución; Ciertamente no voy a rechazarlo por esto.
Jonathan Leffler
16

Creo que la mejor manera de hacer esto es separar el 'reconocimiento' de la funcionalidad:

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

}
xtofl
fuente
8

He publicado un archivo de encabezado para realizar el cambio en las cadenas en C. Contiene un conjunto de macro que oculta la llamada al strcmp () (o similar) para imitar un comportamiento similar al de un interruptor. Lo he probado solo con GCC en Linux, pero estoy bastante seguro de que se puede adaptar para admitir otro entorno.

EDITAR: agregó el código aquí, según lo solicitado

Este es el archivo de encabezado que debe incluir:

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

Y así es como lo usas:

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
fuente
Edité el ejemplo no agregando un "descanso", sino resaltando el hecho de que puedes omitirlo
Andrea Carron
1
eso es mejor! Antes de usar "sscanf" para hacer coincidir, aprendí "regex.h", que tiene mucho que ver con casos de cadenas :)
LinconFive
Qué hermosa solución, buena legibilidad y mucha más funcionalidad en comparación con un interruptor / carcasa. ¡Gracias! No olvide el "switchs_end:" después de cerrar el corchete.
Achim
6

Hay una forma de realizar la búsqueda de cadenas más rápido. Supuestos: dado que estamos hablando de una declaración de cambio, puedo asumir que los valores no cambiarán durante el tiempo de ejecución.

La idea es utilizar qsort y bsearch de C stdlib.

Estaré trabajando en el código de 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;
}
Dariusz
fuente
6

Para agregar a la respuesta de Phimueme anterior, si su cadena siempre tiene dos caracteres, entonces puede construir un int de 16 bits a partir de los dos caracteres de 8 bits, y activarlo (para evitar declaraciones anidadas de cambio / caso).

MikeBrom
fuente
Si realmente lo desea To add to Phimueme's answer above, no dude en utilizar la función de comentario. :)
Onion-Knight
3
@Onion: Notarás que MikeBrom no tiene actualmente la reputación de comentar publicaciones que no sean las suyas y responder a sus propias preguntas. Dicho esto, @Mike "arriba" es resbaladizo en SO, porque no hay un orden de clasificación confiable. Es mejor enlazar a la respuesta como "... en la respuesta de Phimueme ..." (aunque esa respuesta se eliminó ahora, y el enlace solo es bueno para usuarios con más de 10k de reputación).
dmckee --- ex-moderador gatito
3

No podemos escapar de la escalera if-else para comparar una cadena con otras. Incluso el switch-case normal también es una escalera if-else (para enteros) internamente. Es posible que solo deseemos simular el caso del interruptor para cadena, pero nunca podemos reemplazar la escalera if-else. El mejor de los algoritmos para la comparación de cadenas no puede escapar del uso de la función strcmp. Significa comparar carácter por carácter hasta que se encuentre una diferencia. Por lo tanto, el uso de escalera if-else y strcmp es inevitable.

MANIFESTACIÓN

Y aquí están las macros más simples para simular el caso del interruptor para cadenas.

#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

Y puedes usarlos como

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

Salida:

in def
in ghi
in DEFAULT

A continuación se muestra el uso de SWITCH anidado:

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

Salida:

in def
in def => xyz
in ghi
in DEFAULT

Aquí está SWITCH de cadena inversa, donde puede usar una variable (en lugar de una constante) en la cláusula 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

Salida:

in str3
Ramu
fuente
"Incluso el caso de cambio normal también es una escalera if-else (para enteros) internamente", eso no es cierto. Si es posible, el compilador generará una tabla de salto, que será mucho más eficiente. Ver stackoverflow.com/a/14067661/4990392
Dada
2

Generalmente así es como lo hago.

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";
        }
    }
}
EvilTeach
fuente
Interesante. Carece (probablemente por elección) de codificación defensiva. Y admiro los aparatos adicionales por si acaso. Hace que el código sea mucho más legible (aunque prefiero llaves egipcias para el caso).
Dariusz
1
Por cierto, puede usar expresiones constantes en etiquetas de caso. case 'B'<<8+'1':aclararía esto, creo, que 0x4231.
Jens
Usaría una macro. #define twochar(a) (((uint16_t)a[1]<<8)|a[0])
v7d8dpo4
1

Así es como lo haces. No en realidad no.

#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;
}
user14554
fuente
3
No creo que esto es estándar C.
Johan Kotlinski
2
Hacer que la macro apoye la endianidad mixta, o una función se deja como ejercicio para el lector.
2
Es estándar C, pero no portátil. El orden de bytes del carácter multibyte es 'dependiente de la implementación' y no necesita reflejar el orden de bytes de las máquinas. Lo usé una vez y me quemé: en Solaris SPARC (big endian) GNU-C 3.4 usa un orden de bytes diferente al de Sunstudio 12.
Patrick Schlüter
@tristopia Tienes razón, por supuesto (todo lo que uno puede tener después de intentar hacer algo como esto de verdad). Es por eso que todos deberíamos usar B en su lugar.
¿Por qué mataste tu cuenta?
1

Si es una cadena de 2 bytes, puede hacer algo como en este ejemplo concreto donde enciendo los códigos de idioma 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_ * son enteros constantes que se utilizan para indexar en matrices.

Patrick Schlüter
fuente
0

Suponiendo poco endianness y sizeof (char) == 1, podría hacer eso (algo como esto fue sugerido por MikeBrom).

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

Podría generalizarse para el caso BE.

ruslik
fuente
2
¡No hagas eso! Esto puede provocar una excepción de "alineación de datos". No se garantiza que char * txt apunte a una dirección que coincida con los requisitos de alineación de int.
harper
@R pidió eso. @harper no es el caso de x86.
ruslik
Niklas no pidió x86. Y como mencionaste el caso del big endian, no te diriges exclusivamente al entorno x86. Así que '
harper
Además, los caracteres multibyte no están necesariamente en orden de bytes de máquina. Vea mi comentario a la respuesta de jbcreix.
Patrick Schlüter
0

Los punteros de función son una excelente manera de hacer esto, p. Ej.

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

... esto llama a una función que ha establecido mediante la tecla de cadena (una función por caso):

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

Use una implementación de hashmap / tabla / diccionario preexistente como khash, devuelva ese puntero a una función dentro de switchFunction()y ejecútelo (o simplemente devuélvalo switchFunction()y ejecútelo usted mismo). Si la implementación del mapa no almacena eso, simplemente use un uint64_ten su lugar que emite en consecuencia a un puntero.

Ingeniero
fuente
@ eri0o Si pensabas que era decente, ¿por qué no votas a favor? El votante negativo original ya no está.
Ingeniero
-2

Hola, esta es la forma fácil y rápida si tienes este caso:

[Modo rápido]

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

[Modo EXPLICADO]

por ejemplo: tengo muchos menús, cada opción en el primer menú te lleva al segundo menú, lo mismo con el segundo menú y el tercer menú. pero las opciones son diferentes para que sepas que el usuario ha elegido finalmente. ejemplo:

menú 1: 1 ==> menú 2: 4 ==> menú 3: 2 (...) la elección es 142. otros casos: 111,141,131,122 ...

solución: guarde el primero en a, el segundo en b, el tercero en 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)
abdull benlamina
fuente