我记不住的getopt_long的那些参数和返回值

前言:最近在学习面向Linux系统进行C语言的编程,通过查询man手册和查看网络上的各种文章来获取一点点的知识,重点是看完手册还是一脸懵逼,搞不懂手册里面再说啥,而本篇文章将记录一下学习getopt_long的那些参数和返回值,希望能和大家讲清楚和说明白。

optstring分为三种选项 普通的,必须选项(:),可选选项(::),这个略,可以自行百度。

0. 可选选项

optstring 为 ":a::b:X"
Option syntaxMeaning
-a
OK, No argument provided (optional).
-afoo
OK, argument is foo
-a foo
Wrong, no space allowed with optional arguments.
foo is considered a non-option argument.
-bfoo
OK, argument is foo (required).
-b foo
OK, argument is foo (required).
-b
Wrong, option b requires an argument.

注意:可选参数需要紧紧挨着写,不能有空格。

1. 未知的选项和缺少选项参数(Unknown Options and Missing Option Arguments)

当我们面对上面两个情况时候,如何进行处理

optstring为 "a:b:X"

当我们输入 -t 时候会出现 "未知的选项"的错误;

当我们输入 -a 而不输入选项参数时候,会出现"缺少选项参数"的错误;

一般情况下getopt会输出错误,但是我们希望我们能有相关的语句去处理或自定义提示。

我们通过在 optstring前面添加 ":",即 ":a:b:X"来进行解决,代码如下所示:

/* Notice the leading : in the option string */   optwhile ((opt = getopt(argc, argv, ":a:b:X")) != -1) 
{switch (opt) {case 'a':printf("Option a has arg: %s\n", optarg);break;case 'b':printf("Option b has arg: %s\n", optarg);break;case 'X':printf("Option X was provided\n");break;case '?':printf("Unknown option: %c\n", optopt);break;case ':':printf("Missing arg for %c\n", optopt);break;}
}

假设这个程序输出为a.out, 则测试结果为:

Command line optionsOutput
./a.out -a
Missing arg for a
./a.out -t
Unknown option: t
./a.out -a one -t -X -b
Option a has arg: one
Unknown option: t
Option X was provided
Missing arg for b
./a.out -a one,two,three
Option a has arg: one,two,three
./a.out -a "one two three"
Option a has arg: one two three

我们查看文档, man 3 getopt 有如下文字,与咱们测试结果一致:

是说以":"开头的话,getopt不会打印错误同时针对 缺少选项参数的情况会返回 ":" ,这样可以让调用者或开发者区分这两种情况。通过添加":"将getopt关闭打印错误输出。

2. nonoption是否有序及获取相关值

nonoption,换一种写法 non-option也行,意思是非选项参数

比如,我们执行gcc程序,如下所示:

gcc -Wall -Wextra main.c foo.c bar.c -O -o program -ansi -pedantic -Werror

哪个是non-option,其实就是前面没有"-"和"--"的,也就是 main.c/foo.c/bar.c, 而 program是-o选项的参数它不是nonoption。

我们先试一下:

#include <stdio.h>  /* printf */
#include <getopt.h> /* getopt */int main(int argc, char *argv[])
{int opt;while ((opt = getopt(argc, argv, ":a:b:X")) != -1) {switch (opt) {case 'a':printf("Option a has arg: %s\n", optarg);break;case 'b':printf("Option b has arg: %s\n", optarg);break;case 'X':printf("Option X was provided\n");break;case '?':printf("Unknown option: %c\n", optopt);break;case ':':printf("Missing arg for %c\n", optopt);break;}}/* Get all of the non-option arguments */if (optind < argc) {printf("Non-option args: ");while (optind < argc)printf("%s ", argv[optind++]);printf("\n");}return 0;
}

测试结果为:

Command line optionsOutput
./a.out x -a one y -X z
Option a has arg: one
Option X was provided
Non-option args: x y z 
./a.out x y z -a one -b two
Option a has arg: one
Option b has arg: two
Non-option args: x y z 

我们发现了一个奇怪的现象,就是这些非选项参数即使写在了其他选项参数的前面,但是它输出在了最后面,也就是说并没有按照书写的顺序进行输出。

原因是:getopt函数会将这些非选项参数放到数组argv的最后,当没有选项处理则返回-1并终止while循环。我们通过optind进行循环来获取后续的参数。

如果你想获取这些 非选项参数并且是按顺序进行输出,你需要在optstring前加"-",通过添加"-"来关闭getopt将non option移动到argv数组末尾。

#include <stdio.h>  /* printf */
#include <getopt.h> /* getopt */int main(int argc, char *argv[])
{int opt;/* Notice the leading minus sign - in the option string below   */   /* Remember that the number one in single quotes '1' is not the */   /* same as the number one without quotes. '1' is ASCII 49       */   while ((opt = getopt(argc, argv, "-:a:b:X")) != -1) {switch (opt) {case 'a':printf("Option a has arg: %s\n", optarg);break;case 'b':printf("Option b has arg: %s\n", optarg);break;case 'X':printf("Option X was provided\n");break;case '?':printf("Unknown option: %c\n", optopt);break;case ':':printf("Missing arg for %c\n", optopt);break;case 1:printf("Non-option arg: %s\n", optarg);break;}}return 0;
}

当存在 non option出现时候,getopt_long函数返回值为 1

测试结果为:

Command line optionsOutput
./a.out x y z -a foo

Non-option arg: x

Non-option arg: y

Non-option arg: z

Option a has arg: foo

./a.out x -a foo y -b bar z -X w

Non-option arg: x

Option a has arg: foo

Non-option arg: y

Option b has arg: bar

Non-option arg: z

Option X was provided

Non-option arg: w

./a.out -t x -a foo -M y -b bar z -X w -b
Unknown option: t
Non-option arg: x
Option a has arg: foo
Unknown option: M
Non-option arg: y
Option b has arg: bar
Non-option arg: z
Option X was provided
Non-option arg: w
Missing arg for b

3.长选项以及短选项和长选项的关联

短选项的缺点是:

1. 选项个数受限,对于小程序这个倒没事,但是对于一个复杂的程序就显着不足,

2. 无法记住短选项的意思,比如 -a代表add,但是无法代表alter等

看一下rsync和wget你就会发现有很多的参数,而 getopt_long就是处理长选项的函数。

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

argc 代表参数的个数

argv 代表保存各个参数的数组,每个参数是一个字符串

optstring 代表短选项的字符串

longopts 代表长选项的配置数组指针

longindex 代表 longopts数组的索引的指针

struct option 
{const char *name;    /* name without -- in front                                  */int         has_arg; /* one of: no_argument, required_argument, optional_argument */int        *flag;    /* how the results are returned                              */int         val;     /* the value to return or to put in flag                     */
};static struct option long_options[] = {{"add",     required_argument, NULL,  0 },{"append",  no_argument,       NULL,  0 },{"delete",  required_argument, NULL,  0 },{"verbose", no_argument,       NULL,  0 },{"create",  required_argument, NULL,  0 },{"file",    optional_argument, NULL,  0 },{NULL,      0,                 NULL,  0 }};

如果flag为NULL,则这个 getopt_long函数返回 val 

如果flag为指针,则将val放到flag指针中,这个getopt_long函数返回 0 

测试程序如下:

#include <getopt.h> /* getopt */
#include <stdlib.h> /* exit   */
#include <stdio.h>  /* printf */int main(int argc, char **argv)
{int c;while (1) {int option_index = 0;static struct option long_options[] = {{"add",     required_argument, NULL,  'a'},{"append",  no_argument,       NULL,  'p'},{"delete",  required_argument, NULL,  'd'},{"verbose", no_argument,       NULL,  'v'},{"create",  required_argument, NULL,  'c'},{"file",    optional_argument, NULL,  'f'},{NULL,      0,                 NULL,    0}};/* Still need to provide an option string for the short options */c = getopt_long(argc, argv, "-:a:pd:vc:f::", long_options, &option_index);if (c == -1)break;switch (c) {case 0:printf("long option %s", long_options[option_index].name);if (optarg)printf(" with arg %s", optarg);printf("\n");break;case 1:printf("regular argument '%s'\n", optarg);break;case 'a':printf("option a with value '%s'\n", optarg);break;case 'p':printf("option p\n");break;case 'd':printf("option d with value '%s'\n", optarg);break;case 'v':printf("option v\n");break;case 'c':printf("option c with value '%s'\n", optarg);break;case 'f':printf("option f with value '%s'\n", optarg ? optarg : "NULL");break;case '?':printf("Unknown option %c\n", optopt);break;case ':':printf("Missing option for %c\n", optopt);break;default:printf("?? getopt returned character code %c ??\n", c);}
}

测试结果为:

Command lineOutput
./a.out --delete=foo -c5 --add=yes --append
option d with value 'foo'
option c with value '5'
option a with value 'yes'
option p
./a.out --d=foo --ad=yes --ap
option d with value 'foo'
option a with value 'yes'
option p
./a.out --create=5 --create 6 --c=7 --c 8  
option c with value '5'
option c with value '6'
option c with value '7'
option c with value '8'
./a.out --file=5 --file 6 --file7
option f with value '5'
option f with value 'NULL'
regular argument '6'
Unknown option 

--d能匹配上--delete,--ad能匹配上--add,--ap能匹配上--append,--c能匹配上--create

4. 传true或false

有些时候的选项并不进行传值,而是传true或false

gcc -c foo.c   // -c 就是一个flag,代表true只编译不链接。如果不写,则进行编译和链接。
#include <getopt.h> /* getopt */
#include <stdio.h>  /* printf *//* File scope flags, all default to 0 */
static int f_add;
static int f_append;
static int f_create;
static int f_delete;
static int f_verbose;int main(int argc, char **argv)
{int c;while (1) {int option_index = 0;static struct option long_options[] = {{"add",     no_argument, &f_add,     1},{"append",  no_argument, &f_append,  1},{"create",  no_argument, &f_create,  1},{"delete",  no_argument, &f_delete,  1},{"verbose", no_argument, &f_verbose, 1},{NULL,      0,           NULL,       0}};c = getopt_long(argc, argv, "-:", long_options, &option_index);printf("the value of c : %d\n",c);if (c == -1)break;switch (c) {case 1:printf("non option argument '%s'\n", optarg);break;case '?':printf("Unknown option %c\n", optopt);break;}}printf("    f_add: %i\n", f_add);printf(" f_append: %i\n", f_append);printf(" f_delete: %i\n", f_delete);printf(" f_create: %i\n", f_create);printf("f_verbose: %i\n", f_verbose);return 0;
}

测试结果为:

Command lineOutput
./a.out --verbose --create
    f_add: 0f_append: 0f_delete: 0f_create: 1
f_verbose: 1
./a.out --verbose --append --create --add --delete
    f_add: 1f_append: 1f_delete: 1f_create: 1
f_verbose: 1
./a.out --v --c --ap --ad --d
    f_add: 1f_append: 1f_delete: 1f_create: 1
f_verbose: 1
./a.out -v -c -d -a
Unknown option v
Unknown option c
Unknown option d
Unknown option af_add: 0f_append: 0f_delete: 0f_create: 0
f_verbose: 0

如果flag为NULL,则这个 getopt_long函数返回 val 

如果flag为指针,则将val放到flag指针中,这个getopt_long函数返回 0 

5. 我的小代码

#include <stdio.h>     /* for printf */
#include <stdlib.h>    /* for exit */
#include <getopt.h>int main(int argc, char *argv[])
{int c;int digit_optind = 0;// 默认为0static int f_flag;while (1) {int this_option_optind = optind ? optind : 1;int option_index = 0;static struct option long_options[] = {{"add",     required_argument, 0, 'a'},{"append",  no_argument,       0, 'p'},{"delete",  required_argument, 0, 'd'},{"verbose", no_argument,       0, 'v'},{"create",  required_argument, 0, 'c'},{"file",    optional_argument, 0, 'f'},{"help",    no_argument,       0, 'h'},{"flag",    no_argument, &f_flag,  1 },{0,         0,                 0,  0 }};c = getopt_long(argc, argv, "-:a:pd:vc:f::h",long_options, &option_index);//printf("the value of c : %d\n",c)if (c == -1)break;switch (c) {case 0:printf("%s (true of false),the flag value is %d\n", long_options[option_index].name,f_flag);break;case 1:printf("non option argument '%s'\n", optarg);break;case 'a':printf("option a or add with value '%s'\n", optarg);break;case 'p':printf("option p or append\n");break;case 'd':printf("option d or delete with value '%s'\n", optarg);break;case 'v':printf("option v or verbose\n");break;case 'c':printf("option c or create with value '%s'\n", optarg);break;case 'f':printf("option f or file with value '%s'\n", optarg ? optarg : "NULL");break;case '?':printf("Unknown option %c\n", optopt);break;case ':':printf("Missing option for %c\n", optopt);break;default:	printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]);printf("\t-a,--add           add somethings(required argument)\n");printf("\t-p,--append        append somethings(no argument)\n");printf("\t-d,--delete        delete somethings(required argument)\n");printf("\t-v,--verbose       show the verbose(no argument)\n");printf("\t-c,--create        create somethings(required argument)\n");printf("\t-f,--file          add a file(required argument)\n");printf("\t-h,--help          help(no argument)\n");printf("\t--flag             flag 0 or 1(no argument)\n");printf("\n");exit(0);}} exit(EXIT_SUCCESS);
}

这个代码可以输出帮助信息,以及 上述0、1、2、3、4等各种问题的结合版,可以参考,谢谢。

参考文档:

1. Example of Getopt (The GNU C Library)

2. man 3 getopt

3.Mead's Guide To getopt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/194980.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ElasticStack日志分析平台-ES 集群、Kibana与Kafka

一、Elasticsearch 1、介绍&#xff1a; Elasticsearch 是一个开源的分布式搜索和分析引擎&#xff0c;Logstash 和 Beats 收集的数据可以存储在 Elasticsearch 中进行搜索和分析。 Elasticsearch为所有类型的数据提供近乎实时的搜索和分析&#xff1a;一旦数据被索引&#…

0基础学习PyFlink——水位线(watermark)触发计算

在《0基础学习PyFlink——个数滚动窗口(Tumbling Count Windows)》和《0基础学习PyFlink——个数滑动窗口&#xff08;Sliding Count Windows&#xff09;》中&#xff0c;我们发现如果窗口中元素个数没有把窗口填满&#xff0c;则不会触发计算。 为了解决长期不计算的问题&a…

PyCharm 【unsupported Python 3.1】

PyCharm2020.1版本&#xff0c;当添加虚拟环境发生异常&#xff1a; 原因&#xff1a;Pycharm版本低了&#xff01;不支持配置的虚拟环境版本 解决&#xff1a;下载PyCharm2021.1版本&#xff0c;进行配置成功&#xff01;

2023年,全球CIO最关注的问题是什么?

面对AI大潮&#xff0c;全球CIO们在焦虑什么&#xff1f;随着全球数字化转型步伐的加速&#xff0c;CIO的角色发生了哪些转变&#xff1f; 继2022年5月发布首份全球CIO报告之后&#xff0c;联想集团今年又发布了以“韧性的全球首席信息官&#xff08;The Resilient CIO&#xf…

python大数据毕设选题

文章目录 0 前言1 大数据毕设选题推荐2 开题指导3 最后 0 前言 大家好&#xff01;大四的同学们&#xff0c;毕业设计的时间即将到来&#xff0c;你们准备好了吗&#xff1f;为了帮助大家更好地开始毕设&#xff0c;我作为学长给大家整理了最新的计算机大数据专业的毕设选题。…

微信公众号与小程序打通:流量变现的新路径

随着移动互联网的迅速发展&#xff0c;微信公众号和小程序已经成为企业营销和运营的重要工具。将微信公众号与小程序打通&#xff0c;不仅可以提高用户体验&#xff0c;还能有效提升流量的变现效率。本文将为您解析如何打通微信公众号与小程序&#xff0c;让流量快速变现。 一、…

开发知识点-Git

团队协作-Git Giteegitee 创建仓库打开项目所在目录&#xff0c;右键选择Git Bush Here(你要确定电脑上已经安装了Git&#xff09;初始化本地仓库配置验证信息。 完美解决github访问速度慢介绍Git 与 SVN 区别IDEA 添加 gitee Gitee Git Gitee 大家都知道国内访问 Github 速度…

【前段基础入门之】=>CSS3新特性 响应式布局

文章目录 概念媒体查询媒体类型媒体特性媒体运算符 概念 所谓对响应式布局方案的理解&#xff0c;众说纷纭&#xff0c;核心点就是同一套代码在不同尺度屏幕下的布局呈现方式的不同 社区中有很多人分享&#xff0c;并列出了多种实现响应式布局的方案&#xff0c;比如【 rem&…

quickapp_快应用_快应用组件

快应用组件 web组件web页面与快应用页面通信网页接收/发送消息网页接收消息 快应用页面接收/发送消息给网页发送消息 通信前提- trustedurl list组件refresh组件语法error-使用refresh组件会改变页面高度&#xff01;refresh组件list组件实现下拉刷新 tab组件 web组件 作用&am…

微信抽奖活动怎么做

微信抽奖活动&#xff1a;打破传统&#xff0c;创新互动&#xff0c;带给你超乎想象的惊喜体验&#xff01; 随着互联网的飞速发展&#xff0c;人们越来越热衷于参与各种线上活动。而微信&#xff0c;作为中国最大的社交平台之一&#xff0c;自然成为了各种活动的聚集地。今天…

IntelliJ IDEA 安装 GitHub Copilot插件 (最新)

注意&#xff1a; GitHub Copilot 插件对IDEA最低版本要求是2021.2&#xff0c;建议直接用2023.3&#xff0c;一次到位反正后续要升级的。 各个版本的依赖关系&#xff0c;请参照&#xff1a; ##在线安装&#xff1a; 打开 IntelliJ IDEA扩展商店&#xff0c;输入 "Git…

IntelliJ IDEA启动一个普通的java web项目的配置

原创/朱季谦 这是我很久以前刚开始用IntelliJ IDEA时记录的笔记&#xff0c;应该是五年前的一篇笔记了。正好赶上最近离职了&#xff0c;可以有比较多的时间把以前的记录整理一下&#xff0c;可以让刚接触到IntelliJ IDEA的童鞋学习如何在IntelliJ IDEA引入一个单机版的jar形式…

【python零基础入门学习】python进阶篇之数据库连接-PyMysql-全都是干货-一起来学习吧!!!

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

【npm 错误】:npm ERR! code ERESOLVE、npm ERR! ERESOLVE could not resolve问题

用过npm的小伙伴都会有这么一个情况出现&#xff0c;就是npm install /npm install xxxx 会出现改一连串的错误&#xff0c;如下&#xff1a; 解决办法&#xff1a; 只要在npm install后面加上--legacy-peer-deps就可以解决问题,安装插件也一样 npm install --legacy-peer-dep…

原论文一比一复现 | 更换 RT-DETR 主干网络为 【VGG13】【VGG16】【VGG19】| 对比实验必备

本专栏内容均为博主独家全网首发,未经授权,任何形式的复制、转载、洗稿或传播行为均属违法侵权行为,一经发现将采取法律手段维护合法权益。我们对所有未经授权传播行为保留追究责任的权利。请尊重原创,支持创作者的努力,共同维护网络知识产权。 论文地址:https://arxiv.o…

V10服务器安装virt-manage

kvm是什么 KVM(Kernel-based Virtual Machine, 即内核级虚拟机) 是一个开源的系统虚拟化模块。它使用Linux自身的调度器进行管理&#xff0c;所以相对于Xen&#xff0c;其核心源码很少。目前KVM已成为学术界的主流VMM之一&#xff0c;它包含一个为处理器提供底层虚拟化 可加载…

[CISCN 2023 华北]pysym

源码如下 from flask import Flask, render_template, request, send_from_directory import os import random import string app Flask(__name__) app.config[UPLOAD_FOLDER]uploads app.route(/, methods[GET]) def index():return render_template(index.html) app.route…

IDEA写mybatis程序,java.io.IOException:Could not find resource mybatis-config.xml

找不到mybatis-config.xml 尝试maven idea:module&#xff0c;不是模块构造问题 尝试检验pom.xml&#xff0c;在编译模块添加了解析resources内容依旧不行 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.or…

vb.net 实时监控双门双向门禁控制板源代码

本示例使用设备介绍&#xff1a;实时网络双门双向门禁控制板可二次编程控制网络继电器远程开关-淘宝网 (taobao.com) Imports System.Net.Sockets Imports System.Net Imports System.Text Imports System.ThreadingImports System.Net.NetworkInformation Imports System.Man…

释放搜索潜力:基于Milvus快速搭建语义检索系统(快速版),让信息尽在掌握

搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术细节以及项目实战(含码源) 专栏详细介绍:搜索推荐系统专栏简介:搜索推荐全流程讲解(召回粗排精排重排混排)、系统架构、常见问题、算法项目实战总结、技术…