Sunday, January 2, 2011

getopt_long()函數 --- 參數解析

get_opt()函數:
函數原型::
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
用法見右邊欄
1.參數說明:
optstring:選項字母組成的字串。如果該字串裡的任一字符後面有冒號,那麼這個選項就要求有選項參數。
char *optarg:當前選項參數字串(如果有)。
int optind:argv的當前索引值。當getopt()在while循環中使用時,循環結束後,剩下的字串視為操作數,在argv[optind]至argv[argc-1]中可以找到。
int opterr:這個變量非零時,getopt()函數為“無效選項”和“缺少參數選項,並輸出其錯誤信息。

int optopt:當發現無效選項字符之時,getopt()函數或返回'?'字符,或返回':'字符,並且optopt包含了所發現的無效選項字符。

2.更改getopt()函數的出錯信息輸出與否:
a. 在呼叫getopt()之前,將opterr設置為0,這樣就可以在getopt()函數發現錯誤的時候強制它不輸出任何消息。
b. 在optstring參數的第一個字符前加冒號,那麼getopt()函數就會保持沉默,並根據錯誤情況返回不同字符,如下:
“無效選項” —— getopt()返回'?',並且optopt包含了無效選項字符(這是正常的行為)。
“缺少選項參數” —— getopt()返回':',如果optstring的第一個字符不是冒號,那麼getopt()返回'?',這會使得這種情況不能與無效選項的情況區分開。

/*get_opt function test
huasion 20090920
*/
#include <stdio.h>
#include <unistd.h>

int main( int argc, char ** argv)
{
 
int i,oc;
int res = 0;
char *b_opt_arg;
char ec;
/*commen print argument*/
printf("*********************************************** *******\n");
printf("usage: get_opt \n ");
printf("argc=%d\n", argc);
for(i=0;i<argc;i++)
   printf("argv[%d]:%s\n", i, argv[i]);
printf("*********************************************** *******\n");
/*over*/
while((oc=getopt(argc,argv,":ab:cd:")) != -1){
   switch(oc){
   case 'a':
    printf("case a optind = %d.\n",optind);
    break;
   case 'b':
printf("case b have a value,optarg = %s ,optind = %d.\n",optarg,optind);
    break;
   case 'c':
    printf("case c optind = %d.\n",optind);
    break;
   case 'd':
printf("case d have a value optarg = %s ,optind = %d.\n",optarg,optind);
    break;
   case '?':
    ec = (char)optopt;
  
printf("option \'%c\' invalid! optind = %d, .\n",ec,optarg,optind);
  
   case ':':
printf("getopt() return value : , you need a option value \n");
  
   default:
    break;
   }

}
printf("it is over, res = %d \n",res);

}
**********************************分割線************** ********************
getopt_long()函數
函數原型:
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
前三個參數的含義和getopt()函數一致,其餘意義如下:
longopts: 長選項表地址 ,定義為:
   struct option{
            const char *name;
            int has_arg;
            int *flag;
            int val;
     };

longindex: 如果沒有設置為NULL,那麼它就指向一個變量,這個變量會被賦值為尋找到的長選項在longopts中的索引值,這可以用於錯誤診斷。
const char *name: 這是選項名,前面沒有短橫線。譬如"help"、"verbose"之類。
int has_arg:描述了選項是否有選項參數。如果有,是哪種類型的參數,此時,它的值一定是下表中的一個。符號常量 數值 含義
no_argument 0 選項沒有參數
required_argument 1 選項需要參數
optional_argument 2 選項參數可選
int *flag
如果這個指針為NULL,那麼getopt_long()返回該結構val字段中的數值。如果該指針不為NULL,getopt_long()會使得它所指向的變量中填入val字段中的數值,並且getopt_long()返回0。如果flag不是NULL,但未發現長選項,那麼它所指向的變量的數值不變。
int val
這個值是發現了長選項時的返回值,或者flag不是NULL時載入*flag中的值。典型情況下,若flag不是NULL,那麼val是個真/假值,譬如1 或0;另一方面,如果flag是NULL,那麼val通常是字符常量,若長選項與短選項一致,那麼該字符常量應該與optstring中出現的這個選項的參數相同。
每個長選項在長選項表中都有一個單獨條目,該條目裡需要填入正確的數值。數組中最後的元素的值應該全是0。數組不需要排序,getopt_long()會進行線性搜索。但是,根據長名字來排序會使程序員讀起來更容易。


/*get_opt function test
huasion 20090920
*/
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>

