문제

C에서 getOpt_long은 선택적인 인수를 명령 줄 매개 변수 매개 변수에 구문 분석하지 않습니다.

프로그램을 실행할 때 선택적 인수는 아래의 예제처럼 인식되지 않습니다.

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

테스트 코드는 다음과 같습니다.

#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;
}
도움이 되었습니까?

해결책

GLIBC 문서 또는 GetOpt Man 페이지에는 언급되지 않았지만 긴 스타일 명령 줄 매개 변수에 대한 선택적 인수는 'Equals Sign'(=)을 요구합니다. 옵션 인수를 매개 변수에서 분리하는 공간은 작동하지 않습니다.

테스트 코드에서 실행되는 예제 :

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

다른 팁

Man Page는 확실히 잘 문서화하지 않지만 소스 코드는 약간 도움이됩니다.

간단히 : 당신은 다음과 같은 일을해야합니다 (이것은 약간 과장된 것일 수 있지만) :

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

_getOpt_internal 이전의 주석 중에서 :

...

만약에 getopt 다른 옵션 캐릭터를 찾으면 해당 캐릭터를 반환하고 업데이트 optind 그리고 nextchar 다음에 전화를 걸었습니다 getopt 다음 옵션 문자 또는 Argv-Element로 스캔을 재개 할 수 있습니다.

더 이상 옵션 문자가없는 경우 getopt 반환 -1. 그 다음에 optind 옵션이 아닌 첫 번째 ARGV 요소의 ARGV의 색인입니다. (ARGV- 요소는 옵션이 아닌 사람들이 이제 마지막으로 오도록 순열되었습니다.) <-- a note from me: if the 3rd argument to getopt_long starts with a dash, argv will not be permuted

...

OptString의 숯이 콜론이 뒤 따르는 경우 ARG를 원한다는 것을 의미하므로 ARGV 요소의 다음 텍스트 또는 다음 argv-element의 텍스트가 반환됩니다. optarg. 두 개의 콜론은 옵션 인 Arg를 원하는 옵션을 의미합니다. 현재 ARGV 요소에 텍스트가 있으면 반환됩니다. optarg, 그렇지 않으면 optarg 0으로 설정됩니다.

...

... 라인 사이를 읽어야하지만. 다음은 원하는 것을 수행합니다.

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

나는 또한 같은 문제에 부딪쳐서 여기에왔다. 그런 다음 이것을 깨달았습니다. "옵션 _argument"의 사용 사례가 많지 않습니다. 옵션이 필요한 경우 프로그램 로직에서 확인하면 옵션이 선택 사항 인 경우 GetOpt 레벨에서 모든 옵션이 선택 사항이므로 필수가 아니므로 "옵션 _argument"의 사용 사례가 없습니다. 도움이 되었기를 바랍니다.

PS : 위의 예에서는 올바른 옵션이 -praise -praise-name "name"-Blame-Name "Name"이라고 생각합니다.

공간 문자가없는 매개 변수 옆에 인수를 작성하면 동등한도 작동하지 않습니다. 예를 들어:

$ ./respond --blameJohn
You suck John!
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top