메뉴 건너뛰기


Developer > Application


UNIX에 명령어 파라미터를 받아들이는 일반적인 방법으로 getopt()함수를 사용한다.
이 함수는 UNIX의 getopt.h 헤더를 include하여 사용할 수 있다.
또한 GNU계열에서는 getopt()뿐만아니라 getopt_long()이라는 긴 이름의 파라미터를 명령으로 받아들이는 함수가 존재한다.
 
 
이 곳에는 Windows에서도 getopt()와 getopt_long()을 사용할 수 있도록 제공하고 있다.
 
getopt()와 getopt_long()의 사용방법은 다음과 같다.
 
시스템은 main 함수를 호출함으로써 C 프로그램을 시작한다.  그것은 당신이 프로그램을 만들 때 
main 이라 이름지어진 함수를 꼭 만들어야 함을 의미하고_그것을 하지 않았을 때 에러없이 프로그
램을 링크할 수 없을 것이다.

main 함수는 아무런 인수를 취하지 않거나, 커멘드 라인에서 받아들이는 인수를 나타내는 두 개의 
인수를 취한다. 다음처럼.

      int main (int argc, char *argv[])
커멘드 라인 인수들은 공백으로 분리된 토큰으로써 프로그램을 호출하도록 쉘 커맨드에 주어진다; 
그래서, `cat foo bar'라고 했을 때 인수는 `foo' 와 `bar'가 된다.  어떤 프로그램에서 커맨드 라인에 
인수를 넣는 방법은 오직 main함수의 인수를 통해서 가능하다.  만일 main 함수가 인수를 취하지 
않는다면, 당신은 커맨드 라인에서 인수를 취할 수 없다. 

argc 인수는 커맨드 라인 인수들의 개수를 말하고, argv 인수는 C 문자열의 벡터이다; argv의 각 
요소들은 공백으로 분리된 개별적인 커맨드 라인 인수 문자열이다.  실행시키려는 프로그램의 파일
이름 또한 첫 번째 요소로써 벡터안에 포함된다.  argc의 값은 이 요소들의 개수이다. 널 포인터가 
항상 마지막 요소가 된다: 즉, argv[argc]는 널 포인터이다. 커맨드 `cat foo bar' 에서, argc는 3이고, 
argv는 "cat", "foo", 그리고 "bar" 라는 세 개의 요소들을 갖는다.

만일 당신의 프로그램에서 커맨드 라인 인수들의 구분이 간단하다면, 당신은 직접 argv로부터 간단
하게 하나씩 인수를 가져올 수 있다. 당신의 프로그램이 한정된 인수들의 개수를 갖지않거나, 모든 
인수들을 한꺼번에 취하지 않는다면 같은 방법으로 인수들을 취할 수 있지만, 그렇지 않다면 그것을 
구문분석 하기 위해서 getopt를 사용해서 인수들을 취해야 할 것이다.

22.1.1  프로그램 인수 구문 관례들.
POSIX 에서 커맨드 라인 인수들을 위해서 다음과 같은 관례들을 권장하고 있다.  getopt(22.1.2 
[Parsing Options] 312 페이지 참조)는 다음의 권장사항을 쉽게 충족시키도록 만든다.

둁 하이픈(hyphen (`_') ) 구획문자(delimiter)로 시작하는 인수들은 옵션이 있다.
둁 한 개의 토큰에서 한 개의 하이픈 구획문자 뒤에 따르는 것은, 만일 그 옵션들이 인수들을 취하
지 않는다면 다중 옵션이 된다. 그래서, `-abc'는 `-a -b -c'와 동등하다.

둁 옵션 이름들은 단일한 알파벳 문자들이다( isalnum에 관하여; 4.1절[Classification of Characters] 
41 페이지 참조)

