2009-02-11 9 views
5

Qualcuno può aiutarmi con la funzione getopt?- getopt

Quando faccio presente quanto segue principale:

char *argv1[] = {"testexec","-?"}; 
char *argv2[] = {"testexec","-m","arg1"}; 
int cOption; 
/* test for -? */ 

setvbuf(stdout,(char*)NULL,_IONBF,0); 
printf("\n argv1 "); 
while ((cOption = getopt (2, argv1, "m:t:n:fs?")) != -1) { 
    switch(cOption){ 
     case 'm': 
      printf("\n -m Arg : %s \n",optarg); 
      break; 
     case '?': 
      printf("\n -? Arg "); 
      break; 
     case 'n': 
      printf("\n -n Arg : %s \n",optarg); 
      break; 
    } 
} 

printf("\n argv2 "); 

while ((cOption = getopt (3, argv2, "m:t:n:fs?")) != -1) { 
    switch(cOption){ 
     case 'm': 
      printf("\n -m Arg : %s \n",optarg); 
      break; 
     case '?': 
      printf("\n -? Arg : %s \n",optarg); 
      break; 
     case 'n': 
      printf("\n -n Arg : %s \n",optarg); 
      break; 
    } 
} 
 

Io corro questo codice su RHEL3 che utilizza vecchia versione libc. Non so quale sia per essere esatto.

Ora il problema è getopt non funziona la seconda volta con argv2. Ma se commento la prima chiamata getopt con argv1, funziona.

Qualcuno può dirmi cosa sto sbagliando qui?

risposta

12

argv1 e 2 devono terminare in 0:

char* argv1[] = {"par1", "par2", 0}; 

Edit: OK, ho letto la pagina di getopt uomo e ho trovato questo:

L'OPTIND variabile è l'indice del prossimo elemento da elaborare in argv. Il sistema inizializza questo valore da a 1. Il chiamante può reimpostarlo su 1 per riavviare la scansione dello stesso argv o durante la scansione di un nuovo vettore argomento.

Quindi, fare optind = 1 tra le due chiamate su getopt lo fa funzionare come previsto.

+0

Buona risposta, ma mentre questo è certamente vero, ho provato a cambiarlo nel codice di esempio e non è stato risolto il particolare problema che veniva posto. –

+0

David, hai ragione. Ho appena individuato quell'errore e ho dimenticato il resto :) Ho modificato la risposta, poiché ho notato che se aggiorni il valore optind a 1, il codice funziona come previsto. Cordiali saluti –

+2

Attenzione: lo standard POSIX non stabilisce che il reset di optind a 1 resetterà getopt() allo stato iniziale, specialmente se non sono stati analizzati completamente i primi argomenti. Ad esempio, se il primo argomento è -xy e ti fermi dopo aver elaborato x, non c'è alcuna garanzia che un reset di optind funzioni. –

4

La funzione getopt() utilizza alcune variabili globali, ad esempio optind e optarg, per memorizzare le informazioni di stato tra le chiamate. Dopo aver completato l'elaborazione di un set di opzioni, i dati lasciati in quelle variabili causano problemi con il successivo set di opzioni. Potresti provare a reimpostare lo stato di getopt tra le chiamate cancellando le variabili, ma non sono sicuro che funzionerebbe dato che la funzione potrebbe utilizzare altre variabili che non sono documentate e non sapresti mai se le avresti ricevute tutti; inoltre, sarebbe assolutamente non portabile (ad esempio se l'implementazione di getopt() cambia, il codice si interrompe). Vedi lo man page per i dettagli. Meglio non usare getopt() per più di un set di argomenti in un dato programma se puoi aiutarlo.

Non sono sicuro se esiste una funzione effettiva per il ripristino dello stato di getopt (o forse una versione rientrante della funzione, che consente di memorizzare lo stato nelle proprie variabili) ... Mi sembra di ricordare di aver visto una cosa del genere una volta, ma non riesco a trovarla ora che guardo: -/

1

C'è qualche ragione per cui non stai usando getopt_long()? Sulla maggior parte delle piattaforme, getopt() chiama semplicemente _getopt_long() con un interruttore per disabilitare gli argomenti lunghi. Questo è il caso di quasi tutte le piattaforme che conosco (ancora in uso), tra cui Linux, BSD e persino sistemi operativi emergenti come HelenOS - lo so, io ero quello che portò getopt alla sua libc :)

molto più facile su CHIUNQUE che usa il tuo programma per avere opzioni lunghe almeno fino a quando non si abituano a usarlo.

getopt_long() vi permetterà di utilizzare due (o più) gli indici di opzioni che possono rimanere 'live' dopo che sono state fatte argomenti di elaborazione, solo l'interno (globale, non rientrante) si dovrebbe essere ri-set che non è un grosso problema.

Ciò consente di confrontare facilmente il conteggio degli argomenti con il numero di opzioni effettivamente passate in entrambe le invocazioni con molti altri vantaggi.per favore considera di non usare l'interfaccia antiquata.

Guarda getopt.h, vedrai cosa intendo.

+2

Definisci la maggior parte delle piattaforme? HP-UX, Solaris, AIX - getopt() non chiama getopt_long(). Ecco 3 delle 6 varianti di Unix (BSD, Linux, MacOS X sono gli altri che contano). –

2

Come indicato nella pagina man:

"Un programma che analizza più vettori di argomento, o esegue una nuova scansione lo stesso vettore più di una volta, e vuole fare uso di estensioni GNU come '+' e '-' all'inizio di optstring, o cambia il valore di POSIXLY_CORRECT tra le scansioni, deve reinizializzare getopt() resettando optind a 0, piuttosto che il valore tradizionale di 1. (Resettando a 0 forza il richiamo di una routine di inizializzazione interna che ricontrolla POSIXLY_CORRECT e controlla le estensioni GNU in optstring.) "

Problemi correlati