C语言中命令行工具 (getopt和getopt_long)

2023-05-16


#include <iostream>
#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

using namespace std;

/* @getopt的全局变量
** 1. char* optarg:正在解析的选项的参数
** 2. int optind:指向下一个选项的索引
** 3. int opterr:非0时会将错误信息打印在stdout上
** 4. int optopt:若一个选项在argv中,但不在选项字符串中时,或者一个带参数的选项没有参数时,getopt()会返回字符?,同时将optopt设为该选项
*/
extern char *optarg;
extern int optind, opterr, optopt;

void test01(int argc, char *argv[])
{
    /* @param
    ** 参数选项有  -a -b -c -d
    ** 其中-a  -b后面不带“:”  所以这两个选项不可以有参数,即使有参数他也不会去识别
    ** -c 后面有一个“:”  所以这个选项后面必须有参数,参数有两种形式  1. 参数紧贴选择项 -b100 ;  2. 参数跟选项使用空格分隔  -b 100
    ** -d 后面有两个“:”  所以这个选项后面的参数可有可无,当有参数的时候  参数必须紧贴选项
    */
    int opt = -1;
    while (opt = getopt(argc, argv, "abc:d::") != -1)
    {
        cout << "opt: " << opt << endl;

        cout << "optarg:" << optarg << endl;
        cout << "optopt:" << optopt << endl;
        cout << "optind:" << optind << endl;
    }

    cout << "opterr:" << opterr << endl;
}

/*
** getopt()允许我们设置optstring的首字符为冒号":",在这种情况下,
** 当发生无法识别的选项错误时getopt()返回字符"?",当发生丢失选项参数错误时返回字符":"。
** 这样我们就可以很轻松地分辨出错误类型了,
** 不过getopt()不会再打印错误信息了,一切事物都由我们自己来处理了。
*/

void test02(int argc, char *argv[])
{
    int verbose = 0; // 一个输出的判断条件
    int n = 0;       // 用于计数
    char opt;        // 用于存getopt函数的返回值

    // 一直循环解析  直到解析完毕
    while ((opt = getopt(argc, argv, "vn:")) != -1)
    {
        switch (opt)
        {
        case 'v':
            verbose = 1; // 将输出条件判断置为1
            break;
        case 'n':
            n = atoi(optarg); // 将选项-n的参数字符串转为整数
            cout << "n : " << n << endl;
            break;
        default:
            fprintf(stderr, "usage: error");
            exit(-1); // 异常退出程序
        }
    }
    int i = 0;
    for (i = 0; i < n; ++i)
    {
        if (verbose)
            cout << i << endl;
    }
    cout << "Done counting to " << n << endl;
}

int main1(int argc, char *argv[])
{
    if (argc < 2)
        return -1;
    test02(argc, argv);

    return 0;
}

/* ---------------------------------------------------------  */
/*
** int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
** 与getopt类似  但是getopt_long可接收长选项,长选项以“--”开头
** 如果程序只接受长选项,必须将optstring设置为空字符串“”
** 长选项可以采用两种形式:--arg=param或--arg param
** longopts是一个指针指向结构体option数组
*/
/* option结构体
** struct option {
**   const char *name;      // 长选项的名字
**   int         has_arg;   // 0不需要参数,1需要参数,2参数可选
**   int        *flag;      // 指定长选项的返回结果类型:flag=NULL时getopt_long返回val(可以将val设置为等效的短选项字符),flag!=NULL时getopt_long返回0
**   int         val;       // 要返回的值
** };
*/

