Newsgroup: it.comp.lang.c
Titolo: Funzione che stampi la riga del sorgente dove e` chiamata...

Ciao a tutti,
vorrei porvi un problema che proprio non riesco a risolvere....
Io ho bisogno di fare una funzione che stampi la riga del codice in cui e`
stata chiamata:
per es.
 1:    void fun( int iRow )
 2:    {
 3:         printf( "Row: %d\n", iRow );
 4:         ....
 5:    }
 6:    #define FUN() fun( __LINE__ )
 7:
 8:
 9:    int main( )
10:    {
11:        ....
12:        FUN();
13:        return 0;
14:    }
Dovrebbe stampare 12...
e se F() venisse chiamata da un altra funzione dovrebbe funzionare bene
comunque:
112:    int altraFunzione( )
113:    {
114:        ...
130:        FUN();
131:        ...
150:    }
dovrebbe stampare 130
Ora il mio problema viene fuori quando la funzione vuole dei parametri! Se
questi sono di numero determinati il problema non sussiste:
1:    void fun( int iRow, char *pcStr, int iNum )
2:    {
3:         printf( "Row: %d\n", iRow );
4:         ....
5:    }
6:    #define FUN( s, i ) fun( __LINE__, s, i )
Come faccio, invece se il numero dei parametri e` variabile:
void fun( int iRow, char *pcStr, ... )
Aiuto!! :(

 void fun( int iRow, char *pcStr, ... )
???
void fun(int iRow, char* format, ...)
{
   va_list vl;
   va_start(vl, format);
   /*
      in base alla strunga di formato,
       qui si decodificano i parametri
    */
   ....
   va_end(vl);
}
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG


No scusa, il problema non e` quello di leggere un numero incognito di
parametri, ma quello di creare un modo, metodo, funzione o macro che possa
gestire il discordo di __LINE__ + il numero di parametri variabili ...

 void fun(int iRow, char* format, ...)
Ma sa che fin qui c'era arrivato pure lui... :-)
Il problema è: come si definisce la macro FUN()? Il preoprocessore non
supporta macro a argomenti variabili.
Anch'io ho avuto la stessa esigenza, e sono riuscito a risolverla solo con
una variabile globale e con un uso decisamente poco elegante dell'operatore
virgola:
   long lRow;
   void _fun (char *pcStr, ... )
   {
      va_list va;
      va_start(va, pcStr);
      printf( "Row: %d ", lRow);
      /* ... Usa la variabile va, probabilmente con vprintf() e company */
   }
   #define FUN lRow = __LINE__ , fun
   130: ...
   131: FUN("Stringa: %s\n", sCiccio);
   123: ...
La riga 131 verrà espansa così:
   lRow = __LINE__ , fun("Stringa: %s\n", sCiccio);
--
Cingar
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/


Non so se ho capito bene il problema, ma come fa il programma compilato a
sapere su che linea del sorgente si trova?
Ciao
Giuseppe

    lRow = __LINE__ , fun("Stringa: %s\n", sCiccio);
Se me lo consentono i miei superiori (perche` effettivamente "decisamente
poco elegante" e` dir poco) la prendero` in considerazione... magari
mettendo il ; anziche` la ,
GRAZIE

    lRow = __LINE__ , fun("Stringa: %s\n", sCiccio);


    lRow = __LINE__ , fun("Stringa: %s\n", sCiccio);


    lRow = __LINE__ , fun("Stringa: %s\n", sCiccio);


 magari mettendo il ; anziche` la ,
Idea brillante, perché non ci ho pensato io! :-) Dopo che hai fatto questa
furbata, prova a scrivere questo:
   100: ...
   101: FUN("Ciao sono la riga 101\n");
   102: ...
   ...
   200: ...
   201: if (pippo)
   202: FUN("Ciao sono la riga 202; pippo non è zero ma bensì %d.\n", pippo);
   203: ...
Quando poi i tuoi superiori ti chiederanno conto del seguente messaggio:
   Riga 101: Ciao sono la riga 202; pippo non è zero ma bensì 0.
... tu rispondigli "L'eleganza prima di tutto!".
--
Cingar
P.S. Lo dicevo solo per falsa modestia: quella virgola *è* elegantissima!
:-) È proprio per permettere trucchetti del genere che esiste l'operatore
virgola.


 supporta macro a argomenti variabili.
__VA_ARGS__ 
cerca sul tuo reference ;)
Luca
-- 
Home: 
http://kronoz.cjb.net
Io mi ricordo sempre il compleanno della mia ragazza:
cade il giorno dopo di quando lei me lo ricorda

 void fun( int iRow, char *pcStr, ... )
In modo standard;
#define FUNC(pcstr, ...) fun( __LINE__ , pcstr, __VA_ARGS__ )
L'unica limitazione e` che deve essere presente almeno un argomento
opzionale nelle chiamate. Se scrivi qualcosa del tipo:
FUNC("foo");
verra` espanso in:
fun( __LINE__ , pcstr, );
che ti dara` un errore di compilazione. Un'estesione del preprocessore
CPP ti permette di scrivere:
#define FUNC(pcstr, ...) fun( __LINE__ , pcstr, ## __VA_ARGS__ )
ma non e` portabile. Potresti scrivere una cosa del genere:
#define FUNC(...) fun( __LINE__ , __VA_ARGS__ )
come workaround, ma devi fare affidamento sul fatto che il chiamate ti
passi come primo argomento una stringa...
Luca
-- 
Home: 
http://kronoz.cjb.net
"Fare l'amore con dieci donne e` fantastico, soprattutto perche` ti
 presentano un sacco di amiche." -- Fabio Di Iorio

 cerca sul tuo reference ;)
Ah, interessante.


 virgola.
sara`...

> #define FUNC(pcstr, ...) fun( __LINE__ , pcstr, __VA_ARGS__ )
Sara` standard, comunque VC++.Net non lo compila...

 Sara` standard, comunque VC++.Net non lo compila...
Forse perche' e' standard C99... AFAIK le macro C89 non supportano un
nummero variabile di argomenti.
C:\>iao Angelo


 nummero variabile di argomenti.
Infatti, ma VC++.NET e` uscito nel 2002... Ok, e` risaputo che VC e gli
standard ISO sono sempre stati su due pianeti diversi.
Luca
-- 
Home: 
http://kronoz.cjb.net
"L'abilita` politica e` l'abilita` di prevedere quello che
 accadra` domani, la prossima settimana, il prossimo mese e
 l'anno prossimo. E di essere cosi` abili, piu` tardi,
 da spiegare  perche' non e` accaduto."