getopt does not parse optional arguments to parameters

后端 未结 3 1886
感情败类
感情败类 2020-12-01 03:15

In C, getopt_long does not parse the optional arguments to command line parameters parameters.

When I run the program, the optional argument is not recognized like t

3条回答
  •  伪装坚强ぢ
    2020-12-01 04:16

    The man page certainly doesn't document it very well, but the source code helps a little.

    Briefly: you're supposed to do something like the following (though this may be a little over-pedantic):

    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++];
    }
    /* ... */
    

    From among the comments preceding _getopt_internal:

    ...

    If getopt finds another option character, it returns that character, updating optind and nextchar so that the next call to getopt can resume the scan with the following option character or ARGV-element.

    If there are no more option characters, getopt returns -1. Then optind is the index in ARGV of the first ARGV-element that is not an option. (The ARGV-elements have been permuted so that those that are not options now come last.) <-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted

    ...

    If a char in OPTSTRING is followed by a colon, that means it wants an arg, so the following text in the same ARGV-element, or the text of the following ARGV-element, is returned in optarg. Two colons mean an option that wants an optional arg; if there is text in the current ARGV-element, it is returned in optarg, otherwise optarg is set to zero.

    ...

    ... though you have to do some reading between the lines. The following does what you want:

    #include 
    #include 
    
    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[optind]
               && '-' != argv[optind][0] ) {
              // This is what makes it work; if `optarg` isn't set
              // and argv[optind] doesn't look like another option,
              // then assume it's our parameter and overtly modify optind
              // 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`, `optind`, etc, and they're
              // not marked const -- implying they expect and intend you
              // to modify them if needed.
              tmp_optarg = argv[optind++];
            }
            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;
    }
    

提交回复
热议问题