티스토리 뷰

728x90

☞ getopt

<unistd.h>

int getopt(int argc, char *const *argv, const char *options);

C 언어로 작성하는 프로그램의 시작점인 main() 함수는 파라미터로 아규먼트의 개수(int argc)와 공백으로 구분되는 아규먼트의 내용을 문자열 배열(char *argv[])을 전달 받습니다. 사용자가 프로그램을 실행시키면서 전달한 아규먼트들을 개수와 배열 형태로 넘겨 주는 것입니다. 통상 하이픈(-)과 함께 다양한 옵션을 지정하게 되는데 이 옵션들의 분석을 간편하게 해주는 것이 getopt()입니다. 일반적인 옵션 지정 방식은 다음과 같습니다.

  • 하이픈(-)에 영문자 및 숫자로 옵션을 지정합니다.
  • -o outfile_name 또는 -ooutfile_name 처럼 추가 아규먼트를 지정하는 옵션도 있는데 공백이 없어도 되고 공백을 기술해도 됩니다.
  • 추가 아규먼트 받지 않는 옵션들은 -abc 또는 -a -b -c 처럼 한번에 기술할 수도 개별로 지정할 수도 있습니다.
  • --는 옵션의 끝을 의미해서 이 이후로는 하이픈이 있어도 옵션으로 취급하지 않습니다.



☞ 예제1

static int get_args (int argc, char *argv[])
{
    int c;

    while ((c = getopt (argc, argv, "saQbqI:P:d:u:p:t:r:o:e:f:n:h:R:")) != EOF)
    {
        switch (c)
        {
        case 's':
            statdump_mode = 1;
            break;
        case 'a':
            autocommit_mode = 1;
            break;
        case 'b':
            batch_mode = 1;
            break;
        case 'q':
            qa_test_flag = 1;
            break;
        case 'I':
            broker_host = optarg;
            break;
        case 'P':
            broker_port = atoi (optarg);
            break;
        case 'd':
            dbname = optarg;
            break;
        case 'u':
            dbuser = optarg;
            break;
        case 'p':
            STRDUP (dbpasswd, optarg);
            break;
        case 't':
            num_thread = atoi (optarg);
            if (num_thread < 1)
                num_thread = 1;
            break;
        case 'r':
            repeat_count = atoi (optarg);
            if (repeat_count < 1)
                repeat_count = 1;
            break;
        case 'o':
            result_file = optarg;
            break;
        case 'e':
            cas_err_file = optarg;
            break;
        case 'f':
            fork_delay = atoi (optarg);
            break;
        case 'n':
            node_name = optarg;
            break;
        case 'h':
            think_time = atoi (optarg);
            break;
        case 'R':
            num_replica = atoi (optarg);
            break;
        case 'Q':
            dump_query_plan = 1;
            break;
        case '?':
            goto getargs_err;
        }
    }

    if (optind >= argc)
    {
        goto getargs_err;
    }

    exec_script_file = argv[optind];

    if (batch_mode)
    {
        if (result_file != NULL && strcmp (result_file, "stdout") == 0)
            result_file = NULL;
    }

    return 0;

getargs_err:
    fprintf (stderr,
        "usage : %s [OPTION] exec_script_file\n" "\n" "valid options:\n" "  -I   broker host\n"
        "  -P   broker port\n" "  -d   database name\n" "  -u   user name\n" "  -p   user password\n"
        "  -t   the number of thread\n" "  -r   the number of times to execute entire query by each thread\n"
        "  -Q   enable to print a plan per query\n" "  -o   result file\n"
        "  -s   enable to print a statdump per query\n" "  -a   enable auto commit mode\n", argv[0]);
    return -1;
}

위의 예제 프로그램은 큐브리드 DBMS의 코드 일부로 옵션 분석 과정에서 오류가 생기면 getargs_err 부분에서 사용법을 출력하는데 이 부분을 참조하면 어떤 옵션이 아규먼트를 요구하는지 등을 확인할 수 있습니다.

getopt()는 통상 main() 함수가 받은 아규먼트 개수(argc), 아규먼트 배열(argv), 옵션 스트링(options)을 인수로 받아서 옵션 문자를 차례대로 리턴합니다. 더이상 옵션이 없으면 -1을 리턴합니다. 함수의 성격상 프로그램 단위의 시스템 영역을 사용하기 때문에 멀티 쓰레드 환경에서 getopt()를 동시에 사용하면 안전하지 않을 수 있습니다.

getopt() 함께 사용하는 시스템 영역에 존재하는 글로벌 변수로 다음과 같은 것들이 있습니다.

  • int opterr : 0이 아닌값이면 분석 과정의 오류 메시지를 stderr로 출력합니다. 0이면 출력하지 않음. 기본값은 출력
  • int optopt : 잘못된 옵션 문자나 추가 아규먼트를 누락한 옵션 문자가 저장되는 곳입니다
  • int optind : 다음 옵션이 있는 argv 배열의 인덱스를 가리킵니다. 모든 옵션이 추출된 다음에 옵션이 아닌 아규먼트를 가리키게 됩니다. 예제에서도 exec_script_file 추출에 이 변수를 활용합니다.
  • char *optarg : 현재 옵션에 해당하는 아규먼트 스트링을 가리킵니다.


옵션 스트링(options)은 프로그램에서 지원하는 옵션 목록으로 추가 아규먼트를 받는 옵션은 뒤에 콜론(:)을 붙입니다. 예제에서 사용한 "saQbqI:P:d:u:p:t:r:o:e:f:n:h:R:"에서도 "I:P:d:u:p:t:r:o:e:f:n:h:R:" 옵션은 추가 아규먼트를 기술해야하는 옵션들입니다.




728x90

'C | C++' 카테고리의 다른 글

프로그램 종료  (0) 2018.08.04
환경 변수 다루기  (0) 2018.08.04
시그널 다루기  (0) 2018.08.04
시그널의 종류와 핸들러  (0) 2018.08.04
비지역적 점프  (0) 2018.08.04