getopt、getopt_long和getopt_long_only

2024-04-12 03:08
文章标签 long getopt

本文主要是介绍getopt、getopt_long和getopt_long_only,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如何分析命令行参数

1、长选项、短选项

GNU/Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符
。比如有一个命令:

$ myprog -a vv --add -b --file a.txt b.txt - -- -e c.txt

在GNU/Linux系统,对这种情况的一种合理解释是:
a是短选项,带一个参数vv;
add是长选项,无参数;
b是短选项,无参数;
file是长选项,带一个参数a.txt;
b.txt是参数;
-是参数,通常表示标准输入,stdin;
--是一个指示符,表明停止扫描参数,其后所有部分都是参数,而不是选项;
-e是参数;
c.txt是参数

2、选项分析函数

为了简化程序设计,有几个库函数可以优雅地分析命令行参数,原型如下:

#include <unistd.h>
int getopt(int argc, char * const argv[],const char *optstring);
全局变量:
extern char *optarg;
extern int optind, opterr, optopt;#define _GNU_SOURCE
#include <getopt.h>
int getopt_long(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char * const argv[],const char *optstring,const struct option *longopts, int *longindex);
3、函数用法

(1)getopt函数,用于分析短选项

参数含义如下:

argc, argv是从main函数获取的参数,原样传给getopt;argc记录参数个数,包括函数名;argv存储函数参数,包括函数名;
optstring为字符串,指示如何分析参数。

关于optstring的几点说明:
a、如果选项带参数,该选项后接冒号,比如上例中optstring为"a:b",指示a带参数,b没有参数;
b、如果选项带可选参数,该选项后接两个冒号,比如"a::b",表明a可能有参数,也可能没有;
c、如果optstring的开头字符为':',表明如果指明选项带参数,而实际命令行没有参数时,getopt返回':'而不是'?'(默认情况下返回'?',和无法识别选项时返回一样);
d、如果optstring的开头字符为'+',表明一但遇到一个无选项的参数(指参数前面没有选项),马上停止扫描,随后的部分当作参数来解释;
e、如果optstring的开头字符为'-',表明如果遇到无选项的参数,则把它当作选项1(不是字符'1')的参数(不是很明白)

f、该函数每解析完一个选项,就返回该选项字符

g、如果选项带参数,参数保存在optarg中。如果选项带可选参数,而实际无参数时,optarg为NULL。

h、当遇到一个不在optstring指明的选项时,返回字符‘?’;如果在optstring指明某选项带参数而实际没有参数时,返回字符‘?’或者字符‘:’,视optstring的第一个字符而定。这两种情况选项的实际值被保存在optopt中。

i、当解析错误时,如果opterr为1则自动打印一条错误消息(默认),否则不打印。

j、当解析完成时,返回-1。

k、每当解析完一个argv,optind就会递增。如果遇到无选项的参数,getopt默认会把该参数调后一位(本人理解应该是指针位置往后串),接着解析下一个参数(这里的参数包括:选项、选项所带的参数、无选项的参数,是个广义的参数概念)。如果解析完成后还有无选项的参数,则optind指示的是第一个无选项的参数在argv中的索引。

(2)getopt_long()函数,同时可以分析短选项和长选项

getopt_long()的工作方式类似于getopt(),不过它还能接收长选项。在接收长选项之前,我们必须定义个一个结构体数组变量longopts,指明我们希望获取的长选项。

struct option {
const char *name;
int has_arg;
int *flag;
int val;
};

含义如下:
name指明长选项的名称;
has_arg指明该选项是否带参数,1为是,0为否,2为可选;
flag指明长选项如何返回,如果flag为NULL,则getopt_long返回val;否则返回0,flag指向的值赋值为val变量的值。如果该长选项没有发现,flag指向的值保持不变;val指明返回的值,或者需要加载到被flag所指示的变量中的值。

option数组的最后一个元素必须全部填充0.

getopt_long的最后一个参数longindex在函数返回时指向被搜索到的选项在longopts数组中的下标。longindex可以为NULL,表明不需要返回这个值。

(3)getopt_long_only函数

getopt_long_only类似于getopt_long,但是它把'-'开头的选项当作长选项来处理,一般情况下,这时结构体数组变量longopts中也会包含我们想分析的短选项。如果该选项与长选项不匹配,而与短选项匹配,则可以作为短选项解析。

在短选项找到的时候,getopt_long和getopt_long_only的表现和getopt一样。如果长选项找到了,如果flag为 NULL,返回val,否则返回0。错误情况的处理和getopt一样,只是返回'?'时还可能是别的情况引起的:选项含糊不明确或者无关参数。

4、例子应用

我们拿Linux手册的一个例子来说事。

