getopt_long很奇怪

时间:2012-11-26 05:09:23

标签: c++ c getopt getopt-long

我正在编写一些用于解析命令行输入的代码。我使用getopt_long的方式如下:

int c = 0; 
static struct option long_options[] =  
{ 
    {"mode",        1,  NULL,   'm'}, 
    {"help",        0,  NULL,   'h'}, 
    {0,             0,  0,      0} 
}; 
while ((c = getopt_long(argc, argv, "mh", long_options, NULL))!=-1) 
{ 
    switch(c) 
    { 
        case 0: 
        { 
            cerr<<"Usage: ./program <-m> <-h>"<<endl; 
            exit(1); 
            break; 
        } 
        case 'm': 
        { 
            if (!strcmp(optarg, "small"))
                mode = 0;
            else if (!strcmp(optarg, "medium"))
                mode = 1;
            else if (!strcmp(optarg, "large"))
                mode = 2;
            else{
                cerr<<"Invalid mode "<<optarg<<endl;
                exit(1);
            }
            break; 
        } 
        case 'h': 
        { 
            cerr<<"See man page for help."<<endl;
            exit(0); 
        } 
        default: 
        { 
            cerr<<"Unrecognized argument!"<<endl; 
            exit(1); 
        } 
    } 
}

我测试了以下内容:

1)

./program

程序不进入while循环。变量c被检查为-1。

2)

./program -h

运作良好。

3)

./program -m small

程序从strcmp()抛出Segmentation Fault抛出。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

以下是如何使用getopt_long()解析选项并正确处理其返回值的示例,例如选项结束,缺少参数和未知选项:

struct Options
{
    std::string username = "guest";

    void parse_command_line(int ac, char** av) try {
        enum {
              HELP
            , USER
        };

        // This array must be in the same order as the enum.
        option const options[] = {
              {"help",            no_argument, nullptr, HELP}
            , {"username",  required_argument, nullptr, USER}
            , {}
        };

        ::opterr = 0;
        for(int c; -1 != (c = getopt_long(ac, av, ":h", options, nullptr));) {
            switch(c) {
            // both short and long option
            case 'h':
            case HELP:
                usage(av, EXIT_SUCCESS);
                break;

            // only long option
            case USER:
                username = ::optarg; // 
                break;

            case ':': // missing argument
                throw Exception("--%s: an argument required", options[::optopt].name);

            case '?': // unknown option
                throw Exception("%s: unknown option", av[optind - 1]);
            }
        }

    }
    catch(std::exception& e) {
        fprintf(stderr, "error: %s\n", e.what());
        usage(av, EXIT_FAILURE);
    }
};

注意,没有必要为每个长选项提供相应的短选项。