[C] 프로그램 파라미터를 처리하는 getopt() 사용법

C프로그램의 파라미터 파싱 및 처리

문자열 파싱은 스크래치 상태(아무것도 없는 빈 상태)로부터 구현하기가 만만치 않은데, 이를 도와주는 라이브러리 함수가 있으니 바로 unistd.h에 정의된 getopt() 함수이다.

getopt()

이 함수의 원형은 다음과 같다.

int getopt(int argc, char * const argv[], const char *optstring);

이 함수의 파라미터는 간단한다.

  1. argc, argv : main() 함수가 받은 파라미터를 그대로 전달한다.
  2. optstring : 파싱해야 할 파라미터를 쓴다. 옵션이 별도의 파라미터를 받는 경우 콜론을 함께 쓴다.

예를 들어 -h, -v, -f filename을 받는 세 가지 옵션이 있다고 하면 옵션스트링은 "hvf:"가 된다. 각각의 옵션을 파싱해내기 위해서는 getopt()함수가 0을 리턴할 때까지 계속해서 반복하면 된다.

그외 전역변수

이 함수와 관련된 전역 변수에는 다음과 같은 것들이 있다.

  • optarg : 옵션 뒤에 별도의 파라미터 값이 오는 경우, 이를 파싱한 결과 파라미터 값은 optarg에 문자열로 저장된다.
  • optind : 다음번 처리될 옵션의 인덱스이다. 만약 파싱한 옵션이후에 추가적인 파라미터를 받는다면 (예를 들어 입력 파일 이름 같이) 이 값을 활용할 수 있다. getopt()함수는 한 번 호출될 때마다 이 값을 업데이트한다.
  • opterr : 옵션에 문제가 있을 때, 이 값은 0이 아닌 값이되며, getopt()함수가 메시지를 표시하게 된다.
  • optopt : 알 수 없는 옵션을 만났을 때 해당 옵션이 여기에 들어간다. (이 때 getopt의 리턴값은 ‘?’가 된다.)

샘플 코드

아래 샘플 코드는 간략한 예를 보여준다. 이 코드에서는 a, b, c의 세 옵션을 인식하며 각각의 옵션이 주어지는 경우 해당 플래그 변수를 1로 정의하고 그 결과를 출력한다.

1:  #include <stdio.h>
2:  #include <unistd.h> // for getopt()
3:  
4:  int main(int argc, char * const * argv){
5:      int flag_a = 0, flag_b = 0, flag_c = 0;
6:      int c; // option
7:      while( (c = getopt(argc, argv, "abc")) != -1) {
8:          // -1 means getopt() parse all options
9:          switch(c) {
10:             case 'a':
11:                 flag_a=1;
12:                 break;
13:             case 'b':
14:                 flag_b=1;
15:                 break;
16:             case 'c':
17:                 flag_c=1;
18:                 break;
19:             case '?':
20:                 printf("Unknown flag : %c", optopt);
21:                 break;
22:         }
23:     }
24:     if(flag_a) {printf("flag a is ON \n");}
25:     if(flag_b) {printf("flag b is ON \n");}
26:     if(flag_c) {printf("flag c is ON \n");}
27:     return 0;
28: }

보통 while문으로 루프를 돌면서 옵션들을 하나씩 검사한다. getopt가 optstring으로 정의되지 않은 옵션문자를 만나면 opterr 값이 세팅되고, 동시에 getopt()함수가 해당 문자에 대해 메시지를 출력한다. 이 때 반환값은 '?'가 되고 이때 알 수 없는 옵션 문자는 optopt에 저장된다.

추가 파라미터를 필요로하는 옵션

gcc의 -o와 같이 파일 이름등의 추가 파라미터를 필요로하는 옵션은 다음과 같이 처리한다.

  1. optsting에서 옵션 문자 뒤에 콜론을 붙인다. "abcf:"와 같은 식으로 쓴다.
  2. getopt()함수는 -f를 만나면 자동으로 그 뒤에 붙은 문자열을 공백까지 탐색하여 이를 optarg에 복사한다.
  3. 처리시에는 리턴값이 ‘f’인 경우 optarg의 값을 그대로 액세스하면 된다.

이러한 처리 코드는 아래와 같다.

case 'f':
    memcpy(file_name, optarg, strlen(optarg));
    break;

또한 파라미터가 있다고 정의한 경우, 파라미터 값이 빠진채로 실행되었다면 이 때는 옵션이 인식할 수 없는 옵션으로 처리된다.

case '?':
    if(optopt == 'f') {
        printf("option -f requires FILENAME\n");
    }
    break;

optind

옵션문자들을 모두 처리한 이후에 프로그램 자체의 파라미터를 처리하기 위해서는 optindargv의 인덱스로 사용하여 파라미터를 전달 받을 수 있다.

그외 긴 이름

--output등의 긴 이름 옵션을 사용하기 위해서는 getoptlong함수를 사용한다.