Newsgroup: it.comp.lang.c
Titolo: Da numero a carattere a stringa con il preprocessore

Ho un numero definito come simbolo:
  #define NUM  44
Vorrei poterlo usare in situazioni del genere:
  printf("%d\n", NUM);
  printf("%c\n", NUM);
  printf("%s\n", STRING(NUM));
Ovviamente le prime due istruzioni funzionano. La terza ha bisogno
della macro STRING che però non so definire. Dovrebbe convertire
il valore di un simbolo (NUM in questo caso) in stringa, ma il
classico
operatore # del preprocessore genererebbe "44", io invece voglio
"\044", cioè una stringa costante con un solo carattere che è il
carattere
ASCII corrispondente al numero.
Qualcuno mi aiuta?


sprintf()
Ciao Jack

 sprintf()
No scusa, volevo fare la conversione in stringa tutta a
preprocessore...

pozz ha scritto:

#define NUM 42
#define STRING(x) STRING2(x)
#define STRING2(x) #x



Ancora non ci siamo. Con la macro STRING() voglio che venga
generata una stringa costante formata da un carattere il cui
codice ASCII è il valore del simbolo NUM.
In pratica, se NUM è 42, vorrei che STRING(NUM) fosse "\x2A"
o "\052" (mi sa che la codifica ASCII in una stringa costante
possa essere rappresentata solo in ottale o esadecimale e non
in decimale).
Se la conversione a preprocessore da decimale in esadecimale
(o ottale) è complicata, potrei anche definire NUM direttamente
in esadecimale:
#define NUM 052
Ma anche in questo caso come generare una stringa costante
mediante macro del tipo "\052"??


Guarda che quello che chiedi è esattamente:
printf("%c\n", NUM);
se non è l'output desiderato, allora, forse la domanda è sbagliata.
Se dici l'uso che ne devi fare ...
Ciao


#define STRINGA(num) '\\0" #num
printf("%s\n", STRINGA(99));  dà \099
Ciao
Giovanni
-- 
   A computer is like an air conditioner,
   it stops working when you open Windows.
   < 
http://giovanni.homelinux.net/
 >

 #define STRINGA(num) '\\0" #num
Naturalmente deve essere:
#define STRINGA(num) "\\0" #num


 Se dici l'uso che ne devi fare ...
Lo so che così funziona, ma a me serve il tutto a preprocessore. Non
voglio
chiamare la printf() per creare la stringa a partire dal codice ASCII.
L'esempio iniziale delle tre printf() era solo per dire che mi servono
due macro:
- una che genera il carattere a partire dal codice ASCII
- l'altra che genere la stringa a partire dal codice ASCII
In altre parole potrei scrivere tre macro:
#define NUM 42
#define CHAR_NUM '\042'
#define STRING_NUM "\042"
Siccome ho parecchi numeri e siccome la CHAR_NUM e la STRING_NUM
per via logica sono derivate da NUM, avevo pensato di definire
#define CHAR(NUM)   che fornisce '\042' e
#define STRING(NUM) che fornisce "\042"
Il problema è come definire queste due macro.

 #define STRINGA(num) "\\0" #num
Scusatemi non riesco a spiegarmi. La macro STRING(num) non deve
creare la stringa \042 così com'è, ma deve creare una stringa costante
di UN SOLO carattere corrispondente alla codifica ASCII di num.
Cioè se facessi printf("%s", CHAR(024)) dovrebbe essere visualizzato
uno spazio perchè CHAR(024) dovrebbe essere espanso in "\024" e 024
è l'ottale di 20, codifica ASCII dello spazio.

pozz ha scritto:

la CHAR(NUM) non ha senso, è direttamente NUM
mentre la stringa è un indirizzo in memoria, se non lo fornisci non puoi 
averlo  come vuoi tu.
Questo è quello che potresti fare:
#define STRING_NUM(vect, val) \
	do { vect[0] = val; vect[1] = 0; } while(false)
Ciao

 è l'ottale di 20, codifica ASCII dello spazio.
