getopt ikke analysere valgfrie argumenter til parametere

stemmer
38

I C, betyr getopt_long ikke analysere de valgfrie argumenter for å kommandere linjeparametrene parametere.

Når jeg kjører programmet, er det valgfritt argument ikke er anerkjent som et eksempel kjøre under.

$ ./respond --praise John
Kudos to John
$ ./respond --blame John
You suck !
$ ./respond --blame
You suck !

Her er en test kode.

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

int main(int argc, char ** argv )
{
    int getopt_ret, option_index;
    static struct option long_options[] = {
               {praise,  required_argument, 0, 'p'},
               {blame,  optional_argument, 0, 'b'},
               {0, 0, 0, 0}       };
    while (1) {
        getopt_ret = getopt_long( argc, argv, p:b::,
                                  long_options,  &option_index);
        if (getopt_ret == -1) break;

        switch(getopt_ret)
        {
            case 0: break;
            case 'p':
                printf(Kudos to %s\n, optarg); break;
            case 'b':
                printf(You suck );
                if (optarg)
                    printf (, %s!\n, optarg);
                else
                    printf (!\n, optarg);
                break;
            case '?':
                printf(Unknown option\n); break;
        }
    } 
    return 0;
}
Publisert på 27/06/2009 klokken 12:15
kilden bruker
På andre språk...                            


4 svar

stemmer
78

Selv om det ikke er nevnt i glibc dokumentasjon eller getopt mannen siden, valgfrie argumenter til lang stil kommandolinjeparametere krever 'likhetstegn (=). Volumet som skiller valgfri argument fra parameteren ikke fungerer.

Et eksempel kjøre med test-koden:

$ ./respond --praise John
Kudos to John
$ ./respond --praise=John
Kudos to John
$ ./respond --blame John
You suck !
$ ./respond --blame=John
You suck , John!
Svarte 27/06/2009 kl. 12:18
kilden bruker

stemmer
1

Jeg kjørte inn i det samme problemet og kom hit. Da jeg innså dette. Du har ikke mye av en bruk tilfelle av "optional_argument". Hvis et alternativ er påkrevd du sjekke fra programmet logikk, hvis et alternativ er valgfritt så du trenger ikke gjøre noe fordi på getopt nivå alle alternativene er valgfrie, de er ikke obligatorisk, så det er ingen bruk tilfelle av "optional_argument". Håper dette hjelper.

ps: for eksempelet over tror jeg de riktige alternativene er --praise --praise-navnet "navn" --blame --blame-navnet "navn"

Svarte 06/09/2015 kl. 21:46
kilden bruker

stemmer
9

Mannen side absolutt ikke dokumentere det veldig bra, men kildekoden hjelper litt.

Kort: du skal gjøre noe som følgende (selv om dette kan være litt over-pedantisk):

if(   !optarg
   && optind < argc // make sure optind is valid
   && NULL != argv[optind] // make sure it's not a null string
   && '\0' != argv[optind][0] // ... or an empty string
   && '-' != argv[optind][0] // ... or another option
  ) {
  // update optind so the next getopt_long invocation skips argv[optind]
  my_optarg = argv[optind++];
}
/* ... */

Blant kommentarene foregå _getopt_internal:

...

Hvis getoptfinner et annet alternativ karakter, returnerer den det tegnet, oppdateringoptind og nextcharslik at den neste samtalen til getoptkan gjenoppta skanningen med følgende alternativ tegnet eller ARGV-element.

Hvis det ikke finnes flere alternative tegn, getoptreturnerer -1. Da optinder indeksen i ARGV av første ARGV-element som ikke er et alternativ. (Argv-elementer har blitt permuted slik at de som ikke er alternativer nå kommer sist.)<-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted

...

Hvis en char i OPTSTRING er etterfulgt av et kolon, som betyr at det vil ha en arg, så den følgende tekst i samme ARGV-element, eller teksten i det følgende ARGV-element, returneres i optarg. To kolon betyr en opsjon som ønsker en valgfri arg; hvis det er tekst i det aktuelle ARGV-element, returneres i optarg, ellers optargsettes til null .

...

... om du må gjøre noe lesing mellom linjene. Følgende gjør hva du vil:

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

int main(int argc, char* argv[] ) {
  int getopt_ret;
  int option_index;
  static struct option long_options[] = {
      {"praise",  required_argument, 0, 'p'}
    , {"blame",  optional_argument, 0, 'b'}
    , {0, 0, 0, 0}
  };

  while( -1 != ( getopt_ret = getopt_long(  argc
                                          , argv
                                          , "p:b::"
                                          , long_options
                                          , &option_index) ) ) {
    const char *tmp_optarg = optarg;
    switch( getopt_ret ) {
      case 0: break;
      case 1:
        // handle non-option arguments here if you put a `-`
        // at the beginning of getopt_long's 3rd argument
        break;
      case 'p':
        printf("Kudos to %s\n", optarg); break;
      case 'b':
        if(   !optarg
           && NULL != argv[optindex]
           && '-' != argv[optindex][0] ) {
          // This is what makes it work; if `optarg` isn't set
          // and argv[optindex] doesn't look like another option,
          // then assume it's our parameter and overtly modify optindex
          // to compensate.
          //
          // I'm not terribly fond of how this is done in the getopt
          // API, but if you look at the man page it documents the
          // existence of `optarg`, `optindex`, etc, and they're
          // not marked const -- implying they expect and intend you
          // to modify them if needed.
          tmp_optarg = argv[optindex++];
        }
        printf( "You suck" );
        if (tmp_optarg) {
          printf (", %s!\n", tmp_optarg);
        } else {
          printf ("!\n");
        }
        break;
      case '?':
        printf("Unknown option\n");
        break;
      default:
        printf( "Unknown: getopt_ret == %d\n", getopt_ret );
        break;
    }
  }
  return 0;
}
Svarte 14/09/2015 kl. 23:14
kilden bruker

stemmer
-3

Hvis du skriver argumentet ved siden av parameter uten mellomrom verken lik fungerer også. For eksempel:

$ ./respond --blameJohn
You suck John!
Svarte 16/05/2017 kl. 08:22
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more