2013-02-24 23 views
5

Ho la seguente funzione C con un numero variabile di argomenti, che dovrebbe cercare la char* word attraverso una tabella hash e scrivere true o false in un file che, se specificato, è il secondo parametro; altrimenti, è stdout.comportamento strano della funzione con numero variabile di parametri in C

Funziona benissimo se a specificare il nome del file, il problema è quando non lo faccio (per esempio find("foo")). In questo caso, scrive il risultato in un file denominato foo anziché stdout.

Qual è la causa?

void find(char* word, ...) 
{ 
va_list list; 
char *fname = NULL; 
va_start(list, word); 
FILE* f; 
fname = strdup(va_arg(list, char*)); 
va_end(list); 
if (<condition>) // condition suited for the case in which the file name is received 
    f = fopen(fname, "a"); 
else 
    f = stdout; 
if (member(word)) 
    fprintf(f, "True\n"); 
else 
    fprintf(f, "False\n"); 
} 

Al posto di <condition> ho provato fname != NULL e strlen(fname) > 0 ma quelli non si applicano e si continua a vedere come fnameword quando fname non è specificato.

Grazie mille per l'aiuto che puoi fornire.

+1

varargs non devono essere utilizzati in questo modo. Stai meglio usando 'void find (char * word, char * filename)' e controllando se 'filename' è' NULL' e in tal caso scrivi su stdout. Inoltre, non dimenticare di chiudere il file, che hai aperto, se hai aperto un file. –

risposta

6

Dalla pagina man va_* s':

Se non c'è argomento successivo, o se il tipo non è compatibile con il tipo dell'argomento effettivo successivo (come promosso in base alla argomento di default promozioni), si verificheranno errori casuali.

Se si desidera utilizzare una lista di parametri variabili, è necessario mettere a punto una sorta di terminazione per la lista (ad esempio, aggiungere sempre un argomento NULL fittizio):

find (word, NULL); 
find (word, filename, NULL); 

o fornire il numero di parametro come parametro:

find (1, word); 
find (2, word, filename); 
+0

OK, grazie per avermi ricordato. Funziona con NULL alla fine dell'elenco. Inizialmente pensavo che NULL (o altro comportamento) fosse in qualche modo implicito per argomenti che non erano stati ricevuti, ma non lo sa da solo quando termina la lista. – thehousedude