Verifica del numero minimo di argomenti della riga di comando, ma che consente il passaggio della guida

1

Mi sono imbattuto in uno scenario strano. Sono sicuro che devo aver incontrato la stessa situazione in passato e tuttavia in qualche modo non l'ho notato fino ad ora.

Sto scrivendo un programma che richiede almeno due argomenti da riga di comando. Occuparsi di questo è abbastanza semplice, basta controllare che ci siano argomenti sufficienti. Ad esempio:

A:  if (argc < 3) PrintHelpAndQuit();

Tuttavia, voglio anche consentire all'utente di richiedere specificamente le schermate di aiuto usando un singolo argomento da riga di comando. Ad esempio:

B:  if (args[1] == "/?")  PrintHelpAndQuit();
C:  if (args[1] == "/?1") PrintHelp1AndQuit();
D:  if (args[1] == "/?2") PrintHelp2AndQuit();

Il problema è che se metto per primo la riga A , si assicura che siano stati specificati almeno due argomenti, il che impedisce le righe B , C , e D da chiamata, e quindi l'utente non può accedere a quegli schermi.

Se metto la riga A dopo le altre, il programma si bloccherà se non viene specificato alcun argomento (l'accesso al primo membro dell'array di argomenti non è definito).

Sembra che ci siano (solo?) due modi per avvicinarsi a questo:

  • Metti le linee della schermata di aiuto in un blocco condizionale che verifica che ci sia almeno un argomento (che duplica il lavoro della linea A ):

    if (argc > 1) {
      if (args[1] == "/?...
    }
    
    if (argc < 3) PrintHelpAndQuit();
    

  • Metti una riga in più in alto che controlla se non ci sono argomenti e stampa aiuto e si chiude in questo caso:

    if (argc < 2) PrintHelpAndQuit(); // now almost entirely duplicates line A
    if (args[1] == "/?...
    if (argc < 3) PrintHelpAndQuit();
    


Entrambi questi approcci sono ridondanti a vari livelli.

In che modo gli altri affrontano questa situazione? Esiste un modo più elegante (e meno ridondante) per richiedere un numero minimo di argomenti senza precludere un singolo argomento?

    
posta Synetech 11.06.2013 - 15:38
fonte

4 risposte

3

Logicamente, il problema come definito richiede un controllo che ci sia almeno un argomento per il caso di aiuto, così come un controllo che ci siano almeno due argomenti per il caso d'uso normale.

Pensa a cosa devi dire per descrivere il comportamento del programma:

[The program] requires at least two command-line arguments...

Poi

I also want to allow the user to specifically request the help-screen(s) using a single command-line argument.

Anche per descrivere il comportamento in parole, hai bisogno di due diversi requisiti sul numero di argomenti. Non sorprende che il codice abbia bisogno di due requisiti. Avere due assegni non è ridondante, perché è l'importo minimo necessario per testare logicamente le opzioni valide.

    
risposta data 11.06.2013 - 15:49
fonte
2

Le utilità della riga di comando, nella mia esperienza, tendono ad essere universalmente brutte quando si tratta di essere flessibili durante l'analisi di argomenti, specialmente quando si ha un comando che può assumere un numero arbitrario di argomenti. Ci sarà quasi sempre un certo livello di duplicazione o controllo incrociato, perché al suo centro lo strumento è probabilmente breve, il che significa che probabilmente è un singolo file, il che significa che è probabilmente procedurale.

Il primo passo per qualsiasi strumento da riga di comando è l'analisi degli argomenti. Questo è fondamentalmente l'equivalente di impostare lo stato iniziale della macchina a stati rappresentata dal resto del tuo script.

Ecco alcuni pseudocodici:

if args.length is 0 or (args.length is 1 and args[0] is '--help')
    do_help_message_thing();
elseif args.length is 1
    do_invalid_usage_thing();

Non mi preoccuperei troppo del codice nel tuo strumento. Stai scrivendo lo strumento per incapsulare un po 'di tristezza in modo che chiunque utilizzi lo strumento in futuro possa prendere una scorciatoia. Finché la sceneggiatura non è bacata, relativamente veloce e non ha il potenziale per fluire un sistema, la gente ti amerà per questo (almeno nella mia esperienza).

    
risposta data 11.06.2013 - 15:49
fonte
0

Negli strumenti * nix è normale richiedere che tutte le opzioni / flag siano posizionate prima degli argomenti obbligatori. Con questo requisito e il fatto che devi semplicemente scartare il resto degli argomenti se avvii una funzione di aiuto puoi fare quanto segue:

switch args[1]:
    case "/?") PrintHelpAndQuit();
    case "/?1") PrintHelp1AndQuit();
    case "/?2") PrintHelp2AndQuit();

Una volta superata l'istruzione switch , conosci che tutti gli argomenti seguenti sono (almeno due) argomenti necessari e puoi controllare argc < 3 .

    
risposta data 11.06.2013 - 16:00
fonte
0

Non lavorare con i conteggi degli argomenti. Posizionare gli argomenti in una coda ed elaborare la coda. Questo è molto più facile da lavorare.

Queue q = new Queue();
for(int i=0; i < argc; i++)
{
    q.push(args[i]);
}

Una volta entrati in coda, è possibile elaborare gli argomenti tramite un semplice metodo di invio. Quello che dovresti fare è seguire uno schema coerente per la piattaforma. Su Windows gli argomenti sono preceduti da una barra diretta e gli argomenti senza una barra sono parametri per l'argomento precedente. Su Linux è un doppio trattino.

Supponiamo di avere alcuni utilizzi come questo

tool.exe /mode on /prompt off
tooo.exe /? /mode on

Il primo imposta alcune opzioni, mentre il secondo visualizza l'aiuto per un'opzione. Poiché hai gli argomenti in una coda, puoi elaborarli in questo modo.

while(!q.empty())
{
    String arg = q.pop();
    // is it an option
    if(arg.startsWith("/"))
    {
        switch(arg)
        {
            case "/mode":
               setMode(q.pop());
               break;
            case "/prompt":
               setPrompt(q.pop());
               break;
            case "/help":
               showHelp(q.pop(),q.pop());
               exit();
               break;
        }
    }
    else
    {
       exit("Unexpected argument");
    }
}

// run the program, all options are set

Ora non ho eseguito alcun controllo sugli argomenti mancanti della coda, ma potresti fare la tua coda dove pop() ha accettato un valore predefinito.

Con una coda l'ordine degli argomenti non infrange nulla.

tool.exe /mode on /prompt off
tool.exe /prompt off /mode on
tooo.exe /prompt on /? /mode on

Tutti i precedenti sono validi.

    
risposta data 11.06.2013 - 16:18
fonte

Leggi altre domande sui tag