2012-03-28 8 views
8

Desidero concatenare una stringa letterale e char letterale. Essendo sintatticamente corretto, "abc" 'd' "efg" rende un errore di compilazione:Concatena stringa letterale con char letterale

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

Ormai devo usare snprift (inutilmente), nonostante il valore della stringa letterale e l'essere letterale char conoscere al momento della compilazione.

Ho provato

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

ma non funziona perché il terminatore null S non viene rimosso. (Oltre di dare gli avvisi del compilatore.)

C'è un modo per scrivere una macro per usare

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

Nel caso in cui qualcuno chieda perché lo voglio: Il char letteral proviene da una libreria e devo stampare la stringa come messaggio di stato.

+0

Io non voglio * * voler utilizzare sprintf o qualsiasi funzioni di runtime. Si prega di non inserire alcuna risposta che impieghi le chiamate al metodo di runtime. – kay

+0

Se il letterale proviene da una libreria, come stai accedendo? È una macro fornita dal file di intestazione della libreria? –

+0

Sì, proviene da un file di intestazione. – kay

risposta

2

C consente solo di concatenare stringhe letterali. In realtà, non c'è niente di sbagliato con snprintf(). Si potrebbe anche usare strcpy():

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

Si potrebbe anche usare un gigante switch dichiarazione per superare questa limitazione:

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

    /* ... */ 

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

... ma mi rifiuto di rivendicare alcun autore.

Per dirla in breve, basta attaccare con snprintf().

+0

Il fatto è che io non * voglio * usare snprintf o strcpy. È più una questione filosofica che una domanda per principianti ... – kay

+1

kay: Ah, capisco ... Buona fortuna! ;) A proposito, cosa c'è di sbagliato con 'printf (" part1% c part2 \ n ", c);'? – Philip

+1

Non c'è niente di "sbagliato" con printf. Volevo solo sapere se era possibile ottenere l'intera stringa in fase di compilazione senza alcuna attività di runtime. Non c'è niente in ballo di avere una tale macro o no. Vedi ... è una domanda filosofica. ;) – kay

6

Se si può vivere con le virgolette singole essere inclusi con esso, è possibile utilizzare in stringa:

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

A seconda del contesto che può o non può essere appropriato, ma per quanto convincente che sia in realtà una stringa letterale in questo modo, è l'unico modo che mi viene in mente senza formattazione in fase di runtime.

+0

Perché non utilizzare direttamente STR1 nella concatenazione, come JOIN (a, b, c) a STR1 (b) c? Invece di usare la sotto-macro STR()? – Luciano

3

Prova questo. Utilizza il trucco macro C di macro doppi in modo che l'argomento macro abbia la possibilità di espandersi prima di essere sottoposto a stringa.

#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

mi si avvicinò con una soluzione specifica per GCC che non mi piace troppo, come non si può usare 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

Buona idea, ma la compilazione con gcc con l'opzione '-pedantic' fornisce gli avvisi" array inizializzato da parentesi costante di stringa "e" ISO C proibisce gruppi armati all'interno di espressioni ". –