int main( int argc, char ** argv)
{
 
int i,oc;
int res = 0;
char *b_opt_arg;
char ec;
int do_name, do_gf_name;
char *l_opt_arg;
struct option longopts[] = {
   { "name", no_argument, &do_name, 1 },
   { "gf_name", no_argument, &do_gf_name, 1 },
   { "love", required_argument, NULL, 'l' },
   { 0, 0, 0, 0},
};

/*commen print argument*/
printf("*********************************************** *******\n");
printf("usage: get_opt \n ");
printf("argc=%d\n", argc);
for(i=0;i<argc;i++)
   printf("argv[%d]:%s\n", i, argv[i]);
printf("*********************************************** *******\n");
/*over*/
while((oc = getopt_long(argc, argv, ":l:", longopts, NULL)) != -1){
switch (oc){
case 'l':
   l_opt_arg = optarg;
   printf("Our love is %s!\n", l_opt_arg);
break;
case 0:
printf("getopt_long()設置變量: do_name = %d\n", do_name);
printf("getopt_long()設置變量: do_gf_name = %d\n", do_gf_name);
break;
}
}

printf("it is over, res = %d \n",res);

}

#include <stdio.h>
#include <getopt.h>
int do_name, do_gf_name;
char *l_opt_arg;
struct option longopts[] = {
{ "name", no_argument, NULL, 'n' },
{ "gf_name", no_argument, NULL, 'g' },
{ "love", required_argument, NULL, 'l' },
{ 0, 0, 0, 0},
};
int main(int argc, char *argv[])
{
int c;
while((c = getopt_long(argc, argv, ":ngl:", longopts, NULL)) != -1){
//其中,選項以及其有無參數由":ngl:"決定而不是在option longopts[] 表中的值決定
switch (c){
case 'n':
printf("My name is LYR.\n");
break;
case 'g':
printf("Her name is BX.\n");
break;
case 'l':
l_opt_arg = optarg;
printf("Our love is %s!\n", l_opt_arg);
break;
}
}
return 0;
}


三、getopt_long函數
getopt_long用來處理長選項,使用man 3 getopt_long,得到其聲明如下:
#include <getopt.h>
int getopt_long(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char * const argv[], const char *optstring,
const struct option *longopts, int *longindex);
前三個參數與getopt相同,下一個參數是指向數組的指針,這個數組是option結構數組,option結構稱為長選項表,其聲明如下:
struct option
{
     const char *name;
     int has_arg;
     int *flag;
     int  val;
};
結構中的元素解釋如下:
const char *name:選項名,前面沒有短橫線
int has_arg:描述長選項是否有參數,其值見下表
符號常量           數值             含義
no_argument         0           選項沒有參數
required_argument   1           選項需要參數
optional_argument   2         選項的參數是可選的
int *flag:
如果該指針為NULL,那麼getopt_long返回val字段的值;
如果該指針不為NULL,那麼會使得它所指向的結構填入val字段的值,同時getopt_long返回0
int val:
如果flag是NULL,那麼val通常是個字符常量,如果短選項和長選項一致,那麼該字符就應該與optstring中出現的這個選項的參數相同;
/*
* FileName:      
* Author:          heguangwu   Version: v1.0   Date: 2008-11-22
* Description:     example of getopt_long
* Version:       
* Function List: 
*                  1.
* History:       
*      <author>    <time>     <version >    <desc>
*/

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>

char *para = ":ab:cf:v";
int do_all = 0;
int do_help = 0;
int do_version = 0;
char *file = NULL;

struct option longopt[] =
{
     {"all", no_argument, &do_all, 1},
     {"file", required_argument, NULL, 'f'},
     {"help", no_argument, &do_help, 1},
     {"version", no_argument, &do_version, 1},
     {"bob", required_argument, NULL, 'b'},
     {0, 0, 0, 0},
};

int main(int argc, char *argv[])
{
    int oc = -1;
    char *b_input = NULL;

    while((oc = getopt_long(argc, argv, para, longopt, NULL)) != -1)
    {
         switch(oc)
         {
         case 'a':
               printf("input para is a\n");
              break;
         case 'b':
              b_input = optarg;
              printf("input para is b,and optarg is %s\n", b_input);
             break;
        case 'c':
             printf("input para is c\n");
        break;
        case 'v':
            printf("input para is v\n");
            break;
        case 'f':
            printf("input para is f\n");
            file = "hello world";
          break;
        case 0:
           break;
        case ':':
             printf("option %c requires an argument\n",optopt);
             break;
       case '?':
         default:
            printf("option %c is invalid:ignored\n",optopt);
            break;
         }
   }

     printf("do_all is %d\n",do_all);
     printf("do_help is %d\n",do_help);
     printf("do_version is %d\n",do_version);
   printf("do_file is %s\n",file);
     printf("bob is %s\n", b_input);

     return 0;
}
執行的結果:只顯示關鍵結果
[root@heguangwu projects]# ./opt_ex2 -a
input para is a

[root@heguangwu projects]# ./opt_ex2 --all
do_all is 1

[root@heguangwu projects]# ./opt_ex2 -f h
input para is f
do_file is hello world

[root@heguangwu projects]# ./opt_ex2 --bob aa
input para is b,and optarg is aa
bob is aa

[root@heguangwu projects]# ./opt_ex2 -b aa
input para is b,and optarg is aa

1 comment: