1、main函数参数形式
int main(int argc , char *argv[] , char *env[]);
//第一个参数argc代表命令行的参数个数
//第二个参数依次指向各个参数,如"ls -l",argv[0]指向"ls",argv[1]指向"-l",argv[2]为NULL
//第三个参数为当前进程环境变量列表
2、命令行参数识别
在命令行输入命令时,选项的位置是随意的,如ls -l -a 与ls -a -l的效果是一样的
2.1、getopt(int argc , char *argv[] , char *optstring) 引入头文件"unistd.h"
第一个参数、第二个参数同main函数的前两个参数,第三个参数optstring定义了选项和参数的形式
(1)单个字符表示该选项没有参数
(2)单个字符后面接单个冒号,表示该选项后面必定有参数,且以空格分隔选项和参数
(3)单个字符后面接双冒号,表示该选项后可以有参数也可以没有参数;若有参数,参数必须紧跟在选项后
如:
ab:c::
选项a没有参数;选项b有一个参数且用空格分隔;选项c可以有参数也可以没有参数,若有参数,参数必须紧跟在选项后
此外还有4个与getopt相关的全局变量
int optopt:存储未满足optstring规定的选项
char *optarg:指向当前选项的参数指针
int optind:确定选项和对应参数后,指向下一个argv参数
int opterr:若设为0,则getopt不想stderr输出错误信息
调用原理:
每次调用完getopt,都会返回对应的选项,使得optarg指向该选项对应的参数。若选项不满足optstring的规则,则返回‘?’,并将该选项存入optopt;若解析完毕则返回-1。
解析完毕后,getopt会重新排列argv中的参数,所有不符合要求的选项和参数被放到argv的最后(其中选项在前、参数在后),并使optind指向这些不符合要求的选项参数在argv中的起始下标。
1 #include <stdio.h>
2 #include <unistd.h>
3
4 int main(int argc ,char ** argv ,char ** env){
5 int res;
6 opterr=0; //不显示错误信息
7 while((res = getopt(argc , argv , "ab:c::")) != -1){
8 switch(res){
9 case 'a':
10 printf("option=a\toptarg=%s\toptopt=%c\toptind=%d\targv[optind]->%s\n",optarg,optopt,optind,argv[optind]);
11 break;
12 case 'b':
13 printf("option=b\toptarg=%s\toptopt=%c\toptind=%d\targv[optind]->%s\n",optarg,optopt,optind,argv[optind]);
14 break;
15 case 'c':
16 printf("option=c\toptarg=%s\toptopt=%c\toptind=%d\targv[optind]->%s\n",optarg,optopt,optind,argv[optind]);
17 break;
18 case '?':
19 printf("option=?\toptarg=%s\toptopt=%c\toptind=%d\targv[optind]->%s\n",optarg,optopt,optind,argv[optind]);
20 break;
21 }
22
23 }
24 printf("OVER\noptarg=%s\toptopt=%c\toptind=%d\targv[optind]->%s\n",optarg,optopt,optind,argv[optind]); //打印三个全局变量最终值
25 int i = 1 ;
26 printf("******************************************\n");
27 for(; i < argc ; i++){ //打印重新排列后的命令行参数
28 printf("%s\n",argv[i]);
29 }
30 }
sudo ./main -a -b bbb -c ccc -d ddd
option=a optarg=(null) optopt= optind=2 argv[optind]->-b
option=b optarg=bbb optopt= optind=4 argv[optind]->-c
option=c optarg=(null) optopt= optind=5 argv[optind]->ccc
option=? optarg=(null) optopt=d optind=7 argv[optind]->ddd
OVER
optarg=(null) optopt=d optind=6 argv[optind]->ccc
******************************************
-a
-b
bbb
-c
-d
ccc
ddd
2.2、getopt_long
它不仅能识别短选项(命令 -短选项),而且还支持长选项(命令 --长选项)。
int getopt_long(int argc , char **argv , char * shortOpt ,struct option * longOpt, int *index) 注意:struct option 要引入头文件”getopt.h“
前三个参数同getopt的参数,shortOpt定义的短选项及参数的形式。
第四个参数定义的是结构体option数组,
第五个参数记录长选项位于longOpt数组的下标,一般情况下设为NULL
struct option{
const char *name; //长选项名称
int has_arg; //0表示该选项没有参数,1表示必须有参数,2参数为可选
int *flag; //一般为NULL,则getopt_long返回val;否则,将val的值赋给flag所指向的整形变量,函数返回值为0
int val; //一般设为长选项对应的短选项,若flag为NULL,则val作为函数的返回值。否则将val赋给flag所指向的变量
};
若不想支持短选项,则让shortOpt为”“空字符串即可,但不能设为NULL。
1 #include <stdio.h>
2 #include <unistd.h>
3 #include <getopt.h>
4 int main(int argc , char **argv , char **env){
5 int res; //保存函数返回值
6 struct option longOption[4]={ //定义长选项数组
7 {"help",0,NULL,'h'},
8 {"version",0,NULL,'v'},
9 {"output",1,NULL,'o'},
10 {NULL,0,NULL,0}
11 };
12 opterr=0; //不输出错误信息
13 int index; //长选项位于longOption的下标
14 while( -1 != (res = getopt_long(argc , argv , "hvo:",longOption ,&index))){
15 switch(res){
16 case 'h':
17 printf("option=help\n");
18 break;
19 case 'v':
20 printf("option=version\n");
21 break;
22 case 'o':
23 printf("option=output,output path=%s\n",optarg);
24 break;
25 case '?':
26 printf("error\n");
27 break;
28 }
29 printf("index in longOption is %d\n",index);
30 }
31
32 return 0;
33 }
输出:
sudo ./main -h
option=help
index in longOption is -1218614280 //对于短选项,函数的第五个参数无效sudo ./main -o /home/out
option=output,output path=/home/out
index in longOption is -1219220488 sudo ./main --version
option=version
index in longOption is 1sudo ./main --output /home/out
option=output,output path=/home/out
index in longOption is 2