Linux 에서 명령 인수를 처리하기위한 함수 getopt 를 아주 많이 사용합니다. Windows에서는 그런 함수가 없어서 만들어서 사용해 보도록 하겠습니다.
이글에서는 Windows 에서 getopt 구현 하여 그 코드와 예제를 보여드리도록 하겠습니다.
Linux 에서 getopt 함수란
Linux 에서 getopt 함수는 명령행 인수를 처리하는 데 유용한 함수입니다. 이 함수는 주로 프로그램이 실행될 때 전달된 명령행 인수(argument)를 파싱하고 처리하는 데 사용됩니다. getopt 함수를 사용하면 효율적으로 명령행 옵션을 처리하고 관련된 작업을 수행할 수 있습니다.
getopt 함수는 <unistd.h>
헤더 파일에 선언되어 있습니다. getopt 함수의 프로토타입은 다음과 같습니다:
int getopt(int argc, char * const argv[], const char *optstring);
이 함수는 세 개의 인수를 받습니다:
argc
: 명령행에 전달된 인수의 수를 나타내는 정수입니다.argv
: 명령행에 전달된 실제 인수들을 포함하는 문자열 배열입니다.optstring
: 인수로 받을 옵션 문자열을 지정하는데 사용됩니다.
getopt 함수는 getopt_long 함수와 함께 사용될 수 있으며, getopt_long 함수는 더 유연한 옵션 처리를 제공합니다. 그러나 기본적인 옵션 처리에 대해 설명하기 위해서는 getopt 함수에 초점을 맞추도록 하겠습니다.
일반적으로 C 프로그램에서 getopt 함수를 사용하는 방법은 다음과 같습니다:
- getopt 함수를 사용하기 전에
extern char *optarg;
와extern int optind, opterr, optopt;
선언을 추가합니다. - getopt 함수를 반복문 안에서 호출하여 명령행 인수를 처리합니다.
- 각 옵션에 대한 처리를 switch 문이나 if 문을 사용하여 수행합니다.
- 명령행에 지정된 옵션이 없을 때까지 getopt 함수를 호출합니다.
간단한 예제를 통해 이해를 돕겠습니다. 다음은 프로그램 이름을 포함한 간단한 명령행 인수를 처리하는 C 프로그램의 예제입니다:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int opt;
while ((opt = getopt(argc, argv, "abc:")) != -1) {
switch (opt) {
case 'a':
printf("Option 'a' was specified\n");
break;
case 'b':
printf("Option 'b' was specified\n");
break;
case 'c':
printf("Option 'c' was specified with value '%s'\n", optarg);
break;
case '?':
fprintf(stderr, "Unknown option: '%c'\n", optopt);
break;
}
}
return 0;
}
위 프로그램은 ‘a’, ‘b’, ‘c’ 세 가지 옵션을 인식합니다. ‘c’ 옵션은 추가적인 인수를 가질 수 있으며, optarg 변수를 통해 해당 값을 받아옵니다. 이 프로그램은 다음과 같은 명령행을 처리할 수 있습니다:
./program -a -b -c value
이렇게 하면 각 옵션에 대한 메시지가 출력되고, ‘c’ 옵션의 값은 ‘value’가 됩니다.
이러한 방식으로 getopt 함수를 사용하여 명령행 인수를 처리할 수 있습니다.
Windows 에서 getopt 함수 구현하기
Linux 에서 getopt 를 사용해서 명령인자를 처리를 하던 개발자라면 윈도우즈에서 명령 처리가 리눅스의 그것보다 쉽지 않다는것을 알 수 있습니다.
자체적으로 windows 에는 getopt 함수가 없기 대문입니다.
자 그러면 만들어야지요.
아래 코드는 C 언어로 작성된 getopt 함수의 구현입니다. 이 함수는 명령행 인수(argument)를 파싱하고 처리하는 데 사용됩니다.
int opterr = 1; // 오류 메시지 출력 여부
int optind = 1; // 부모 argv 벡터의 인덱스
int optopt; // 유효성을 확인하는 문자
int optreset; // getopt 재설정
char *optarg; // 옵션과 관련된 인수
char EMSG[] = "";
#define BADCH (int)'?'
#define BADARG (int)':'
/*
* getopt -- argc/argv 인수 벡터를 구문 분석합니다.
*/
int getopt(int nargc, char *const *nargv, const char *ostr) {
static char *place = EMSG; // 옵션 문자 처리
char *oli; // 옵션 문자 리스트 인덱스
// 옵션 처리 재설정 또는 스캔 포인터 업데이트
if (optreset || !*place) {
optreset = 0;
// optind가 nargc를 넘거나 현재 위치의 문자가 '-'가 아닌 경우
if (optind >= nargc || *(place = nargv[optind]) != '-') {
place = EMSG;
return (-1);
}
// "--"를 찾은 경우
if (place[1] && *++place == '-') {
++optind;
place = EMSG;
return (-1);
}
}
// 옵션 문자 확인
if ((optopt = (int)*place++) == (int)':' || !(oli = (char *)strchr(ostr, optopt))) {
// 사용자가 '-'를 옵션으로 지정하지 않은 경우, -1로 가정
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
// 옵션에 대한 오류 메시지 출력
if (opterr && *ostr != ':')
fprintf(stderr, "getopt: illegal option -- %c\n", optopt);
return (BADCH);
}
// 인수가 필요하지 않은 경우
if (*++oli != ':') {
optarg = NULL;
if (!*place)
++optind;
} else {
// 인수가 필요한 경우
if (*place)
optarg = place;
else if (nargc <= ++optind) {
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
fprintf(stderr, "getopt: option requires an argument -- %c\n", optopt);
return (BADCH);
} else
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt);
}
전체 예제
#include <stdio.h>
#include <string.h>
int opterr = 1; // 오류 메시지 출력 여부
int optind = 1; // 부모 argv 벡터의 인덱스
int optopt; // 유효성을 확인하는 문자
int optreset; // getopt 재설정
char *optarg; // 옵션과 관련된 인수
char EMSG[] = "";
#define BADCH (int)'?'
#define BADARG (int)':'
/*
* getopt --
* argc/argv 인수 벡터를 구문 분석합니다.
*/
int getopt(int nargc, char *const *nargv, const char *ostr)
{
static char *place = EMSG; // 옵션 문자 처리
char *oli; // 옵션 문자 리스트 인덱스
// 옵션 처리 재설정 또는 스캔 포인터 업데이트
if (optreset || !*place)
{
optreset = 0;
// optind가 nargc를 넘거나 현재 위치의 문자가 '-'가 아닌 경우
if (optind >= nargc || *(place = nargv[optind]) != '-')
{
place = EMSG;
return (-1);
}
// "--"를 찾은 경우
if (place[1] && *++place == '-')
{
++optind;
place = EMSG;
return (-1);
}
}
// 옵션 문자 확인
if ((optopt = (int)*place++) == (int)':' || !(oli = (char *)strchr(ostr, optopt)))
{
// 사용자가 '-'를 옵션으로 지정하지 않은 경우, -1로 가정
if (optopt == (int)'-')
return (-1);
if (!*place)
++optind;
// 옵션에 대한 오류 메시지 출력
if (opterr && *ostr != ':')
fprintf(stderr, "getopt: illegal option -- %c\n", optopt);
return (BADCH);
}
// 인수가 필요하지 않은 경우
if (*++oli != ':')
{
optarg = NULL;
if (!*place)
++optind;
}
else
{
// 인수가 필요한 경우
if (*place)
optarg = place;
else if (nargc <= ++optind)
{
place = EMSG;
if (*ostr == ':')
return (BADARG);
if (opterr)
fprintf(stderr, "getopt: option requires an argument -- %c\n", optopt);
return (BADCH);
}
else
optarg = nargv[optind];
place = EMSG;
++optind;
}
return (optopt);
}
int main(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "abc:")) != -1)
{
switch (opt)
{
case 'a':
printf("Option 'a' was specified\n");
break;
case 'b':
printf("Option 'b' was specified\n");
break;
case 'c':
printf("Option 'c' was specified with value '%s'\n", optarg);
break;
case '?':
fprintf(stderr, "Unknown option: '%c'\n", optopt);
break;
}
}
return 0;
}
빌드된 위 프로그램을 cmd 로 실행 시켜보도록 하겠습니다. 출력은 다음과 같습니다.
D:\>program -a -b -c value
Option 'a' was specified
Option 'b' was specified
Option 'c' was specified with value 'value'
결론
Windows 에서 getopt 함수를 만들어 그 코드와 에제를 보여드렸습니다.
위 코드로 windows 에서도 getopt를 쉽게 사용해 보시기 바랍니다.