C getopt_long() 실행 시 긴 이름의 옵션 사용 함수
프로그램을 실행할 때의 옵션을 처리합니다.
- 헤더: getopt.h
- 형태: int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex) - 인수: int argc 인수의 개수
char * const argv[] 인수 내용
const char *optstring 검색하려는 짧은 옵션들의 문자열
const struct option *longopts 검색하려는 긴 이름의 옵션 모음
int *longindex 옵션에 해당되는 색인 번호 - 반환: int 0 == 긴 이름의 옵션
-1 == 옵션 분석을 모두 마침
나머지는 getopt()와 동일
getopt_long()은 getopt()처럼 프로그램을 실행할 때의 옵션을 확인합니다. 예를 들어 아래와 같이 프로그램을 실행할 수 있습니다.
]$ ./sample-app -r -c -f test.txt
실행 시 입력한 옵션을 프로그램에서 처리하기 위해서 main()함수의 argc 나 argv를 직접 사용하기에는 여러 모로 불편합니다. 대신에 getopt() 함수를 이용하는 것이 편합니다. 그러나 getopt() 함수로 처리하는 옵션은 -r -c 와 같이 문자 하나만 사용하는 옵션에만 사용할 수 있습니다. 즉, 아래와 같이 긴 이름의 옵션을 사용하지 못합니다.
]$ ./sample-app --repeat --filename=test.txt
옵션이라도 문자 하나 보다는 긴 이름의 옵션을 사용하는 것이 편합니다. 이런 긴 이름의 옵션을 쉽게 사용할 수 있도록 해주는 함수가 getopt_long() 함수입니다.
실행 옵션 관련 함수
- getopt() : '-'로 시작하는 짧은 이름의 옵션을 검색합니다.
- getopt_long() : 짧은 이름의 옵션과 '--'로 시작하는 긴 이름의 옵션을 검색합니다.
- getopt_long_only() : '-', '--' 모두 긴 이름 옵션으로 검색합니다.
getopt()와 다른 점, struct option
getopt()를 사용하는 옵션은 - 문자 하나만 사용합니다. 그러나 getopt_long()를 사용하는 긴 옵션은 -- 처럼 문자 두개로 입력해야 합니다. getopt_long() 함수를 사용하기 위해서는 getopt() 함수와 달리 긴 이름의 옵션 정보를 미디 준비해야 합니다. 예를 들어,
- 옵션에 --opt55를 입력했다면 var55 변수에 55라는 값을 구하고, 옵션에 없다면 0의 값을 가지게 하겠습니다.
- 옵션에 --opt99를 입력했다면 var99 변수에 99라는 값을 구하고, 옵션에 없다면 0의 값을 가지게 하겠습니다.
- --repeat 옵션이 있는지 여부를 확인 하겠습니다.
- --name= 옵션을 사용했다면 옵션에 지정한 문자열을 구하겠습니다.
이와 같이 처리해야할 옵션이 결정되었다면 아래와 같이 struct option을 작성합니다.
struct option options[] = {
{"opt55" , 0, &var55, 55},
{"opt99" , 0, &var99, 99},
{"repeat", 0, 0, 0},
{"name" , 1, 0, 0},
{0, 0, 0, 0}
};
struct option은 아래와 같이 구성되어 있습니다.
struct option
{
const char *name; // 옵션의 긴 이름입니다.
int has_arg; // 옵션에 해당하는 자료, 즉 --name=test.c 처럼 인수가 필요한지
// 여부를 지정합니다.
// 0 : 필요 없음
// 1 : 필요 함
int *flag; // 옵션이 입력되었다면 지정한 값을 받을 수 있는 변수 주소입니다.
int val; // 옵션이 입력되었다면 여기에 지정한 값을 flag 변수에 대입합니다.
};
struct opton 구조에 따라 각 행의 의미를 보겠습니다.
- {"opt55" , 0, &var55, 55}
옵션의 긴 이름은 opt55 이며, 옵션에 필요한 인자는 없습니다. 즉, --opt55=어쩌구저쩌구 라고 "=어쩌구저쩌구"를 넣을 수 없습니다. 옵션이 지정되었다면 var55 변수에 55값을 넣어라가 되겠습니다. - {"opt99" , 0, &var9955, 995}
옵션의 긴 이름은 opt99 이며, 옵션에 필요한 인자는 없습니다. 옵션이 지정되었다면 var99 변수에 99값을 대입하게 됩니다. - {"repeat", 0, 0, 0}
옵션의 긴 이름은 repeat 이며, 필요한 추가 자료는 없습니다. 옵션이 있는지의 여부를 받는 포인터 변수도 없습니다. - {"name" , 1, 0, 0}
옵션의 긴 이름은 name이며, =로 지정하는 자료가 필요합니다. 없으면 에러 메시지가 출력됩니다. 옵션이 있는지의 여부를 받는 포인터 변수가 없습니다.
실행 여부에 따라 아래와 같은 결과를 얻을 수 있습니다.
]$ ./sample --opt55 --repeat -name=test.txt
- var99 변수 값에는 변동 없음
- var55 변수에 55를 대입
- repeat 옵션이 지정되었음을 알게됨
- name의 문자열 데이터는 "test.txt"
C언어 getopt_long() 함수 예제
#include <stdio.h>
#include <getopt.h>
static int var55;
static int var99;
int main( int argc, char **argv)
{
struct option options[] = {
{"opt55" , 0, &var55, 55},
{"opt99" , 0, &var99, 99},
{"repeat", 0, 0, 0},
{"name" , 1, 0, 0},
{0, 0, 0, 0}
};
char *name;
int opt;
int index = 0;
while( 1){
opt = getopt_long( argc, argv, "", options, &index);
if ( -1 == opt) break; // 모든 옵션을 확인했으면 루프 종료
switch( opt){
case 0:
if ( options[index].flag != 0) break; // 변수 주소 지정이 없다면
// 다음 옵션을 확인합니다.
// 즉, --repeat와 --name이 아니면
// 스킵합니다.
printf("옵션 %s", options[index].name);
if ( NULL != optarg) printf("=%s", optarg);
printf("\n");
break;
} /* switch 의 끝*/
} /* while 의 끝 */
printf( "var55= %d\n", var55);
printf( "var99= %d\n", var99);
/* 남아있는 코맨드 라인 인수들을( 옵션이 없는) 출력하라. */
if (optind < argc){
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
}
C언어 getopt_long() 예제 실행 결과
]$ ./a.out ./a.out --opt55 --name=test.c --repeat
옵션 name=test.c
옵션 repeat
var55= 55
var99= 0
]$
getopt()처럼 짧은 이름의 옵션 사용 예제
또한 getopt() 와 같이 문자 하나 옵션도 사용할 수 있습니다. 이 옵션 사용은 getopt()와 같습니다. 즉, 아래와 같이 getopt_long() 함수를 호출하면 -r, -f 옵션을 사용할 수 있습니다.
opt = getopt_long( argc, argv, "rf:", options, &index);
아래는 getopt()처럼 문자 하나 옵션까지 처리하는 예입니다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#define TRUE 1
#define FALSE 0
static int var55;
static int var99;
int main( int argc, char **argv)
{
struct option options[] = {
{"opt55" , 0, &var55, 55},
{"opt99" , 0, &var99, 99},
{"repeat", 0, 0, 0},
{"name" , 1, 0, 0},
{0, 0, 0, 0}
};
char *name = NULL;
int is_repeat = FALSE;
int index = 0;
int opt;
while( 1){
opt = getopt_long( argc, argv, "rf:", options, &index);
if ( -1 == opt) break; // 모든 옵션을 확인했으면 루프 종료
switch( opt){
case 0:
switch( index){
case 2 : // options[2]에 해당하는 repeat 라면
is_repeat = TRUE;
break;
case 3 : // options[3]에 해당하는 name 이라면
if ( NULL != optarg){ // 인수가 있다면
name = malloc( strlen( optarg)+1);
memcpy( name, optarg, strlen(optarg)+1);
}
break;
} // switch index
break;
case 'r':
printf("-r 옵션을 사용\n", optarg);
break;
case 'f':
printf("-f 옵션에 대한 값 지정은 %s 입니다.\n", optarg);
break;
case '?':
// 이 처리는 하지 않아도 getopt_long()에서 처리합니다.
// 즉, 생략해도 됩니다.
break;
} // switch opt
} // while
printf( "var55= %d\n", var55);
printf( "var99= %d\n", var99);
if ( is_repeat) printf( "repeat 옵션이 있습니다.\n");
else printf( "repeat 옵션이 없습니다.\n");
if ( NULL != name) printf( "name은 %s 입니다.\n", name);
}
실행 결과입니다.
]$ ./a.out --opt99 --repeat --name=test.c -f test3.c -x --xxx
옵션 repeat
옵션 name=test.c
./a.out: invalid option -- 'f'
./a.out: invalid option -- 'x'
./a.out: unrecognized option '--xxx'
var55= 0
var99= 99
non-option ARGV-elements: test3.c
]$
'컴퓨터 > 프로그래밍' 카테고리의 다른 글
C언어 영문자 인지 숫자 문자인지 판별 함수 isalnum() (0) | 2020.03.16 |
---|---|
C언어 파일의 임의의 위치로 읽기·쓰기 포인터 이동 함수 lseek() (0) | 2020.03.16 |
C언어 도메인 이름으로 hostent 정보 구하기 함수 gethostbyname() (0) | 2020.03.16 |