大家好,又见面了,我是全栈君。
命令行选项和參数控制 UNIX 程序,告知它们怎样动作。
当 gcc的程序启动代码调用我们的入口函数 main(int argc,char *argv[]) 时,已经对命令行进行了处理。argc 參数包括程序參数的个数,而 argv 包括指向这些參数的指针数组。
程序的參数能够分为三种:选项。选项的关联值,非选项參数。
比如:
getopt_test
.c是非选项參数。-o是选项,testopt是-o选项的关联值。
依据Linux的惯例。程序的选项应该以一个短横线开头。后面包括单个字母或数字。选项分为:带关联值的和不带关联值的以及可选的。不带关联值的选项能够在一个短横线后合并使用,比如 ls -al。
此外还有长选项。有两个短横线来指明。比方说 -o filename –output filename 给定输出文件名称等,以下整理了一些国外的资源用来学习。
getopt():短选项处理
int getopt( int argc, char *const argv[], const char *optstring );
单字符选项,假设一个字符后面紧跟以冒号(:),表示该字符有一个关联值作为下一个參数。两个冒号”::”代表这个选项的參数是可选的。
getopt的返回值是argv数组中的下一个选项參数。
由optind记录argv数组的下标,假设选项參数处理完成,函数返回-1;
假设遇到一个无法识别的选项,返回问号(?)。并保存在optopt中;
假设一个选项须要一个关联值。而程序运行时没有提供,返回一个问号(?),假设将optstring的第一个字符设为冒号(:),这样的情况下,函数会返回冒号而不是问号。
实际上。getopt在运行过程中会重排argv数组,将非选项參数移到数组的尾部。
<stdio.h>
<stdlib.h>
<unistd.h>
main(
int
argc,
char
**argv) {
int
opt = 0;
int
i = 0;
const
char
*optstring =
“:vV:h:”
;
//
for
(i = 0; i < argc; i++)
printf
(
“%d:%s\n”
, i, argv[i]);
//分别处理选项參数中的各个參数
while
((opt =
getopt
(argc, argv, optstring)) != -1){
switch
(opt){
case
‘v’
:
printf
(
“verbose\n”
);
break
;
case
‘V’
:
printf
(
“option %c:the Version is %s\n”
, opt, optarg);
break
;
case
‘h’
:
printf
(
“The option %c is %s…\n”
, opt, optarg);
break
;
case
‘?’
:
printf
(
“Unknown option %c\n”
,optopt);
break
;
//option index 终于会指向非选项參数
printf
(
“After getopt the optind = %d \n”
, optind);
//在运行完getopt之后又一次打印 argv数组
for
(i = 0; i < argc; i++)
printf
(
“%d:%s\n”
, i, argv[i]);
return
0;
getopt_long():长选项处理
getopt_long (
int argc, char *const *argv, const char *shortopts, const struct option *longopts, int *indexptr)
Decode options from the vector argv (whose length is argc). The argument shortopts describes the short options to accept, just as it does in getopt
. The argument longopts describes the long options to accept (see above).
When getopt_long
encounters a short option, it does the same thing that getopt
would do: it returns the character code for the option, and stores the options argument (if it has one) inoptarg
.
When getopt_long
encounters a long option, it takes actions based on the flag
and val
fields of the definition of that option.
If flag
is a null pointer, then getopt_long
returns the contents of val
to indicate which option it found. You should arrange distinct values in the val
field for options with different meanings, so you can decode these values after getopt_long
returns. If the long option is equivalent to a short option, you can use the short option’s character code in val
.
If flag
is not a null pointer, that means this option should just set a flag in the program. The flag is a variable of type int
that you define. Put the address of the flag in the flag
field. Put in the val
field the value you would like this option to store in the flag. In this case, getopt_long
returns 0
.
For any long option, getopt_long
tells you the index in the array longopts of the options definition, by storing it into *
indexptr. You can get the name of the option withlongopts[*
indexptr].name
. So you can distinguish among long options either by the values in their val
fields or by their indices. You can also distinguish in this way among long options that set flags.
When a long option has an argument, getopt_long
puts the argument value in the variable optarg
before returning. When the option has no argument, the value in optarg
is a null pointer. This is how you can tell whether an optional argument was supplied.
getopt_long
has no more options to handle, it returns -1
, and leaves in the variable optind
the index in argv of the next remaining argument.
struct option {
char *name; //长选项的名字
int has_arg; // 0/1。标志是否有选项
int *flag; //上面有具体说明,通常为NULL
int val;
};
This field is the name of the option. It is a string.
This field says whether the option takes an argument. It is an integer, and there are three legitimate values: no_argument, required_argument and optional_argument.
val –
These fields control how to report or act on the option when it occurs.
<stdio.h>
<stdlib.h>
<unistd.h>
<getopt.h>
main(
int
argc,
char
**argv){
const
char
*short_options =
“vhVo:”
;
const
struct
option long_options[] = {
“verbose”
,
optional_argument
, NULL,
‘v’
},
“help”
,
no_argument
, NULL,
‘h’
},
“version”
,
no_argument
, NULL,
‘V’
},
“output”
,
required_argument
, NULL,
‘o’
},
/* Required at end of array. */
for
(;;) {
int
c;
getopt_long
(argc, argv, short_options, long_options, NULL);
//
if
(c == -1) {
break
;
switch
(c) {
case
‘h’
:
printf
(
“The usage of this program…\n”
);
break
;
case
‘v’
:
printf
(
“set the program’s log verbose…\n”
);
break
;
case
‘V’
:
printf
(
“The version is 0.1 …\n”
);
break
;
case
‘o’
:
printf
(
“The output file is %s.\n”
,optarg);
break
;
case
‘?
‘ :
printf
(
“Invalid option , abort the program.”
);
exit
(-1);
default
:
// unexpected
abort
();
return
0;
应用场景分析
<stdio.h>
<stdlib.h>
<string.h>
<unistd.h>
<getopt.h>
<limits.h>
out_of_memory(
void
){
printf
(
“virtual memory exhausted\n”
);
abort
();
*xmalloc(
size_t
size){
void
*p =
malloc
(size ? size : 1);
if
(p == NULL) {
return
p;
*xmemdup0(
const
char
*p_,
size_t
length){
char
*p = xmalloc(length + 1);
memcpy
(p, p_, length);
‘\0’
;
return
p;
*xstrdup(
const
char
*s){
return
xmemdup0(s,
strlen
(s));
*long_options_to_short_options(
const
struct
option options[]){
char
short_options[UCHAR_MAX * 3 + 1];
char
*p = short_options;
for
(; options->
name
; options++) {
const
struct
option *o = options;
if
(o->
flag
== NULL && o->
val
> 0 && o->
val
<= UCHAR_MAX) {
val
;
if
(o->
has_arg
==
required_argument
) {
‘:’
;
else
if
(o->
has_arg
==
optional_argument
) {
‘:’
;
‘:’
;
‘\0’
;
//不能直接返回局部变量:字符数组,须要在堆上分配空间。然后返回相应的指针。
return
xstrdup(short_options);
void
int
argc,
char
*argv[])
enum
{
OPT_BOOTSTRAP_CA_CERT
= UCHAR_MAX + 1,
OPT_TIMESTAMP
,
DAEMON_OPTION_ENUMS
,
TABLE_OPTION_ENUMS
static
struct
option long_options[] = {
“verbose”
,
optional_argument
, NULL,
‘v’
},
“help”
,
no_argument
, NULL,
‘h’
},
“version”
,
no_argument
, NULL,
‘V’
},
“timestamp “
,
no_argument
, NULL,
OPT_TIMESTAMP
},
char
*short_options = long_options_to_short_options(long_options);
//当把把长短选项分离出来之后。就是上面的处理套路
//这里只打印出short options
printf
(
“%s\n”
,short_options);
free
(short_options);
main(
int
argc,
char
**argv) {
return
0;
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/116544.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...