【问题标题】:C Getopt : Wrong argument corresponding to its optionC Getopt:与其选项对应的参数错误
【发布时间】:2012-08-05 17:55:51
【问题描述】:

我想获得这个命令的选项:

my_cmd show --value true -D

要做到这一点,我需要检查两次选项(由于架构)。在第二遍期间,不可能正确检索与其选项对应的参数。 在此示例中,在第二次传递期间,检索到的参数(对于选项 --value)是 -D 而不是 true

第一关:

void getoptions (int argc, char **argv, globalargs_t* globalargs) {

    static const char *optstring = "vDqnd:c:f:o:h?:";

    static const struct option longopts[] = {
        { "help",         no_argument,        NULL,    'h' },
        { "Debug",        no_argument,        NULL,    'D'},
        { "verbose",    no_argument,        NULL,    'v'},
        { "quiet",        no_argument,        NULL,    'q'},
        { "noheader",    no_argument,        NULL,    0},
        { "delimiter",    required_argument,     NULL,    0},
        { "columns",    required_argument,    NULL,    0},
        { "filter",        required_argument,    NULL,    0},
        { "order",        required_argument,    NULL,    0},
        { "getid",        no_argument,        NULL,    'i'},
        { NULL,            no_argument,        NULL,    0 }
    };

    int opt = 0;
    int longindex = 0;
    //opterr = 0;

    /* Process the arguments with getopt_long(), then populate globalargs-> */
    opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    while( opt != -1 ) {
        switch( opt ) {
            case '?':
                break;
            case 'D':
                globalargs->debug = 1;    /* true */
                break;
            case 'v':
                globalargs->verbose++;
                break;
            case 'q':
                globalargs->quiet = 1;
                break;
            case 'i':
                globalargs->id = 1;
                break;
            case 'h':
                globalargs->help = 1;
                break;
            case 0:        /* long option without a short arg */
                if( strcmp( "Debug", longopts[longindex].name ) == 0 ) {
                    globalargs->debug = 1;
                }
                if( strcmp( "verbose", longopts[longindex].name ) == 0 ) {
                    globalargs->verbose = 1;
                }
                if( strcmp( "quiet", longopts[longindex].name ) == 0 ) {
                    globalargs->quiet = 1;
                }
                if( strcmp( "noheader", longopts[longindex].name ) == 0 ) {
                    globalargs->noheader = 1;
                }
                if( strcmp( "delimiter", longopts[longindex].name ) == 0 ) {
                    globalargs->delimiter = *optarg;
                }
                if( strcmp( "filter", longopts[longindex].name ) == 0 ) {
                    globalargs->filter = optarg;
                }
                if( strcmp( "order", longopts[longindex].name ) == 0 ) {
                    globalargs->order = optarg;
                }
                if( strcmp( "columns", longopts[longindex].name ) == 0 ) {
                    globalargs->columns = optarg;
                }
                break;
            default:
                /* You won't actually get here. */
                break;
        }
        opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    }
    if (optind < argc) {
        while (optind < argc) {
            globalargs->actions[globalargs->actionsindex] = argv[optind++];
            globalargs->actionsindex++;
        }
    }
}

第二遍:

