C语言之用getopt解析命令行参数
开发环境为WIN10操作系统下用VMWARE17虚拟的UBUNTU LINUX 18.04LTS 命令行参数的解析有两种方法,其中一种方法是用getopt或getoptlong函数,另一种方法是argp系列函数。
短命令参数处理函数getopt
# include <unistd.h>
int getopt ( int argc, char * const argv[ ] , const char * optstring) ;
extern char * optarg;
extern int optind, opterr, optopt;
包含头文件 unistd.h ,头文件中有四个外部定义的变量: opterr 如果此变量为非零值则输出错误信息,如置零则不输出错误信息 optopt 保存不在处理范围内的、未知的参数字符 optarg 字符指针型,保存参数的值 optind 下一个argv的索引,默认为1 getopt函数的第一个参数和第二个参数直接来自main函数 getopt函数的第三个参数optstring为参数名的首字母,可以选择加冒号,如果参数后还需要再加一个参数,则必需加冒号,否则不必! 如果optstring为"abc:d",则说明, ** 第一个命令行参数为-a,不必附加参数; ** 第二个命令行参数为-b,不必附加参数; ** 第三个命令行参数为-c,必须附加参数,格式为: -c foo ; ** 第四个命令行参数为-d不必附加参数。
简单示例,代码如下:
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <ctype.h>
int
main ( int argc, char * argv[ ] )
{
int hflag = 0 ;
int vflag = 0 ;
char * svalue = NULL ;
int index;
int c;
opterr = 0 ;
while ( ( c = getopt ( argc, argv, "hvs:" ) ) != - 1 )
switch ( c)
{
case 'h' : hflag = 1 ; break ;
case 'v' : vflag = 1 ; break ;
case 's' : svalue = optarg; break ;
case '?' :
if ( optopt == 's' )
fprintf ( stderr , "Option -%c requires an argument.\n" , optopt) ;
else if ( isprint ( optopt) )
fprintf ( stderr , "Unknown option `-%c'.\n" , optopt) ;
else
fprintf ( stderr , "Unknown option character `\\x%x'.\n" , optopt) ;
return 1 ;
default :
abort ( ) ;
}
printf ( "hflag = %d, vflag = %d, svalue = %s\n" , hflag, vflag, svalue) ;
for ( index = optind; index < argc; index++ )
printf ( "Non-option argument %s\n" , argv[ index] ) ;
return 0 ;
}
编译运行,测试输出如下:
songvm@ubuntu:~/works/xdn/boo$ gcc opt.c -o opt
songvm@ubuntu:~/works/xdn/boo$ ./opt
hflag = 0 , vflag = 0 , svalue = ( null)
以上为无命令行参数情况,标记和默认值均为0或NULL
songvm@ubuntu:~/works/xdn/boo$ ./opt -h
hflag = 1 , vflag = 0 , svalue = ( null)
songvm@ubuntu:~/works/xdn/boo$ ./opt -v
hflag = 0 , vflag = 1 , svalue = ( null)
songvm@ubuntu:~/works/xdn/boo$ ./opt -h -v
hflag = 1 , vflag = 1 , svalue = ( null)
以上加命令行参数-h、-v或同时相加的情况,标记置为1!!!
songvm@ubuntu:~/works/xdn/boo$ ./opt -s
Option -s requires an argument.
songvm@ubuntu:~/works/xdn/boo$ ./opt -sfoo
hflag = 0 , vflag = 0 , svalue = foo
songvm@ubuntu:~/works/xdn/boo$ ./opt -s bar
hflag = 0 , vflag = 0 , svalue = bar
以上加命令行参数-s情况,svalue的值因为后续参数的变化而改变!!!
songvm@ubuntu:~/works/xdn/boo$ ./opt -a -b -c
Unknown option `-a'.
songvm@ubuntu:~/works/xdn/boo$ ./opt a b c
hflag = 0 , vflag = 0 , svalue = ( null)
Non-option argument a
Non-option argument b
Non-option argument c
以上加的命令行参数均不在我们的代码处理范围内,故提示未知命令行参数或非可选命令行参数!!!
长命令行参数处理函数getopt_long
# include <getopt.h>
int getopt_long ( int argc, char * const argv[ ] ,
const char * optstring,
const struct option * longopts, int * longindex) ;
包含在getopt.h头文件之内, #include <getopt.h> 第三个参数optstring格式与getopt函数中的用法一样!!! 第四个参数option结构体,struct option包含四个成员 ** 第1个成员为长命令行参数字符串; ** 第2个成员为是否需要后续参数开关,no_argument表示不需要后续参数,required_argument表示需要后续参数; ** 第3个成员为开关标记的指针,如果命令行参数是一个标记开关,此成员值为保存标记开关的变量指针; ** 第4个成员为长命令行参数字符串对应的短命令行参数字符,如果命令行参数是一个标记开关,设置值为1,以便后续处理。 第五个参数longindex,保存长命令行参数的索引值的变量指针!!! 详细见下面示例代码中的说明。
简单示例,代码如下:
# include <stdio.h>
# include <stdlib.h>
# include <getopt.h>
int
main ( int argc, char * * argv)
{
int debug_flag = 0 ;
struct option lopts[ ] =
{
{ "debug" , no_argument, & debug_flag, 1 } ,
{ "help" , no_argument, 0 , 'h' } ,
{ "version" , no_argument, 0 , 'v' } ,
{ "script" , required_argument, 0 , 's' } ,
{ 0 , 0 , 0 , 0 }
} ;
int c = 1 ;
while ( c != - 1 )
{
int optidx = 0 ;
c = getopt_long ( argc, argv, "dhvs:" , lopts, & optidx) ;
if ( c == - 1 )
break ;
switch ( c)
{
case 0 :
if ( lopts[ optidx] . flag != 0 ) break ;
printf ( "option %s" , lopts[ optidx] . name) ;
if ( optarg) printf ( " with arg %s" , optarg) ;
printf ( "\n" ) ;
break ;
case 'd' :
puts ( "option -d\n" ) ;
debug_flag = 1 ;
break ;
case 'h' :
puts ( "option -h\n" ) ;
printf ( "Some help message here!\n" ) ;
break ;
case 'v' :
puts ( "option -v\n" ) ;
printf ( "Some version message here!\n" ) ;
break ;
case 's' :
printf ( "option -s with value `%s'\n" , optarg) ;
break ;
case '?' :
break ;
default :
abort ( ) ;
}
}
if ( debug_flag)
printf ( "debug flag is set!\n" ) ;
if ( optind < argc)
{
printf ( "non-option ARGV-elements: " ) ;
while ( optind < argc)
printf ( "%s " , argv[ optind++ ] ) ;
putchar ( '\n' ) ;
}
return 0 ;
}
编译运行,测试结果如下:
songvm@ubuntu:~/works/xdn/boo$ gcc -g optl.c -o optl
songvm@ubuntu:~/works/xdn/boo$ ./optl --version
option -v
Some version message here!
songvm@ubuntu:~/works/xdn/boo$ ./optl --help
option -h
Some help message here!
以上显示长命令行参数–version与-v结果相同,–help与-h结果相同!
songvm@ubuntu:~/works/xdn/boo$ ./optl --debug
debug flag is set!
songvm@ubuntu:~/works/xdn/boo$ ./optl -d
option -d
debug flag is set!
songvm@ubuntu:~/works/xdn/boo$ ./optl --script
./optl: option '--script' requires an argument
songvm@ubuntu:~/works/xdn/boo$ ./optl --script foo.sh
option -s with value ` foo.sh'
songvm@ubuntu:~/works/xdn/boo$ ./optl -s
./optl: option requires an argument -- ' s'
songvm@ubuntu:~/works/xdn/boo$ ./optl -sfoo.sh
option -s with value ` foo.sh'
以上显示长命令行参数–script与-s结果相同!
songvm@ubuntu:~/works/xdn/boo$ ./optl --append --file bar.txt
./optl: unrecognized option '--append'
./optl: unrecognized option '--file'
non-option ARGV-elements: bar.txt
以上加的命令行参数均不在我们的代码处理范围内,故提示信息!
有很多和系统相关的东西,不同操作系统会出现不同的结果,编码时一定要注意!!!