2016-07-22 15 views
2

ich die folgende C-Code versuche aus (gespeichert in Datei namens testgetopt.c):C: getopt(): Option scheint nicht zu wirken

#include <stdio.h> 
#include <stdlib.h> 
#include <getopt.h> 
#include <ctype.h> 

void usage(char *s) 
{ 
    fprintf(stderr, "Usage: %s [-d] -i input-TIFF-file -o output-raw-file\n", s); 
    fprintf(stderr, "Note: -d indicates debugging option\n"); 
} 

int main(int argc, char **argv) { 
    char c; 
    size_t i; 
    char *itext = NULL, *otext = NULL; 
    FILE *fout; 
    short debug = 0; 

    if ((c = getopt(argc, argv, "di:o:")) == EOF) { 
     usage(argv[0]); 
     exit(1); 
    } 

    while ((c = getopt(argc, argv, "di:o:")) != EOF) { 
     switch (c) { 
     case 'd': 
      debug = 1; 
      break; 
     case 'i': 
      itext = optarg; 
      break; 
     case 'o': 
      otext = optarg; 
      break; 
     case '?': 
      if (optopt == 'i' || optopt == 'o') 
       fprintf (stderr, "Option -%c requires an argument.\n", optopt); 
      else if (isprint (optopt)) 
       fprintf (stderr, "Unknown option `-%c'.\n", optopt); 
      else 
       fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); 
      usage(argv[0]); 
      exit(1); 
     default: 
      fprintf(stderr, "Both -i and -o are needed\n"); 
      usage(argv[0]); 
      exit(1); 
     } 
    } 
    printf("debug = %i\n", debug); 
    if (debug) 
     printf ("input file = %s, output file = %s\n", itext, otext); 
    return EXIT_SUCCESS; 
} 

ich kompilieren mit:

gcc testgetopt.c 

Aber unabhängig davon, ob ich -d oder nicht, habe ich immer Debug-Set auf 0 gesetzt. Das Programm sollte -D Debug auf 1, 0 gesetzt haben, sonst.

Was wird falsch gemacht?

Hier sind die Beispiele:

Versuchen wir zunächst ohne -d

./a.out -i in.dat -o out.dat 
debug = 0 

Lassen Sie uns als nächstes versuchen, mit -d enthalten.

./a.out -d -i in.dat -o out.dat 
debug = 0 

Vielen Dank im Voraus für jede Hilfe und Anregungen!

+0

Wie haben Sie versucht zu debuggen? Das Ausdrucken der Ergebnisse von "getopt" innerhalb der Schleife würde Ihnen Daten liefern, auf denen Sie eine Theorie über das, was vor sich geht, aufbauen können, obwohl nette Stapel-Überflieger großzügig diese Arbeit für Sie erledigt haben. –

Antwort

3

Das Problem ist, dass Sie getopt als Plausibilitätsprüfung aufrufen und dann das Ergebnis nicht verwenden, wenn es erfolgreich ist. Das bedeutet, dass die erste Option immer verworfen wird. Sie können dies leicht überprüfen, indem -d als nicht-erste Option setzen:

$ ./a.out -i in.dat -o out.dat -d 
debug = 1 
input file = (null), output file = out.dat 

Sie können sehen, dass die -d wirksam tat diesmal aber das erste Argument, -i, nicht gesetzt ist.

Es gibt mehrere Möglichkeiten, dies zu beheben. Der empfohlene Weg (IMHO) besteht darin, den ersten Anruf getopt zu entfernen. Ändern Sie dann die Plausibilitätsprüfung, um die tatsächlichen Optionen zu überprüfen. Das heißt, es sollte Code nach der getopt-Schleife sein, die verifiziert, dass alle obligatorischen Optionen bereitgestellt wurden.

Zum Beispiel:

int main(int argc, char **argv) { 
    char c; 
    size_t i; 
    char *itext = NULL, *otext = NULL; 
    FILE *fout; 
    short debug = 0; 

    /* REMOVED THIS BLOCK OF CODE 
    if ((c = getopt(argc, argv, "di:o:")) == EOF) { 
     usage(argv[0]); 
     exit(1); 
    } 
    */ 

    while ((c = getopt(argc, argv, "di:o:")) != EOF) { 
     switch (c) { 
     case 'd': 
      debug = 1; 
      break; 
     case 'i': 
      itext = optarg; 
      break; 
     case 'o': 
      otext = optarg; 
      break; 
     case '?': 
      if (optopt == 'i' || optopt == 'o') 
       fprintf (stderr, "Option -%c requires an argument.\n", optopt); 
      else if (isprint (optopt)) 
       fprintf (stderr, "Unknown option `-%c'.\n", optopt); 
      else 
       fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt); 
      usage(argv[0]); 
      exit(1); 
     default: 
      fprintf(stderr, "Both -i and -o are needed\n"); 
      usage(argv[0]); 
      exit(1); 
     } 
    } 

    /* ADD SOME ARGUMENT SANITY CHECKS */ 
    if (!itext || !otext) { 
     printf("Missing mandatory arguments\n"); 
     exit(1); 
    } 

    printf("debug = %i\n", debug); 
    if (debug) 
     printf ("input file = %s, output file = %s\n", itext, otext); 
    return EXIT_SUCCESS; 
} 
+0

Es tut mir leid, ich verstehe nicht "Dann ändern Sie die Plausibilitätsprüfung, um die tatsächlichen Optionen zu überprüfen. Das heißt, es sollte Code nach der getopt-Schleife sein, der bestätigt, dass alle obligatorischen Optionen bereitgestellt wurden." Könnten Sie bitte eine Referenz/Beispiel angeben? Vielen Dank! – user3236841

+0

Ich habe einen Beispielcode hinzugefügt, der die anfängliche 'getopt'-Prüfung entfernt und nach dem Parsen der Befehlszeile einige Plausibilitätsprüfungen hinzufügt. Die Plausibilitätsprüfungen sind nur ein Beispiel und Sie müssen andere/andere Anforderungen überprüfen. – kaylum

+0

BTW, warum funktioniert der "Standard" nicht? Hier ist, was ich bekomme: – user3236841

1

Weil Sie getopt zweimal anrufen, müssen Sie optind = 1; zwischen den Anrufen setzen.

+0

Das funktioniert, danke! Aber ich würde gerne wissen, wie man es nicht zweimal nennt! – user3236841

+0

Sie haben Recht, die wirkliche Antwort ist nicht zweimal 'getopt() 'aufzurufen. @ Kaylums Antwort gibt einige gute Tipps, wie man das macht – John3136

+0

Ich kann nicht scheinen, beide Antworten zu überprüfen! Das eine zu tun nimmt dem anderen die Kontrolle! Ich werde diesen Kommentar hinterlassen und den anderen überprüfen, da das mehr in der Linie von dem ist, was ich möchte. Danke nochmal! – user3236841