getopt_long使用详解及实例

getopt_long用法详解

getopt_long介绍

getopt_long 是一个在 Linux 和类 Unix 系统中常用的函数,用于解析命令行参数。它支持短选项(如 -a)和长选项(如 --long-option),并且能够处理带有参数的选项。以下是 getopt_long 的详细使用方法

  1. 函数原型
    getopt_long 的函数原型如下:
int getopt_long(int argc, char *const argv[], const char *shortopts,
                const struct option *longopts, int *longindex);

  1. 参数说明
  • argc 和 argv:这两个参数与 main 函数中的参数一致,分别表示命令行参数的数量和参数数组。
  • shortopts:这是一个字符串,表示短选项的格式。例如,“ab:c::” 表示 a 是无参数选项,b 是带必需参数的选项,c 是带可选参数的选项。
  • longopts:这是一个指向 struct option 数组的指针,用于定义长选项的格式。每个 struct option 结构体包含以下字段:
    name:长选项的名称。
  • has_arg:指示选项是否带参数,0 表示无参数,1 表示必需参数,2 表示可选参数。
  • flag:如果为 NULL,则 getopt_long 返回 val;否则,返回 0,并将 val 存储到 flag 指向的变量中。
  • val:将要返回的值或存储到 flag 指向的变量中的值。
  • longindex:这是一个指向整数的指针,用于返回长选项在 longopts 数组中的索引。通常设置为 NULL。
  1. 返回值
    如果遇到有效的短选项或长选项,getopt_long 返回该选项的字符(对于短选项)或 val(对于长选项)。
    如果所有选项都已处理完毕,返回 -1。

  2. 如何得带参选项的参数值
    char *optarg是在getopt.h头文件中声明的指针变量,用于得到每个参数选型的参数值。

getopt_long使用实例

static void show_usage(const char *cmd)
{
    printf("Usage: %s [options] ... \n", cmd);
    printf("  -h, --help           display this help and exit\n");
    printf("  -v, --version        get and show version\n");
     printf(" -r, --reboot         reboot RSU\n");
    printf("  -l, --rxlevel        setting rx level\n");
    printf("  -p, --tpwer          setting tx power\n");
    printf("  -i, --id             setting id mode\n");
    printf("  -c, --idc            setting id change interval times\n");
    printf("  -m, --setmmi         setting SetMMI\n");

    exit(0);
}

