이번에는 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>
/* 플래그는 `--verbose' 에 의해 설정한다. */
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}
};
/* getopt_long는 이곳에 옵션 인덱스를 저장한다. */
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 '?':
/* getopt_long는 이미 에러 메시지를 프린트했다. */
break;
default:
abort ();
}
}
/* 그들이 맞추쳤던 것으로 `--verbose'와 `--brief'를 보고하는 대신에, 우리는 그들로부터 나온 결
과로 마지막 상황을 보고한다. */
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);
}