Problem mit optionalen Parametern in getopt

younix

I need more knowledge.
Hallo,

ich habe ein Problem mit optionalen Parametern in getopt.

Ich habe ein kleines Beispiel Programm, welches sich anderes verhält, als ich es aus der Dokumentation von getopt herrausgelesen habe.

Quelltext von "prog.c":
PHP:
#include <stdio.h>
#include <unistd.h>

int main( int argc, char **argv)
{
        int a = 0;
        int b = 0;
        int c = 0;
        int d = 0;
        int opt = 0;

        while ((opt = getopt(argc, argv, "ab:c::d")) != -1) {
                switch (opt) {
                        case 'a':
                                a = 1;
                                printf("a: %s\n", optarg);
                                break;
                        case 'b':
                                b = 1;
                                printf("b: %s\n", optarg);
                                break;
                        case 'c':
                                c = 1;
                                printf("c: %s\n", optarg);
                                break;
                        case 'd':
                                d = 1;
                                printf("d: %s\n", optarg);
                                break;
                        default:
                                printf( "usage error1\n");
                                exit(1);
                }
        }

        printf("a: %d\n", a);
        printf("b: %d\n", b);
        printf("c: %d\n", c);
        printf("d: %d\n", d);

        return 0;
}

Ich habe das Programm übersetzt mit:
"gcc prog.c -o prog"

Laut Dokumentation (Manpage) sollte der Paramter "c::" ein optionales Argument unterstützen. Aber wenn ich "prog -c blub" ausführe, dann verhält sich das Programm als wenn ich nur "c" als parameter von getopt() gewählt hätte.

In anderen Quelltexten, die ich gesehen haben, wurde es genau so implementiert. Aber bei mir funktioniert es komischer weise nicht.
Ich erhalte immer "c: (null)" als Ausgabe für das Argument.

Ausgaben:
PHP:
./prog -c blub
c: (null)
a: 0
b: 0
c: 1
d: 0

./prog -b blub
b: blub
a: 0
b: 1
c: 0
d: 0

Getestet habe ich es unter OpenBSD 4.3 und Debian/Etch.
Das Programm verhält sich in den beiden Systemen gleich.

Kennt einer von euch das Problem oder weiss wo mein Fehler liegt?

danke, younix
 
Soweit ich weiss, ist nur ein Doppelpunkt notwendig und hinter c stehen zwei. Die while() Schleife sollte demnach so aussehen:
Code:
while ((opt = getopt(argc, argv, "ab:c:d")) != -1) {

Bei Deiner Ausgabe sieht man ja, dass es mit -b auch funktioniert.

HTH

Edit: Zu schnell geantwortet und falsch gelesen. :(
 
Code:
$ ./prog -c
c: (null)
a: 0
b: 0
c: 1
d: 0
$ ./prog -c blub
c: (null)
a: 0
b: 0
c: 1
d: 0
$ ./prog -cblub
c: blub
a: 0
b: 0
c: 1
d: 0
$ uname -rs
OpenBSD 4.3
Da ist die Doku wohl etwas ungenau.

Ein Blick in den Quellcode (Datei src/lib/libc/stdlib/getopt_long.c, Funktion getopt_internal) bestaetigt zudem, dass optionale Argumente nur ohne Leerzeichen uebergeben werden duerfen.

Und es gibt sogar eine Begruendung:
Back out change in rev 1.15 of to allow whitespace to separate a
flag from its optional argument if permutation is disabled. The
idea was that since "r:" would match "-r foo" then "r::" should
match "-r foo" too as long as we know that things have not been
reshuffled. Unfortunately, this causes incompatibilities with GNU
getopt_long when the POSIXLY_CORRECT environment variable is set.

Hoffe, geholfen zu haben.
 
Danke yetano.

Ich werde in Zukunft die Sourcen in meine Lesereihe(FAQ, Manpage, Google) mit aufnehmen ;-)
 
Zurück
Oben