int main(int argc, char **argv)
{   
    uint8_t verbuf[200] = {0};
    uint8_t vst_buf[512] = {0};
    uint32_t verlen;

    cmd_55aa_protocol_init();

    char resp[100] = {0};
    int ret;
    int option;
    char *name = NULL;
    char *content = "Hello, World!";

    const char * const short_options = "hvrl:p:i:c:m:";
    const struct option long_options[] = {
        { "help",    0, NULL, 'h' },
        { "version", 0, NULL, 'v' },
        { "rboot",   0, NULL, 'r' },
        { "tpwer",   1, NULL, 'p' },
        { "rxlevel", 1, NULL, 'l' },
        { "idc",     1, NULL, 'c' },
        { "id",      1, NULL, 'i' },
        { "setmmi",  1, NULL, 'm' },
        { NULL,      0, NULL,  0  }
    };

    if (argc < 2)
    {
        show_usage(argv[0]);
    }

    cmd_55aa_t9_init();

    uint8_t txpower = 24;
    uint8_t rxlevel = 16;
    uint8_t rsuidmode = 1;
    uint8_t idchangeinterval = 2;
    uint8_t setmmi = 1;
    uint8_t gettxpower;

     while ((option = getopt_long(argc, argv, short_options, long_options, NULL)) != -1) 
    {
        switch (option)
        {
        case 'h':
            show_usage(argv[0]);
            break;
        case 'v':
            cmd_55aa_t9_get_ver_test(verbuf, sizeof(verbuf), &verlen);
            printf("\r\nversion: %s\r\n", verbuf);
            break;
        case 'p':
            txpower = atoi(optarg);
            if (0 > txpower || txpower > 31)
            {
                printf("txpower %d is invalid, range: 0-31\n", txpower);
                exit(-1);
            }
            printf("txpower %d\n", txpower);
            break;
        case 'l':
            rxlevel = atoi(optarg);
            if (0 > rxlevel || rxlevel > 31)
            {
                printf("rxlevel %d is invalid, range: 0-31.\n", rxlevel);
                exit(-1);
            }
            printf("rxlevel %d\n", rxlevel);
            break;
        case 'c':
            idchangeinterval = atoi(optarg);
            printf("idchangeinterval %d\n", idchangeinterval);
            break;
        case 'i':
            rsuidmode = atoi(optarg);
            printf("rsuidmode %d\n", rsuidmode);
            if (rsuidmode != 0 && rsuidmode != 1)
            {
                printf("rsuidmode %d is invalid, range: 0-1.\n", rsuidmode);
                exit(-1);
            }
            break;
        case 'm':
            setmmi = atoi(optarg);
            printf("setmmi %d\n", setmmi);
            if (setmmi != 0 && setmmi != 1)
            {
                printf("setmmi %d is invalid, range: 0-1.\n", setmmi);
                exit(-1);
            }
            break;
        case 'r':
            break;
        case '?':
        default :
            printf("Error: option invalid\n");
            exit(-1);
            break;
        }
    }
    
    printf("\r\n");
    sleep(1);
    while (1)
    {
        cmd_55aa_t9_txpower_set(txpower);
        cmd_55aa_t9_txpower_get(&gettxpower);
        cmd_55aa_t9_rxlevel_set(rxlevel);
        cmd_55aa_t9_id_changeinterval_set(idchangeinterval);

        cmd_55aa_t9_rsuid_mode_set(rsuidmode);
        sleep(1);
        cmd_55aa_t9_setmmi(setmmi);
   
        cmd_55aa_antenna_open();

        sleep(5);

        cmd_55aa_antenna_close();
    }

    cmd_55aa_protocol_deinit();
    
    return 0;
}
<think>好的,我现在需要帮助用户了解C语言中的getopt_long函数的使用方法。用户已经提供了三个引用资料,我需要先仔细阅读这些资料,理解其中的关键点,然后组织出一个结构清晰的回答。 首先,根据系统级指令,我需要确保所有行内数学表达式正确使用$...$格式,但这个问题可能不涉及数学表达式。不过,用户的问题是关于C函数的参数解析,所以重点在于代码示例和函数参数的正确格式。 用户提供的引用[1]和[2]提到了getoptgetopt_long的区别,特别是getopt_long多出的两个参数,一个是结构体数组,另一个是长选项索引的指针。引用[3]可能是一个博客链接,提供了更详细的例子。这些信息需要整合到回答中,确保正确引用。 接下来,我需要按照用户的要求,回答结构清晰,分步骤说明。可能需要包括函数原型、参数解释、使用步骤、示例代码以及注意事项。同时,生成相关问题,帮助用户深入理解。 现在,我需要检查每个引用中的关键点。引用[1]指出getopt_long的原型,以及因为选项a默认不带参数导致解析错误的问题。引用[2]详细说明了结构体数组和长选项索引参数的作用,并提到可以设置为NULL。引用[3]可能是一个使用示例,但用户未提供具体内容,可能需依赖前两个引用。 在编写函数原型时,需要正确列出所有参数:argc, argv, optstring, longopts, longindex。每个参数的解释要准确,特别是optstring中的冒号规则和结构体option的成员:name, has_arg, flag, val。 使用步骤部分应分点说明,如定义选项结构体、构造optstring、循环处理参数等。示例代码需要正确展示如何定义长选项和短选项,并处理返回值。同时,需要注意错误处理和optind的使用。 注意事项部分需要提到选项结构体数组以全零元素结尾,optstring中的顺序,错误消息的处理,以及如何重置getopt_long的状态。这些信息可能来自引用中的细节,例如引用[2]提到的结构数组和第二个附加参数为NULL的情况。 在生成相关问题的时候,需要围绕getopt_long的扩展,比如与getopt的区别、处理参数的方法、错误处理、结构体option的细节,以及实际应用场景。这样可以帮助用户进一步探索相关主题。 最后,确保所有引用标识正确添加到对应的位置,例如在函数原型处添加[^1],在结构体参数处添加[^2]等。代码块需要用正确的语法高亮,例如标记为C语言,并正确缩进。 现在需要检查是否有遗漏的信息,比如getopt_long如何处理长选项和短选项,如何区分它们,以及如何处理带参数的选项。同时,在示例代码中,要展示如何同时处理长选项和对应的短选项,比如--help对应-h,并在结构体中设置val为'h',这样在switch中处理。 可能还需要提到返回值,当getopt_long遇到长选项时,如果flag为NULL,则返回val的值;否则,将变量指向val。这部分需要准确描述,以避免误解。 在注意事项中,提到使用opterr=0来抑制错误输出,并自行处理错误消息,这来自引用中的常见做法。 总结,整个回答需要覆盖函数参数、结构体定义、使用步骤、示例代码、注意事项和相关问题,确保用户能够全面理解getopt_long的用法,并正确引用提供的资料。</think>### getopt_long 函数使用说明 #### 1. 函数原型 ```c #include <getopt.h> int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex); ``` [^1] #### 2. 参数解析 - **argc/argv**:与`main`函数参数一致,表示参数个数和参数值数组 - **optstring**:短选项字符串,格式如`"a:b:c::"`: - `:`表示前一个选项必须带参数(单个字符) - `::`表示前一个选项参数可选(GNU扩展) - **longopts**:长选项结构体数组,定义如下: ```c struct option { const char *name; // 长选项名称 int has_arg; // 是否需要参数:no_argument(0), required_argument(1), optional_argument(2) int *flag; // 若为NULL,getopt_long返回val值;否则将变量指向val int val; // 关联的短选项字符值 }; ``` [^2] - **longindex**:若不为NULL,返回匹配的长选项在`longopts`数组中的索引 #### 3. 使用步骤 1. **定义选项结构体数组**: ```c static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"output", required_argument, 0, 'o'}, {"verbose", optional_argument, 0, 'v'}, {0, 0, 0, 0} // 结束标记 }; ``` 2. **构造optstring**: ```c char *optstring = "ho:v::"; // h无参数,o需参数,v可选参数 ``` 3. **循环处理参数**: ```c int opt; while ((opt = getopt_long(argc, argv, optstring, long_options, NULL)) != -1) { switch (opt) { case 'h': printf("帮助信息\n"); break; case 'o': printf("输出文件:%s\n", optarg); break; case 'v': printf("详细模式,参数:%s\n", optarg ? optarg : "默认值"); break; case '?': printf("未知选项\n"); break; } } ``` #### 4. 关键特性 - 同时支持短选项(如`-h`)和长选项(如`--help`) - 通过`optarg`全局变量获取选项参数 - 通过`optind`记录当前处理的参数索引 #### 5. 注意事项 - 长选项结构体数组必须以全零元素结尾 - optstring中短选项顺序不影响解析逻辑 - 若需禁用错误输出,可设置`opterr = 0` - 多次调用需重置`optind = 1`(非GNU系统可能不支持) ```c // 完整示例:解析 --input=file.txt -n 5 格式参数 struct option opts[] = { {"input", required_argument, 0, 'i'}, {"number", required_argument, 0, 'n'}, {0,0,0,0} }; char *optstr = "i:n:"; ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欲盖弥彰1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值