둁 어떤 옵션들을 인수를 필요로 한다.  예를들어, ld 명령의 `-o' 옵션은 출력 파일 이름으로 하나의 
인수를 필요로 한다.

둁 옵션과 옵션이 필요로 하는 인수들은 토큰으로 분리되어 나타날 수도 있고, 그렇지 않을 수도 있
다. (즉, 그들을 분리하는 공백문자는 선택적 이다. ) 그래서, `-o foo' 와 `-ofoo'는 동등한다.

둁 옵션들은 전형적으로 다른 비-옵션 인수들에 선행된다.
GNU C 라이브러리에 있는 getopt의 구현은 당신의 프로그램을 사용하는 사용자가 심지어 옵션과 
비-옵션 인수들을 혼합했을지라도, 구문분석을 위해서 모든 비-옵션 인수들전에 옵션 인수들이 나타
나도록 만든다. 

둁 인수 `--'는 모든 옵션들을 종결시킨다; 다음에 따르는 인수들은 그들이 하이픈으로 시작할지라
도, 비-옵션 인수들로 취급된다.

둁 한 개의 하이픈 문자가 들어가있는 토큰은 보통 비-옵션 인수로써 취급된다.  관례상, 그것은 기
본 입력과 출력 스트림으로 입력이나 출력을 정하기 위해서 사용된다.

둁 옵션들은 어떤 순서대로 공급되어지고, 또는 여러번 중복해서 나타나기도 할 것이다.  해석은 특
정한 응용 프로그램이 맨 왼쪽에 있다고 해석한다.

GNU 는 그들의 관례에 따라서 긴 옵션을 더한다.  긴 옵션들은 `--'뒤에 따르는 이름으로 구성되
는데 그 이름은 영숫자와 대쉬들로 구성된다. 옵션 이름들은 전형적으로 하나에서 세 개 단어의 길
이를 갖고, 그들은 하이픈으로 단어들을 분리한다.  사용자들은 옵션을 대표하는 약자가 단일 하다면 
얼마든지 옵션이름들을 축약할 수 있다.  한 개의 긴 옵션을 위한 인수를 정하기위해서는, 
`--name=value'라고 써라. 이 구문은 선택적인 인수를 받아들이는 긴 옵션을 가능하게한다. GNU 
시스템은 쉘에서 긴 옵션 이름을 지원할 것이다.

22.1.2  프로그램 옵션들을 구문분석하기.
이번에는 getopt 함수를 어떻게 호출하는지에 대해서 자세히 설명한다. 이 기능을 사용하기 위해서, 
당신의 프로그램에 헤더파일 `unistd.h'을 포함시켜야만 한다.

변수 :   int opterr
만일 이 변수의 값이 0이 아니면, getopt는 만일 알지못하는 옵션 문자가 들어오거나 인수를 필요로
하는 옵션이 옵션을 갖고있지 않다면 표준 에러 스트림에 에러메세지를 프린트한다. 이것은 디폴트 
동작이다.  만일 당신이 이 변수를 0으로 설정하면, getopt는 아무런 메시지도 프린트하지는 않지만, 
에러를 지적하기 위해서 여전히 ? 문자를 여전히 리턴한다.

변수 :   int optopt
getopt가 알려지지 않은 옵션 문자와 만나거나 필요한 인수가 빠져있는 옵션일 때, getopt는 그 옵션 
문자를 이 변수에 저장한다.  당신은 자신만의 진단 메시지를 제공하기 이해서 이 변수를 사용할 수 
있다.

변수 :   int optind
이 변수는 앞으로 분석할 배열 argv의 다음 요소에 대한 인덱스로 getopt에 의해 설정된다.  일단 
getopt가 옵션 인수들 모두를 발견했다면, 당신은 나머지 비-옵션 인수들이 어디에서 시작하는지 결
정하기 위해서 이 변수를 사용할 수 있다.  이 변수의 초기값은 1이다.

변수 :   chat *optarg
이 변수는 인수들을 받아들이는 옵션들을 위해서, 옵션 인수들의 값을 가리키는 포인터로써 getopt
에 의해 설정된다.

