Linux下getopt、getopt_long函数解析以及使用例程


今天准备在阅读Android系统dumpsys源码的时候,初次看到getopt_long函数,看着有点懵逼,严重阻塞我的源码阅读,因此下定决心要研究明白它,顺便记录一下如何使用,防止遗忘。

getopt函数的使用

getopt函数主要是用于方便我们解析命令行参数的C函数, 允许你处理短选项(以单个短划线开头的选项,例如-a,-b)和带参数的短选项(例如-o filename)。比较常用的场景是,我们自己开发了一个小工具,在解析命令行参数的时候,非常方便。

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

参数

argc、argv[]

argc和argv就是main函数的参数是一致的,直接传入即可

optstring

char *optstring = "ab:";

optstring的使用比较简单。短选项字符串:a表示-a选项,不带参数。b:表示-b选项,带一个参数。注意不支持带多个参数哈

返回值

  • 如果找到了合法的选项字符,比如 -a 或 -b,则 getopt 返回这个字符,例如 ‘a’ 或 ‘b’。
  • 如果选项字符后面有冒号(:),表示这个选项需要一个参数。例如,如果 shortopts 是 b:, 选项 -b 必须有一个参数。在这种情况下,getopt 会把参数的指针存储在全局变量 optarg 中。
  • 如果发现一个选项字符不在 shortopts 中,返回 ‘?’ 并且 opterr 设置为 1(默认)。
  • 如果选项要求参数而没有提供参数(例如 -b 后没有参数,shortopts 中为 b:),同样返回 ‘?’,并且 opterr 设置为 1(默认)。同时 optopt 会保存无法识别的选项字符。
  • 识别到选项结束,当所有选项都解析完成时,getopt 返回 -1,并且全局变量 optind 设置为第一个非选项参数的索引。

全局变量

  • optarg:指向当前选项的参数值(如果存在)。
  • optind:指向下一个要处理的命令行参数的索引。
  • optopt:存储当前未被识别的选项字符。
  • opterr:如果为非零,getopt 会输出错误信息到 stderr(默认是 1)。

Demo:getopt

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
    int opt;
    printf("beging optind = %d\n", optind);

   opterr = 0;

   printf("--------------------------------------------------------------\n");

    while ((opt = getopt(argc, argv, "ab:c:")) != -1) {

        printf("opt = %c, optind = %d, optarg = %s, opterr = %d, optopt = %c\n", opt, optind,  optarg, opterr, optopt);

        switch (opt) {
            case 'a':
                printf("Option -a\n");
                break;
            case 'b':
                printf("Option -b with argument '%s'\n\n", optarg);
                break;
            case 'c':
                printf("Option -c,with argument '%s'\n\n", optarg);
                break;
            case '?':
                fprintf(stderr, "Option -%c requires an argument.\n\n", optopt);
                return 1;
            default:
                fprintf(stderr, "Usage: %s [-a] [-b value] [-c]\n\n", argv[0]);
                exit(EXIT_FAILURE);
        }

        printf("--------------------------------------------------------------\n");
    }
    
    int index = optind;
    for (index; index < argc; index++) {
        printf("Non-option argument: %s\n", argv[index]);
    }

    return 0;
}

Demo验证结果如下:

  • 正常情况下:
    在这里插入图片描述

  • 需要参数,但不传入情况:
    在这里插入图片描述

  • 非参数选项
    在这里插入图片描述

getopt_long

getopt_long和getopt不同的地方在于,getopt_long可以同时接受短选项和长选项,并可以选择不接受短选项

int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);

参数

argc和argv

argc和argv就是main函数的参数是一致的,直接传入即可

optstring

optstring用户和getopt的用法一致,如果选择不接受短参数,可以填NULL

longopts

getopt_long和getopt最大的差别就在于这里,这个参数需要传入一个结构体数组。结构体长这个样子。

struct option
{
  const char *name; //长选项的名字
  int has_arg;//长选项是否带参数
  int *flag;//标志变量。如果为 NULL,则 getopt_long 返回 val 的值。如果非 NULL,则 getopt_long 设置此指针指向变量为 val,并返回 0
  int val;
};

longindex

如果不为 NULL,它指向一个整数,该整数保存匹配的长选项在 longopts 数组中的索引。

全局变量

同getopt

Demo:getopt_long

#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>

int flag = 0;

struct option long_options[] = {
    {"help", required_argument, &flag, 1024},
    {"best", required_argument, NULL, 2048},
    {"only", required_argument, NULL, 'o'},
    {0, 0, 0, 0}
};

int main(int argc, char *argv[]) {
    int opt;
    int option_index = 0;

    printf("--------------------------------------------------------------\n");

    while ((opt = getopt_long(argc, argv, "o:", long_options, &option_index)) != -1) {

        printf("opt = %d, %c, flag = %d, option_index = %d\n\n", opt, opt, flag, option_index);
        switch (opt) {
            case 0:
                printf("flag =  %d\n", flag);
                printf("flag is not null, value: %s\n\n", optarg);
                break;
            case 2048:
                printf("best called, value: %s\n\n", optarg);
                break;
            case 'o':
                printf("-o or --only called , value: %s\n\n", optarg);
                break;
            case '?':
                printf("Usage: xxxxxx \n\n");
                exit(EXIT_FAILURE);
            default:
                printf("?? getopt returned character code 0%o ??\n\n", opt);
        }

        printf("--------------------------------------------------------------\n");
    }

    
    int i = optind;
    for (i; i < argc; i++) {
        printf("Remaining argument: %s ??\n", argv[i]);
    }

    return 0;
}

Demo验证结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

叮当学长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值