2012-03-28 14 views
8

Quiero concat un literal de cadena y literal de char. Al ser sintácticamente incorrecta, "abc" 'd' "efg" hace que un error del compilador:Concatenar literal de cadena con literal de char

x.c:4:24: error: expected ',' or ';' before 'd'

Por ahora tengo que usar snprift (innecesariamente), a pesar del valor de cadena literal y el ser literal carbón saber en tiempo de compilación.

me trataron

#define CONCAT(S,C) ({ \ 
    static const char *_r = { (S), (C) }; \ 
    _r; \ 
}) 

pero no funciona porque el terminador nulo de S no es despojado. (Además de dar advertencias del compilador.)

¿Hay una manera de escribir una macro para usar

  • "abc" MACRO('d') "efg" o
  • MACRO1(MACRO2("abc", 'd'), "efg") o
  • MACRO("abc", 'd', "efg")?

En caso de que alguien pregunte por qué quiero eso: El literal de char proviene de una biblioteca y necesito imprimir la cadena como un mensaje de estado.

+0

Yo no quiero * * que desee usar ninguna de las funciones de tiempo de ejecución o sprintf. No coloque ninguna respuesta que emplee llamadas de método de tiempo de ejecución. – kay

+0

Si el literal proviene de una biblioteca, ¿cómo está accediendo a él? ¿Es una macro proporcionada por el archivo de encabezado de la biblioteca? –

+0

Sí, proviene de un archivo de encabezado. – kay

Respuesta

2

C solo le permitirá concatenar literales de cadena. En realidad, no hay nada de malo en snprintf(). También es posible usar strcpy():

strcpy(dest, str1); 
dest[strlen(dest)] = c; 
strcpy(dest + strlen(dest) + 1, str2); 

También es posible usar un gigante switch declaración de superar esta limitación:

switch(c) { 
    case 'a': 
     puts("part1" "a" "part2"); 
     break; 
    case 'b': 
     puts("part1" "b" "part2"); 
     break; 

    /* ... */ 

    case 'z': 
     puts("part1" "z" "part2"); 
     break; 
} 

... pero me niego a reclamar la autoría.

En pocas palabras, simplemente quédese con snprintf().

+0

El problema es que no * quiero * usar snprintf o strcpy. Es más una cuestión filosófica que una pregunta para principiantes ... – kay

+1

kay: Ah, ya veo ... ¡Buena suerte! ;) Por cierto, ¿qué pasa con 'printf (" part1% c part2 \ n ", c);'? – Philip

+1

No hay nada "incorrecto" con printf. Solo quería saber si era posible obtener toda la cadena en tiempo de compilación sin ninguna actividad en tiempo de ejecución. No hay nada en juego de tener tal macro o no. Ya ves ... es una pregunta filosófica. ;) – kay

6

Si se puede vivir con las comillas simples se incluyen con él, usted podría utilizar stringification:

#define SOME_DEF 'x' 

#define STR1(z) #z 
#define STR(z) STR1(z) 
#define JOIN(a,b,c) a STR(b) c 

int main(void) 
{ 
    const char *msg = JOIN("Something to do with ", SOME_DEF, "..."); 

    puts(msg); 

    return 0; 
} 

Dependiendo del contexto que pueden o no ser apropiada, pero en lo convincente que sea realidad una cadena literal de esta manera, es la única forma en que se nos ocurre sin formatear en el tiempo de ejecución.

+0

¿Por qué no utilizar directamente STR1 en la concatenación, como JOIN (a, b, c) a STR1 (b) c? En lugar de usar la sub-macro STR()? – Luciano

3

Pruebe esto. Utiliza el macro truco C de macros dobles, por lo que el argumento de macro tiene la posibilidad de expandirse antes de ser codificado.

#include <stdio.h> 

#define C d 
#define S "This is a string that contains the character " 
#define STR(s) #s 
#define XSTR(s) STR(s) 

const char* str = S XSTR(C); 

int main() 
{ 
    puts(str); 
    return 0; 
} 
3

me ocurrió una solución GCC-específico que no me gusta demasiado, ya no se puede utilizar CONCAT nestedly.

#include <stdio.h> 

#define CONCAT(S1,C,S2) ({      \ 
    static const struct __attribute__((packed)) { \ 
     char s1[sizeof(S1) - 1];     \ 
     char c;         \ 
     char s2[sizeof(S2)];      \ 
    } _r = { (S1), (C), (S2) };     \ 
    (const char *) &_r;       \ 
}) 

int main(void) { 
    puts(CONCAT ("abc", 'd', "efg")); 
    return 0; 
} 

http://ideone.com/lzEAn

+1

Buena idea, pero la compilación con gcc con la opción '-pedantic' da las advertencias" matriz inicializada de cadena entre paréntesis constante "y" ISO C prohíbe grupos enlazados dentro de expresiones ". –

Cuestiones relacionadas