함수 :   int getopt(int argc, char **argv, const char *options)
getopt 함수는 argv와 argc 인수들에의해 지정된 인수 목록으로부터 다음 옵션 인수를 얻는다.  보
통, 그들 값들은 main에 의해 받아 들여진 인수들로부터 직접적으로 온다.  옵션 인수는 이 프로그
램에서 유용하게 쓰일 옵션 문자들을 지정한 문자열이다.  문자열안에 있는 옵션 문자는 인수가 필
요함을 알리기 위해서 콜론(`:')의 다음에 나타난다.

만일 옵션 인수 문자열이 하이픈(`-')으로 시작한다면, 이것은 특별하게 취급된다.  그들은 옵션 문
자가 `\0'인것처럼 리턴되어, 옵션이 없는 인수들을 허용한다.  getopt 함수는 다음 커맨드 라인옵션
의 옵션 문자를 리턴한다.  더 이상 유용한 옵션 인수들이 없을 때, -1을 리턴한다.  그곳은 이제 비
-옵션 인수들이 있을 것이다; 당신은 이것을 체크하기 위해서 argc 파라미터에 대응하는

외부변수 optind를 비교해야만 한다. 
만일 어떤 옵션이 인수를 가진다면, getopt 는 변수들 optarg안에 그것을 저장함으로써 인수를 리턴
한다.  당신이 덧씌워질지도 모르는 정적 변수가 아닌, 보통의 argv 배열을 가리키는 포인터를 라면, 
optarg 문자열을 복사할 필요가 없다.

만일 알려지지 않은 옵션문자를 사용하거나, 옵션 인수가 빠져있다면 getopt는 `?'를 리턴하고 현재 
옵션 문자로 외부변수 optopt를 설정한다.  만일 옵션의 첫 번째 문자가 콜론(`:') 이라면, getopt는 
옵션 인수가 빠져있음을 알리기 위해서 `?' 대신에 `:'를 리턴한다. 또한, 만일 외부변수 opterr이 0
이 아니면(디폴트이다.), getopt는 에러 메시지를 출력한다.

22.1.3  getopt를 사용해서 인수를 구문분석하는 예제.
다음은 getopt가 전형적으로 어떻게 사용되는지를 보여주는 예제이다. 핵심은 다음과 같다:
둁 보통, getopt는 루프안에서 호출된다.  getopt가 더 이상 나타난 옵션이 없음을 알리기 위해서 -1
을 리턴하면, 루프는 종료한다.

둁 switch 구문은 getopt로부터의 리턴값에 따른 각각의 처리에 사용된다. 각각의 경우는 프로그램에
서 나중에 사용될 변수를 설정하게 된다.

둁 두 번째 루프는 남아있는 비-옵션 인수들을 처리하는데 사용된다.
  #include  <unistd.h>
  #include  <stdio.h> 

  int
  main  (int  argc,  char  **argv)
  {
     int  aflag  =  0;
     int  bflag  =  0;
     char  *cvalue  =  NULL;
     int  index;
     int  c; 

     opterr  =  0; 

     while  ((c  =  getopt  (argc,  argv,  "abc:"))  !=  -1)
       switch  (c)
          {
          case  'a':
            aflag  =  1;
            break;
     case  'b':
            bflag  =  1;
            break;
          case  'c':
            cvalue  =  optarg;
            break;
          case  '?':
            if  (isprint  (optopt))
               fprintf(stderr, "Unknown option `-%c'.\n", optopt);
            else
               fprintf  (stderr,
                         "Unknown option character `\\x%x'.\n", optopt);
            return  1;
      default:
            abort  ();
          } 

     printf("aflag = %d, bflag = %d, cvalue = %s\n", aflag, bflag, cvalue); 

     for  (index  =  optind;  index  <  argc;  index++)
       printf  ("Non-option  argument  %s\n",  argv[index]);
     return  0;
  }
다음은 위의 프로그램을 여러 가지 인수들의 조합을 사용했을 때 어떤 결과를 나타내는지에 대한 
예이다.

%  testopt
aflag  =  0,  bflag  =  0,  cvalue  =  (null) 

%  testopt  -a  -b
aflag  =  1,  bflag  =  1,  cvalue  =  (null) 

%  testopt  -ab
aflag  =  1,  bflag  =  1,  cvalue  =  (null) 

%  testopt  -c  foo
aflag  =  0,  bflag  =  0,  cvalue  =  foo 

%  testopt  -cfoo
aflag  =  0,  bflag  =  0,  cvalue  =  foo 

%  testopt  arg1
aflag  =  0,  bflag  =  0,  cvalue  =  (null)
Non-option  argument  arg1 

%  testopt  -a  arg1
aflag  =  1,  bflag  =  0,  cvalue  =  (null)
Non-option  argument  arg1 

%  testopt  -c  foo  arg1
aflag  =  0,  bflag  =  0,  cvalue  =  foo
Non-option  argument  arg1 

%  testopt  -a  --  -b
aflag  =  1,  bflag  =  0,  cvalue  =  (null)
Non-option  argument  -b 

%  testopt  -a  -
aflag  =  1,  bflag  =  0,  cvalue  =  (null)
Non-option  argument  -
22.1.4  긴 옵션들을 구문분석하기.
단일한-문자 옵션들로만 되어있는 GNU-스타일의 긴 옵션들을 받아들이기 위해서는 getopt 대신에 
getopt_long를 사용한다.  당신은 이런 가외의 작은 작업을 통해서 모든 프로그램이 긴 옵션들을 받
아들이게 만들 수 있고, 초보자들에게 어떻게 그 프로그램을 사용하는지 도울 수있다.

데이터 타입 :   struct option
이 구조체는 getopt_long을 위한 단일한 긴 옵션 이름을 설명한다. 긴 옵션을 구성하는 옵션의 하나
인 인수 longopts는 그들 구조체의 배열이 되어야만 한다.  그 배열은 0으로 채워진 요소로써 끝난
다. struct option 구조체는 다음과 같은 필드를 갖는다.

const char *name
이 필드는 옵션의 이름으로 문자열이다.
int has_arg
이 필드는 옵션이 인수를 취하는지 또는 취하지 않는지의 여부를 알린다.  그것은 정수이고 그곳에 
세 개의 합리적인 값들이 있다: no_argument, required argument, 그리고 optional_argument

int *flag
int val  
이 필드들은 그 옵션이 발생할 때 옵션에 대하여 어떻게 보고를 하거나 동작할것인지를 제어한다. 
만일 flag가 널 포인터라면, val은 이 옵션을 대표하는 값이다.  종종 그 값들은 특정한 긴 옵션들의 
단일함을 확인하기 위해서 선택되어진다.  만일 플래그가 널 포인터가 아니라면, 그것은 이 옵션을 
위한 플래그인 int형 변수의 주소가 되어질 것이다. val안의 값은 나타난 옵션을 지적하도록 플래그 
안에 저장하기 위한 값이다.

함수 : 
int getopt__long (int argc, char **argv, const char *shortopts, struct 
option *longopts, int *indexptr)

벡터 argv ( 길이는 argc이다.)로부터 옵션들을 해독한다.  인수 shortopts는 getopt가 해독할 수 있
는 만큼의 짧은 옵션을 나타내고, 인수 longopts는 받아들이기 위한 긴 옵션들을 나타낸다. 
getopt_long이 짧은 옵션을 만났을 때, 그것은 getopt가 하는것과 같은 일을 한다: 그것은 옵션을 위
한 문자 코드를 리턴하고, optarg에 옵션 인수들을(만일 그것이한 개를 가진다면) 저장한다.

getopt_long가 긴 옵션을 만났을 때, 그것은 그 옵션을 정의하는 flag 와 val 필드에 기초한 동작들
을 취한다.

만일 flag가 널 포인터라면, getopt_long 은 발견한 옵션을 지적하도록 val의 내용을 리턴한다.  당신
이 다른 의미를 가진 옵션을 위해서 val 필드안에 별개의 값들을 배열하면, 당신은 getopt_long이 리
턴한 후에 그들 값을 해독할 수 있다.  만일 긴 옵션이 짧은 옵션과 동일하다면, 당신은 짭은 옵션의 
문자 코드를 사용할 수 있다.

만일 flag가 널 포인터가 아니라면, 단지 프로그램안에서 flag가 설정된 이 옵션을 의미한다.  flag는 
당신이 정의한 int형의 변수이다.  flag 필드안에 그 플래그의 주소를 저장하라.  flag에 저장하려는 
옵션값을 val 필드안에 저장하라.  이 경우, getopt_long는0을 리턴한다.

어떤 긴 옵션에서, getopt_long는 배열 longopts안의 옵션 정의에 대한 인덱스를, *indexptr에 저장하
여 알린다.  당신은 longopts[*indexptr].name 으로 옵션의 이름을 얻을 수 있다. 그래서 당신은 그들
의 val 필드안에 있는 값이나, 그들의 인덱스에 의해서 긴 옵션들을 구분할 수 있다.  당신은 플래그
를 설정한 긴 옵션들을 이 방법으로 구분할 수 있다.

어떤 긴 옵션이 인수를 가질 때, getopt_long는 리턴하기 전에 변수 optarg안에 인수값을 저장한다.  
어떤 옵션이 아무런 인수를 가지지 않을 때, optarg안의 값은 널 포인터이다.  이것은 공급된인수가 
옵션을 가졌는지 아닌지에 대한 여부를 당신에게 알리는 방법인 것이다.  getopt_long는 더 이상 처
리할 옵션들이 없을 때, -1을 리턴하고, 다음 남아있는 인수의 argv 인덱스를 변수 optind 안에 남긴
다.

22.1.5  긴 옵션들의 구분분석에 대한 예제.
   #include  <stdio.h> 


      static  int  verbose_flag; 

      int
      main  (argc,  argv)
             int  argc;
             char  **argv;
      {
         int  c; 

         while  (1)
           {
              static  struct  option  long_options[]  =
                {

                   {"verbose",  0,  &verbose_flag,  1},
                   {"brief",  0,  &verbose_flag,  0},

                   {"add",  1,  0,  0},
                   {"append",  0,  0,  0},
                   {"delete",  1,  0,  0},
               {"create",  0,  0,  0},
                   {"file",  1,  0,  0},
                   {0,  0,  0,  0}
                };

              int  option_index  =  0; 

              c  =  getopt_long  (argc,  argv,  "abc:d:", long_options,  &option_index); 


              if  (c  ==  -1)
                break; 

              switch  (c)
                {
                case  0:

                   if  (long_options[option_index].flag  !=  0)
                     break;
                   printf("option %s", long_options[option_index].name);
                   if (optarg)
                     printf("  with  arg  %s",  optarg);
                   printf("\n");
                   break; 

                case  'a':
                   puts("option  -a\n");
                   break; 

                case  'b':
                   puts("option  -b\n");
                   break; 

                case  'c':
                   printf("option  -c  with  value  `%s'\n",  optarg);
   break; 

                case  'd':
                   printf("option  -d  with  value  `%s'\n",  optarg);
                   break; 

                case  '?':

                   break; 

                default:
                   abort  ();
                }
           } 


         if  (verbose_flag)
           puts  ("verbose  flag  is  set"); 


         if  (optind  <  argc)
           {
              printf  ("non-option  ARGV-elements:  ");
              while  (optind  <  argc)
                printf  ("%s  ",  argv[optind++]);
              putchar  ('\n');
           } 

         exit  (0);
      }

 
이곳에는 GNU C Library에 대한 설명을 볼 수 있다.