getopt_long 與 optind

剛開始接觸 一些處理命令行參數的操作,開始不太明白,用例子測試了一下,感覺比以前明瞭多了。

命令行參數有長參數如version, 還有短參數 如 v, 那麼用這兩個都可以。程序處理的時候,會首先把長參數轉換成對應的短參數,如會把version轉成v, 再進行 v 對應的操作就可以了。

命令行參數的選項,有的需要參數,有的不需要參數,或者有的參數是可選的,那麼怎麼區分呢?

首先,對這些選項,如何組織起來? 是以字符串的形式組織起來了。如我有一個程序,有兩個選項,-a, -b, 我輸入的時候是  ./a.out  -a -b, 那麼中間會處理成這種 ab這種字符串的形式,這個字符串就是所有的命令行的輸入選項。區別是否有參數就在於此。如果某個選項必須有參數,則這一選項後有一個參數,如果參數是可選的,則其後面有兩個冒號。如

-a  是沒有參數的, -b 後面必須有參數, -c 後面是否有參數是可選的。則短的命令行選項是:   ab:c::

下面我們通過一個簡單的例子看一下。

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
char *l_opt_arg;
char* const short_options = "myl:";
//char* const short_options = "nbl:";
struct option long_options[] = {
	{ "name",     0,   NULL,    'm'     }, //長選項對應的短選項參數, 第二個0表示選項後面無參數, 1爲有參數,2爲可選
	{ "yourname",  0,   NULL,    'y'     },
	{ "love",     1,   NULL,    'l'     },
	{      0,     0,     0,     0},
};
int main(int argc, char *argv[])
{
	int c, i;
	printf("before:\n");
	for (i=1; i<argc; i++)
		printf("arg:%d : %s\n", i, argv[i]);
	printf("\n");
	while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1)
	{
	//	printf("optind:%d, %c \n", optind, c);
		switch (c)
		{
			case 'm':
				printf("My name is A.\n");
				break;
			case 'y':
				printf("His name is B.\n");
				break;
			case 'l':
				l_opt_arg = optarg;
				printf("Our love is %s!\n", l_opt_arg);
				break;
		}
	}

	printf("optind:%d\n", optind);

	printf("after:\n");
	for (i=1; i<argc; i++)
		printf("arg:%d : %s\n", i, argv[i]);
	return 0;
}

注意,此程序可接收的的選項有三個, 一個是m ,不帶參數, y 不帶參數, l  要求有參數。

那如果-m 不帶參數,如果我寫了參數,會怎麼樣呢?下面看測試

在調用 getopt_long 以後, optind 的值隨之變化 。在while循環後,我們再把開始的命令行參數打印出來,看一下有什麼不同。

把上面的代碼命名爲:  getopt_long.c

編譯,可執行文件爲 a.out

$ gcc  getopt_long.c    


$ ./a.out -m -y
before:
arg:1 : -m
arg:2 : -y

My name is A.
His name is B.
optind:3
after:
arg:1 : -m
arg:2 : -y

$ ./a.out -m -y -l banana
before:
arg:1 : -m
arg:2 : -y
arg:3 : -l
arg:4 : banana


My name is A.
His name is B.
Our love is banana!
optind:5
after:
arg:1 : -m
arg:2 : -y
arg:3 : -l
arg:4 : banana

$./a.out -m lisi -y zhangsan  -l banana  aaa
before:
arg:1 : -m
arg:2 : lisi
arg:3 : -y
arg:4 : zhangsan
arg:5 : -l
arg:6 : banana
arg:7 : aaa


My name is A.
His name is B.
Our love is banana!
optind:5
after:
arg:1 : -m
arg:2 : -y
arg:3 : -l
arg:4 : banana
arg:5 : lisi
arg:6 : zhangsan
arg:7 : aaa


注意 argv 裏面值的順序已經和原來不一樣了,對命令行的參數重新組織了一下順序,也就是不認識的命令行參數,都放在了argv的最後,其中 optind 指向了這些沒有被解釋的參數的第一個。

optind有作用吧!如果你想輸出哪些命令行參數沒有被識別,可以打印出來 for (i=optind; i<argc; i++) printf("%s\n", argv[i]);  即可


附:如果是長參數,則使用 --, 如 --help, 因爲 -help時,(選項不需要參數的情況) 會把它當成 四個選項, -h -e -l -p. 所以使用長參數時,要用兩個 橫線 --


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章