2012-03-28 25 views
8

Chcę dołączyć literał łańcuchowy i literał literowy. Jako niepoprawny składniowo, "abc" 'd' "efg" powoduje błąd kompilatora:Konkatenuj ciąg literału z literałem znaków

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

Teraz muszę używać snprift (niepotrzebnie), pomimo wartości ciąg dosłownym i char dosłownym istoty wiedzą w czasie kompilacji.

Próbowałem

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

ale to nie działa, ponieważ null terminator S nie jest usuwany. (Oprócz dawania ostrzeżenia kompilatora).

Czy istnieje sposób, aby napisać makro do korzystania

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

Na wypadek, gdyby ktoś zapytał, dlaczego tego chcę: literał literowy pochodzi z biblioteki i muszę wydrukować ciąg znaków jako komunikat stanu.

+0

ja nie chcę * chcesz * Zastosowanie sprintf lub jakiekolwiek funkcje starcie. Proszę nie umieszczać żadnych odpowiedzi, które wykorzystują wywołania metod wykonawczych. – kay

+0

Jeśli literał pochodzi z biblioteki, w jaki sposób uzyskujesz do niego dostęp? Czy jest to makro dostarczone przez plik nagłówkowy biblioteki? –

+0

Tak, pochodzi z pliku nagłówkowego. – kay

Odpowiedz

2

C pozwoli ci tylko łączyć literały łańcuchowe. W rzeczywistości nie ma nic złego w snprintf(). Można również użyć strcpy():

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

można też użyć gigantycznego switch oświadczenie do pokonania tego ograniczenia:

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

    /* ... */ 

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

... ale ja odmawiam rości sobie żadnych autorstwa.

Krótko mówiąc, po prostu trzymaj się z snprintf().

+0

Chodzi o to, że nie * chcę * używać snprintf lub strcpy. Jest to raczej pytanie filozoficzne niż pytanie początkujących ... – kay

+1

kay: Ach, rozumiem ... Powodzenia! ;) BTW, co jest nie tak z 'printf (" part1% c part2 \ n ", c);'? – Philip

+1

Nic nie jest "nie tak" z printf. Chciałem tylko wiedzieć, czy można uzyskać cały ciąg w czasie kompilacji bez aktywności runtime. Nie ma nic wspólnego z posiadaniem takiego makro, czy też nie. Widzisz ... to filozoficzne pytanie. ;) – kay

6

Jeśli można żyć pojedyncze cytaty są dołączone do niego, można użyć 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; 
} 

W zależności od kontekstu, które mogą lub nie mogą być właściwe, ale jeśli chodzi o przekonywanie to faktycznie być w ten sposób można napisać ciąg literowy, to jedyny sposób, jaki przychodzi na myśl bez formatowania w czasie wykonywania.

+0

Dlaczego nie używać bezpośrednio STR1 w konkatenacji, jak JOIN (a, b, c) a STR1 (b) c? Zamiast używać podmenu STR()? – Luciano

3

Spróbuj tego. Używa makro makra C podwójnych makr, więc argument makra ma szansę rozwinąć zanim zostanie uszeregowany.

#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

wymyśliłem rozwiązanie GCC specyficzne, że nie lubię zbyt wiele, jak nie można używać 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

Dobry pomysł, ale kompilacja za pomocą gcc z opcją '-pedantic' daje ostrzeżenie" tablica zainicjalizowana z nawiasowanej stałej łańcuchowej "i" ISO C zabrania usztywnionych grup w wyrażeniach ". –

Powiązane problemy