Direi che e' abbastanza chiaro quello che ti serve.
La brutta notizia e' che non si puo' fare con il preprocessor del C.
Il preprocessor e' in grado di gestire solo token validi mentre per
ottenere quello che vuoi tu dovresti costruire un token valido
concatenando dei "pezzi di token" ma non si puo!
In pratica, tu vorresti una cosa del genere:
/* errore! */
#define QUOTE "
/* STRING(42) --> "\042"
#define STRING(x) QUOTE "\0" #x QUOTE
Il problema e' che non puoi definire una macro che prende solo le
virgolette (puoi fare una stringa che contiene le virgolette
 ma e' un'altra cosa) perche' il pre-processore non puo' gestire
caratteri a se stanti come le virgolette a perte ma non chiuse.
ciao
Giacomo

 caratteri a se stanti come le virgolette a perte ma non chiuse.
E' vero, però posso string-izzare un qualsiasi numero con l'operatore
#.
Quindi il vero problema non è trattare le virgolette, quanto il
backslash.
Se infatti faccio:
#define MACRO_STRING(x) #x
#define STRING(x) MACRO_STRING(x)
#define NUM \x2A
ottengo che MACRO_STRING(NUM) viene espanso proprio a "\x2A" e
funziona.
Quello che vorrei fare, però, è definire NUM come 0x2A, 052 o 42 e non
come \x2A perchè poi mi serve usarlo come numero e non come stringa.
Potrei anche definirlo semplicemente come 2A e aggiungerci tramite
macro
lo 0x, ma come potrei aggiungere \x?
Peccato, eppure è una cosa veramente facile ed è un compito proprio
da preprocessore.
Vorrà dire che devo definire due volte lo stesso numero:
#define NUM1  0x2A
#define STRING_NUM1 "\x2A"

pozz ha scritto:

se non ti scoccia scrivere qualche riga in più, ma mantenendo 
l'informazione del numero in un solo punto puoi usare:
#define MAKE_STR(n) const char str##n[] = { n, 0 }
#define STRING_NUM(n)  str##n
#define NUM1  'a'
MAKE_STR(NUM1);
#define STRING_NUM1 STRING_NUM(NUM1)
#define NUM2  98 // 'b'
MAKE_STR(NUM2);
#define STRING_NUM2 STRING_NUM(NUM2)
#define NUM3  0x63 //'c'
MAKE_STR(NUM3);
#define STRING_NUM3 STRING_NUM(NUM3)
#define NUM4  0144  // 'd'
MAKE_STR(NUM4);
#define STRING_NUM4 STRING_NUM(NUM4)
....
   LPCSTR t1 = STRING_NUM1;
   LPCSTR t2 = STRING_NUM2;
   LPCSTR t3 = STRING_NUM3;
   LPCSTR t4 = STRING_NUM4;
------------------
Ciao

 #define STRING_NUM1 STRING_NUM(NUM1)
In realtà questo approccio ha due svantaggi.
Prima di tutto, se definisco 100 numeri ed utilizzo la relativa
stringa solo per
10 di essi (un esempio), il compilatore mi allocherebbe 90 stringhe
costanti che
non utilizzo con perdita di spazio.
Secondo, dovrei rinunciare a scritture del tipo:
const char str[] = "LA STRINGA DI NUM1 " STRING_NUM1 " E' QUESTA";
Grazie lo stesso...

pozz ha scritto:

Allora, riprendendo un tuo esempio, potresti ribaldare la situazione, 
parti dalla stringa ed ottieni il numero:
#define MACRO_STRING(x) #x
#define STRING(x) MACRO_STRING(x)
#define STRING_NUM1 STRING(\x2A)
#define NUM1 STRING_NUM1[0]
sei però obbligato ad usare notazione ottale o esadecimale
Ciao

 sei però obbligato ad usare notazione ottale o esadecimale
Perfetto! Non avevo idea che si potesse usare la sintassi [0] anche
nel preprocessore...
Grazie.