#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;while(1) 
{
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"add", 1, 0, 0},
{"append", 0, 0, 0},
{"delete", 1, 0, 0},
{"verbose", 0, 0, 0},
{"create", 1, 0, ’c’},
{"file", 1, 0, 0},
{0, 0, 0, 0}
};
c = getopt_long (argc, argv, "abc:d:012",long_options, &option_index);
if (c == -1)  // 如果全部分析完,返回-1break;
switch (c) {
case 0:  // 如果是长选项,则返回0,打印长选项名称和参数
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("/n");
break;
case ’0’:  // 以下是短选项的返回结果
case ’1’:
case ’2’:
if (digit_optind != 0 && digit_optind != this_option_optind)printf ("digits occur in two different argv-elements./n");
digit_optind = this_option_optind;
printf ("option %c/n", c);
break;
case ’a’:
printf ("option a/n");
break;
case ’b’:
printf ("option b/n");
break;
case ’c’:
printf ("option c with value ‘%s’/n", optarg);
break;
case ’d’:
printf ("option d with value ‘%s’/n", optarg);
break;
case ’?’:
break;
default:
printf ("?? getopt returned character code 0%o ??/n", c);
}
}
if (optind < argc) {  // 如果满足该条件,则存在无选项参数,打印出无选项参数
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("/n");
}exit (0);
}

我们用digit_optind和this_option_optind来跟踪选项012是否在一起,比如选项 -012 和-0 -1 -2 的optind情况是不一样的,前者返回0、1、2时optind相同,而后者optind的值依次大1。

Comments

这篇关于getopt、getopt_long和getopt_long_only的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/895936

相关文章

long long,_int64使用小结

前言:   在16位环境下,int/unsigned int 占16位,long/unsigned long占32位   在32位环境下,int占32位,unsigned int占16位,long/unsigned long占32位 何时需要使用:   long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647,而unsigned范围是[0,2^32),

《长得太长也是错?——后端 Long 型 ID 精度丢失的“奇妙”修复之旅》

引言 在前后端分离的时代,我们的生活充满了无数的机遇与挑战——包括那些突然冒出来的让人抓狂的 Bug。今天我们要聊的,就是一个让无数开发者哭笑不得的经典问题:后端 Long 类型 ID 过长导致前端精度丢失。说到这个问题,那可真是“万恶之源”啊,谁让 JavaScript 只能安全地处理 Number.MAX_SAFE_INTEGER(也就是 9007199254740991)以内的数值呢?

踩坑记录(Long[]ids)

主要针对Long[] ids 的判空问题 问题代码 public void delYnjC(Long[] ids) {if (CollectionUtils.isEmpty(Collections.singleton(ids))) {throw new NullPointerException("参数不能为空");}naturalYnjCMapper.delYnjC(ids);} 修正

CodeForces 407B Long Path

题意: 有n+1个格子  起点在1  每个格子有个前进1的门  前n个格子有个返回的门(返回前面某个格子)  奇数次走进一个格子就去走返回门  偶数次走前进门  问  走到n+1要走过几道门 思路: 一看就是DP to[i]表示第i个格子的返回门 go[i]表示离开第i个格子需要的步数 sum[i]表示离开前i个格子需要的步数 明显  go[i]=sum[i-1]-sum[to

Command line is too long. Shorten command line for DisplayApplication (1) or

微服务项目启动类起不来,如下 解决办法:IEDA开发环境下 找到你的项目下面的.idea\workspace.xml 添加一个property : <property name="dynamic.classpath" value="true" /> 帮同事看的问题,自己测试没问题就关闭了。图片借用网上的。 参考:参考

[C++] 将LONG类型的color值转换为RGB值

转换原理: The calculation is: (65536 * Blue) + (256 * Green) + (Red) 'Convert RGB to LONG: LONG = B * 65536 + G * 256 + R       'Convert LONG to RGB:  B = LONG \ 65536  G = (LONG - B * 65536) \ 256  R =

Command line is too long. Shorten command line for IhswfldWebApplication or also for Spring Boot ..

工作中,使用idea启动服务时报错如下图: 解决方法:打开启动配置页,选择 JAR mainfest, 点击 Apply, 点击 OK. 再次启动项目

论文笔记:LONG-FORM FACTUALITY IN LARGE LANGUAGE MODELS

Abstract 当前存在问题,大模型在生成关于开放主题的事实寻求问题的时候经常存在事实性错误。 LongFact 创建了LongFact用于对各种主题的长形式事实性问题进行基准测试。LongFact是一个prompt集包含38个领域的数千条提示词,使用GPT-4生成。 Search-Augmented Factuality Evaluator(SAFE) SAFE利用大模型将一个相应拆

dt中ID转化为long[]

1、dt中ID转化为long[]             long[] ids = new long[dataids.Rows.Count];             int index = 0;             foreach (DataRow dr in dataids.Rows)             {                 if (in