int main(int argc, char *argv[])
{
    int c;
    int digit_optind = 0;

    while (1)
    {
        int this_option_optind = optind ? optind : 1;
        int option_index = 0;
        static struct option long_options[] = {
            {"add", required_argument, 0, 0},
            {"append", no_argument, 0, 0},
            {"delete", required_argument, 0, 0},
            {"verbose", no_argument, 0, 0},
            {"create", required_argument, 0, 'c'},
            {"file", required_argument, 0, 0}, // optional_argument  参数可选
            {0, 0, 0, 0}
            /* 注意:option结构数组的最后一个元素必须用0填充 */
        };

        c = getopt_long(argc, argv, "abc:d:012", long_options, &option_index);
        if (c == -1)
            break;

        switch (c)
        {
        case 0:

            if (strcmp(long_options[option_index].name, "add") == 0)
                fprintf(stdout, "long option \"add\" value: %s\n", optarg);
            else if (strcmp(long_options[option_index].name, "append") == 0)
                fprintf(stdout, "long option \"append\"\n");
            else if (strcmp(long_options[option_index].name, "delete") == 0)
                fprintf(stdout, "long option \"delete\" value: %s\n", optarg);
            else if (strcmp(long_options[option_index].name, "create") == 0)
                fprintf(stdout, "long option \"create\" value: %s\n", optarg);
            else if (strcmp(long_options[option_index].name, "verbose") == 0)
                fprintf(stdout, "long option \"verbose\"\n");
            else if (strcmp(long_options[option_index].name, "file") == 0)
                fprintf(stdout, "long option \"file\" value: %s\n", optarg);
            break;
        case '0':
        case '1':
        case '2':
            if (digit_optind != 0 && digit_optind != this_option_optind)
                fprintf(stdout, "digits occur in two different argv elements.\n");
            digit_optind = this_option_optind;
            fprintf(stdout, "option %c\n", c);
            break;
        case 'a':
            fprintf(stdout, "option a\n");
            break;
        case 'b':
            fprintf(stdout, "option b\n");
            break;
        case 'c':
            fprintf(stdout, "option c with value '%s'\n", optarg);
            break;
        case 'd':
            fprintf(stdout, "option d with value '%s'\n", optarg);
            break;
        case '?':
            break;
        default:
            fprintf(stdout, "?? getopt returned character code 0%o ??\n", c);
        }
    }

    if (optind < argc)
    {
        fprintf(stdout, "non-option argv elements: ");
        while (optind < argc)
            fprintf(stdout, "%s ", argv[optind++]);
        fprintf(stdout, "\n");
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言中命令行工具 (getopt和getopt_long) 的相关文章

随机推荐

  • 面向对象单例模式

    单例模式 xff1a 一个类只能创建一个对象 span class token keyword class span span class token class name A span span class token punctuati
  • 设计模式之代理模式

    概念 xff1a 为其他对象提供一种代理 xff0c 用来控制对象的访问 在某些情况下 xff0c 一个对象不适合或不能直接引用另一个对象 xff0c 而代理对象可以在客户端和目标对象之间起到中介作用 span class token co
  • ARM接口技术基础

    ARM介绍 嵌入式系统 xff1a 嵌入式系统 61 嵌入式硬件 43 嵌入式软件 硬件是软件的载体 xff0c 软件是硬件的灵魂 嵌入式软件 xff1a 1 裸机 xff1a APP 2 系统 xff1a OS 43 APP 嵌入式硬件
  • ARM指令之MOV指令汇编与机器码的对应关系

    指令条件码 条件码就是一种简单的测试ALU状态标志位的方法 mov指令机器码 比如 xff1a mov r1 3 立即数 xff1a 3 第一个操作数 xff1a 寄存器1 S xff1a 0 xff08 注意 xff1a mov指令后面加
  • 设计模式之外观模式

    什么是外观模式 外观模式就是将一个复杂的子类系统抽象到同一个接口进行管理 外界只需要通过此接口与子类系统进行交互 xff0c 不需要直接与复杂的子类系统进行交互 外观模式属于结构型模式 外观模式案例 1 实现KTV模式 xff1a 打开电视
  • 设计模式之适配器模式

    概念 将一个类的接口转换成客户希望的另外一个接口 使得原本由于接口不兼容而不能一起工作的那些类可以一起工作 用vector容器中的for each 举例子 span class token keyword class span span c
  • Qt基础学习笔记

    Qt中的常用快捷键 注释 xff1a ctrl 43 运行 xff1a ctrl 43 r 编译 xff1a ctrl 43 b 帮助文档 xff1a F1 自动对齐 xff1a ctrl 43 i 同名之间 h文件与 cpp文件的切换 x
  • Nginx学习 (1) —— 初识Nginx(编译安装、启动停止、简单配置)

    文章目录 Nginx的发行版本Nginx的编译安装 xff08 ubuntu18 04 xff09 Nginx相关操作Nginx启动停止命令安装Nginx为系统服务 Nginx的目录结构与基本原理目录结构 xff1a 基本运行原理 xff1
  • Nginx学习 (2) —— 虚拟主机配置

    文章目录 虚拟主机原理域名解析与泛域名解析 xff08 实践 xff09 配置文件中ServerName的匹配规则技术架构多用户二级域名短网址 虚拟主机原理 为什么需要虚拟主机 xff1a 当一台主机充当服务器给用户提供资源的时候 xff0
  • 如任让Echarts默认显示全部的数据(x轴(时间轴)默认显示查询到的所有数据)

    Echarts绘制折线图 有时候会用到时间轴 但是有时候时间轴默认显示的是部分数据 而不是全部的数据 当客户要求默认显示全部的数据的时候 就可以使用下面的方法 把dataZoom属性的startValue设置为0即可 dataZoom st
  • Nginx学习(3)—— 反向代理、负载均衡、动静分离、URLRewrite、防盗链

    文章目录 网关 代理与反向代理Nginx的反向代理配置基于反向代理的负载均衡的配置负载均衡策略负载均衡权重相关配置 xff08 weight xff09 动静分离Nginx配置动静分离 URL rewrite伪静态配置负载均衡 43 URL
  • Nginx学习(4)—— 高可用配置(keepalived实现Nginx的高可用)

    文章目录 高可用场景及解决方案keepalived的安装 高可用场景及解决方案 一般高可用的服务端会都有备用服务 xff0c 当某一个服务节点挂掉的时候就会有备用机顶上 这往往需要反向代理 Nginx 来将连接切换到可用的服务机器上 如下图
  • Nginx学习(5)—— 基本结构(源码)

    文章目录 Nginx源码学习基本数据结构1 字符串结构 xff1a ngx str t2 类似资源管理的结构 xff1a ngx pool t3 Nginx数组结构 xff1a ngx array t4 哈希表结构 xff1a 1 ngx
  • Nginx学习(6)—— handler模块(自定义handler配置模块的编码编译)

    文章目录 Nginx请求的处理handler简介handler模块的基本结构模块配置结构模块配置指令先看一下 ngx command t 结构 一个模块配置的demo简单模块配置的案例演示 模块上下文结构模块的定义handler模块的基本结
  • Nginx学习(7)—— 过滤模块(filter)

    文章目录 过滤模块简介执行时间和内容执行顺序Nginx是怎么按照次序依次来执行各个过滤模块的呢这些过滤模块的简述 xff08 按执行顺序 xff09 模块编译过滤模块分析相关结构体 响应头过滤函数响应体过滤函数主要功能介绍发出子请求优化措施
  • Nginx学习(8)—— upstream模块

    文章目录 upstream模块简介upstream模块接口memcached模块分析小结 upstream模块简介 nginx模块一般被分成三大类 xff1a handler filter和upstream 前面的章节中 xff0c 读者已
  • Nginx学习(9)—— 负载均衡模块

    文章目录 Nginx负载均衡模块负载均衡配置指令钩子初始化配置初始化请求peer get和peer free回调函数 小结 Nginx负载均衡模块 负载均衡模块用于从 upstream 指令定义的后端主机列表中选取一台主机 nginx先使用
  • Nginx学习(10)—— event模块、core模块、变量

    文章目录 core模块Nginx启动模块 event模块event的类型和功能accept锁 定时器变量Nginx中的变量指的是什么Nginx中如何创建变量Nginx中如何使用变量举个例子 Nginx的模块种类有很多 xff0c 除了HTT
  • Nginx学习(11)—— Nginx源码架构、configure是怎么执行的(编译的具体细节)

    文章目录 Nginx的源码目录结构Nginx中configure的原理auto脚本 模块编译顺序 Nginx的源码目录结构 nginx的源码目录与nginx的模块化以及功能的划分是紧密结合 xff0c 这也使得我们可以很方便地找到相关功能的
  • C语言中命令行工具 (getopt和getopt_long)

    span class token macro property span class token directive hash span span class token directive keyword include span spa