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 1
sudo ./main --output /home/out
option=output,output path=/home/out
index in longOption is 2