void getspecificoptions(int argc, char **argv, globalargs_t* globalargs) {
    static const char *optstring = ":n:d:v:d";

    static const struct option longopts[] = {
        { "name",                required_argument,     NULL,    'n'},
        { "domain",                required_argument,    NULL,    0},
        { "value",                required_argument,    NULL,    0},
        { "defined_value",        required_argument,    NULL,    0},
        { NULL,                    no_argument,        NULL,    0 }
    };

    optind = 1;
    int opt = 0;
    int longindex = 0;

    /* Process the arguments with getopt_long(), then populate globalargs-> */
    opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    while( opt != -1 ) {
        switch( opt ) {
            case 'n':
                /* If used in update/add => must be still a filter */
                globalargs->filter = strcat(globalargs->filter,"cluster.name=");
                globalargs->filter = strcat(globalargs->filter, optarg);
                if(!globalargs->table || strcmp(globalargs->table, "cluster") == 0 ) {
                    globalargs->table = "cluster";
                }
                else {
                    clmError(&t, "dbm-command", -1, "Incompatible options.");
                    exit(EXIT_FAILURE_OPTIONS);
                }
                break;
            case 0:        /* long option without a short arg */
                if( strcmp( "domain", longopts[longindex].name ) == 0 ) {

                    }
                    else {
                        char* f = my_new(500*sizeof(char));
                        f = strcat(f, "cluster.dns_domain=");
                        f = strcat(f, optarg);
                        globalargs->actions[globalargs->actionsindex] = f;
                        globalargs->actionsindex++;
                    }
                    if(strcmp(globalargs->table,"") == 0 || strcmp(globalargs->table, "cluster") == 0 ) {
                        globalargs->table = "cluster";
                    }
                    else {
                        clmError(&t, "dbm-command", -1, "Incompatible options.");
                        exit(EXIT_FAILURE_OPTIONS);
                    }
                }
                if( strcmp( "value", longopts[longindex].name ) == 0 ) {
                    if(strcmp(globalargs->actions[0], "show") == 0 || strcmp(globalargs->actions[0], "delete") == 0 ) {
                        globalargs->filter = realloc(globalargs->filter, strlen(globalargs->filter) + strlen(optarg) + strlen("cluster_profile.value=") + 1);
                        globalargs->filter = strcat(globalargs->filter,"cluster_profile.value=");
                        globalargs->filter = strcat(globalargs->filter, optarg);
                    }
                    else {
                        char* act = my_new(strlen(optarg) + strlen("cluster_profile.value=") + 1U);
                        act = strcat(act, "cluster_profile.value=");
                        act = strcat(act, optarg);
                        globalargs->actions[globalargs->actionsindex] = act;
                        globalargs->actionsindex++;
                    }
                    if(strcmp(globalargs->table,"") == 0 || strcmp(globalargs->table, "profile") == 0 ) {
                        globalargs->table = "profile";
                    }
                    else {
                        clmError(&t, "dbm-command", -1, "Incompatible options.");
                        exit(EXIT_FAILURE_OPTIONS);
                    }
                }
                if( strcmp( "defined_value", longopts[longindex].name ) == 0 ) {
                    /* If used in update/add => must be still a filter */
                    globalargs->filter = strcat(globalargs->filter,"cluster_profile.defined_value=");
                    globalargs->filter = strcat(globalargs->filter, optarg);

                    if(!globalargs->table || strcmp(globalargs->table, "profile") == 0 ) {
                        globalargs->table = "profile";
                    }
                    else {
                        clmError(&t, "dbm-command", -1, "Incompatible options.");
                        exit(EXIT_FAILURE_OPTIONS);
                    }
                }
                break;
        }
        opt = getopt_long( argc, argv, optstring, longopts, &longindex );
    }
}

在这些通过之后,我有globalargs-&gt;filter="-D"

任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • 能不能把使用函数放上来,让我们看看你想要什么?

标签: c linux command-line-arguments getopt


【解决方案1】:

getopt 重新排序参数并将在所有非选项参数之前返回所有选项参数,如manual 中所述:

默认情况下,getopt() 在扫描时会置换 argv 的内容,所以 最终所有的非选项都结束了。另外两种模式是 也实施了。如果 optstring 的第一个字符是 '+' 或 设置环境变量POSIXLY_CORRECT,然后选项处理 一旦遇到非选项参数就停止。如果第一个 optstring 的字符是 '-',那么每个非选项 argv 元素是 就像它是具有字符代码 1 的选项的参数一样处理。 (这被编写为期望选项和 其他任何顺序的 argv 元素,并且关心 两者。)特殊参数“--”强制结束选项扫描 与扫描模式无关。

由于--value true 的正确长语法是--value=truetrue 被视为非选项参数并移到选项参数后面。

【讨论】:

  • 在 Posix 中,如果需要参数,那么 --value true 也是可以接受的。
【解决方案2】:

optind 必须重置为 0 而不是 1。第一次通过时,限定标志被解析,但第二次不是,因为 optind 是 1 而不是 0。将其设置为 0 会重新解析字符串。

optstring 的第一个字符也必须是 + 或 -(在前导冒号之前),以防止参数被重新排序。

这一切都假设您使用的是 GNU 的 getopt_long。

【讨论】:

  • 它与我的第一个 optstring 中的 '-' 和一个用 0 重置的 optind 一起工作。谢谢!
猜你喜欢
  • 2014-12-19
  • 2021-08-03
  • 2013-12-22
  • 2021-06-24
  • 2021-12-27
  • 1970-01-01
  • 1970-01-01
  • 2013-11-05
相关资源
最近更新 更多