getopt は、オプションの引数をパラメーターに解析しません

glibc のドキュメントや getopt のマニュアル ページには記載されていませんが、長い形式のコマンド ライン パラメーターに対するオプションの引数には、「等号」(=) が必要です。オプションの引数とパラメーターを区切るスペースは機能しません。

テスト コードでの実行例:


マニュアル ページは確かにそれを十分に文書化していませんが、ソース コードは少し役に立ちます。

簡単に言えば、次のようなことを行うことになっています (ただし、これは少し専門的すぎるかもしれません):

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

...ただし、行間を読む必要があります。以下はあなたが望むことをします:

#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[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;
}