Kommandozeilenargumente am sinnvollsten prüfen



  • Hallo zusammen,

    stehe vor einem kleinen Problem. Ich möchte ein Kopier-Kommando schreiben, welches nach folgendem Schema aufgebaut sein soll:

    copy -o infile outfile

    o: Eine beliebige Option
    infile: Eingabedatei
    outfile: Ausgabedatei

    Das Ganze soll mit Fehlerbehandlung vonstatten gehen, d.h. das man bei weglassen der Ausgabedatei den Inhalt der Eingabedatei auf den Bildschirm geschrieben bekommt. Mit welchen Systemcalls dies vonstatten gehen soll habe ich mir bereits auch überlegt und es funktioniert. Mein Problem ist nur die Fehlerbehandlung der Kommandozeile. Welche Methode wäre da am sinnvollsten? Die Option bzw. die Parameter sind alle optional. Die einzelnen Positionen in argv[] auf NULL prüfen? Ein Denkanstoß wäre echt nicht schlecht, da ich mit meinen bisherigen Versuchen nicht viel erreicht habe.



  • Es gibt dazu vorgefertigte Funktionen unter Linux:
    http://www.gnu.org/software/libc/manual/html_node/Getopt.html



  • Hallo,

    danke für die Information, allerdings möchte ich es ohne die vorgefertigte Version machen. Ich bin mir nur nicht ganz sicher, ob es ein wenig "unflexibel" ist die einzelnen Argumente auf NULL zu prüfen. D.h. also so in etwa:

    int main(int argc, char *argv[]) {
    
    ...
    
       if((argv[2] == NULL) && (argv[3] == NULL))
          ...Von Tastatur nach Bildschirm ausschreiben
       else if((argv[2] != NULL) && (argv[3] == NULL))
          ...Von Eingabedatei auf Bildschirmausschreiben
       ...
    

    Mein Problem ist eben die Option "-o", welche im Falle von angegebenen Eingabe- und Ausgabedatei, den Inhalt der Eingabedatei NICHT in die Ausgabedatei kopiert, falls letztere bereits existiert. Die Option greift also nur bei angegebener Ein- und Ausgabe-Datei. Hier mal ein Stückchen Code:

    int main(int argc, char *argv[])
    {
       ....Variablendeklaration
    
       /*Option vorhanden ?*/
    
       if((argc > 1) && (checkoption(argv[1], "o") == TRUE))
          option = 1;
       else
          option = 0;
    
       if(((argc-1)-option == 0) || ((argc-1) == 0)) {
       /*Eingabe- und Ausgabe-Parameter nicht angegeben*/
    
          n = copy(STDIN, STDOUT);
    
       } else if(((argc-1) - option == 1) || (argc-1) - option == 1)) {
       /*Nur Eingabe-Parameter angegeben*/
    
          eingabe = open(argv[2], O_RDONLY);
          n = copy(eingabe, STDOUT);
    
       } else if((option == 0) && (argv[2] != NULL) && (argv[3] != NULL)) {
       /*Eingabe- und Ausgabe-Parameter (ohne Option)*/
    
          eingabe = open(argv[2], O_RDONLY);
          ausgabe = open(argv[3], O_WRONLY);
          n = copy(eingabe, ausgabe); 
    
       } else if((argv[2] != NULL) && (argv[3] == NULL)) {
       /*Nur Eingabe-Parameter angegeben*/
    
          eingabe = open(argv[2], O_RDONLY);
          n = copy(eingabe, STDOUT);
    
       } else if((option == 1) && (argv[2] != NULL) && (argv[3] != NULL)) {
       /* Eingabe- und Ausgabe-Parameter (mit Option) */
    
          eingabe = open(argv[2], O_RDONLY);
          ausgabe = open(argv[3], O_WRONLY);
          n = copy(eingabe, ausgabe);
       } 
    }
    int checkoption(char *arg, char *opt)
    {
       if(arg[0] == '-' && arg[1] == opt[0])
          return TRUE;
    
    return FALSE;
    }
    

    Ich muss dazu sagen, dass die einzelnen if-Zweige (in denen auf Parameter geprüft wird) noch nicht stimmen (bis auf den 1. nach der Prüfung auf Option), gerade deswegen, weil ich nicht wirklich sicher bin wie ich am besten prüfen soll.



  • Dein Code sieht schrecklich aus.
    Und ja argv auf NULL zu überprüfen ist extrem unflexibel
    und fehleranfällig weil du auf Speicherbereich zugreifst
    der dich nicht wirklich was angeht:

    Kleines Beispiel zum Nachdenken:

    #include <stdio.h>
    
    int main (int argc, char *argv[]) {
    
            if(argv[1] == NULL && argv[2] != NULL)
                    printf("%s\n",argv[2]);
    
            return 0;
    }
    

    Soll dir einfach zeigen dass nur weil du kein Argument
    eingegeben hast der übrige Speicher nicht unbedingt NULL ist.

    Darf man fragen wieso du die vorgefertigten Funktionen
    nicht verwenden willst?

    Dein Problem und deine Vorgehensweise erinnern mich ein wenig an diesen Thread
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-195632-and-highlight-is-.html
    Bluma löst das Ganze mit argc.

    PS:
    Ihr beide arbeitet nicht zufällig an derselben Hausaufgabe?



  • ich würde auch noch boost::program_options oder wie das heißt empfehlen, is auch sehr gut.

    Wenn dus selbst machen möchtest, dann würde ich dir empfehlen die parameter stück wür stück zu lesen und in einen std::vector zu speichern, bzw. jeden parametere einzeln zu gucken, ob er mit - beginnt, dann ists ne options, die beiden parameter ohne - sind dann deine dateien. Wenn eine Option gesetzt ist, setzt du ein flag und machst dann eben abhängig von dem flag das gewünschte



  • Hallo,

    habe den obigen Code in die Tonne gekloppt und es auch über den Argumentencount gelöst. Habe aber noch ein kleines Problem:

    int main(int argc, char *argv[])
    {
       int n = 0;
       int eingabe = 0;
       int ausgabe = 0;
    
       eingabe = open(argv[2], O_RDONLY);
       n = kopieren(eingabe, 1);  
    }
    

    Die Datei wird ohne Pfadeingabe anstandslos eingelesen und auf dem Bildschirm wieder ausgegeben. Mit Pfad allerdings nicht (wegen / vielleicht?). Wo liegt mein Fehler?



  • Die Pfadangabe sollte sowohl mit relativen als auch absoluten
    Angaben so funktionieren.
    Wie liest du also den Pfad ein?
    Vll. liegt da der Fehler. Lass dir vll. auch mal
    den Pfad nochmal vor dem open ausgeben, dann siehst
    du ob er korrekt eingelesen wurde.

    Bevor du nachher fragen tust warum du die geschriebene
    Datei nicht öffnen kannst: http://www.c-plusplus.net/forum/viewtopic-var-t-is-195751-and-highlight-is-.html



  • Ich gebe den Pfad über die Kommandozeile wie folgt ein:

    - (ohne Pfad): kommando ein.txt
    - (mit Pfad): kommando /tmp/ein.txt


Log in to reply