选项解析函数getopt()和getopt_long()

系统执行一个C语言程序总是从main()函数开始。在标准的C程序中,main()函数有两个参数,它们代表程序的命令行参数,原型如下:

   int main(int argc, char *argv[]);

argc是命令行参数的个数,argv是C字符串的数组,它的元素是单个的命令行参数字符串。执行程序名是第一个字符串,而所有参数之后总是一个NULL指针:argv[argc]总是NULL。
比如,命令“cat abc def”中,argc等于3,argv的有效元素有3个,分别是cat、abc、def。

POSIX建议程序的选项(options)按照下面的规则定义:

  • 选项用连字符“-”开始,并且只含有字符和数字。
  • 多选项可以合并写出:-abc等于-a –b –c。
  • 某些选项可以带一个参数(argument)。如:-o file。 带参数选项一般位于其它无参数选项前面。
  • 两个连字符“–”之后所有的选项都视为普通命令行参数。
  • 长选项用“–”开始,且不带参数。由于长选项没有参数,可以用“–name=value”的形式给出参数。

    如果你的程序参数少,可以直接从argv数组中获取。如果选项较多而复杂,分析起来很麻烦,这时可以使用getopt()和getopt_long()函数分析典型的命令行参数。使用这两个函数,必须包含unistd.h文件

getopt

getopt函数的原型如下:

   int getopt(int argc, char **argv, const char *options);

该函数的作用是分析参数argc和argv提供的选项。

几个外部变量

  • extern char *optarg; extern int optind, opterr, optopt;
  • optarg:若短选项后有参数,则optarg指向该参数
  • optind:扫描选项时,标识下一个选项的索引;扫描结束后,标识第一个非选项参数索引
  • opterr:出现不可识别的选项时,getopt将打印错误信息。将opterr设为0,可不打印错误信息。
  • optopt:存放不可识别的选项至optopt

这里的argcargv往往直接来源于main函数的参数。options给出需要分析的有效选项的列表,是以字符串的形式给出。

其中需要有参数的选项后跟一个“:”,如果参数是可选的,则后面有两个冒号“::”

getopt函数返回命令行中的一个选项字符,如果有参数,其参数存储在预定义变量char* optarg指定的内存中。

如果参数列表argv中包含普通的不是选项的参数,或者包含不在options中指定的选项,则getopt函数返回“?”字符,并且把相应的字符存储到变量optopt中。如果这时外部变量opterr不等于0,则getopt函数会打印错误信息。

当所有选项都给出后,函数返回-1,表示没有选项了。

通常getopt函数应该在一个循环中调用每次给出一个选项,直到返回-1。循环中分析得到的选项,往往用switch语句。循环结束后,往往还需要一个循环分析不是选项的命令行参数,首个不是选项的命令行参数的位置存储在变量optind中。下面举例如下:

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

   int
   main(int argc,char *argv[])
   {
      int aflag = 0;
      int bflag = 0;
      char *cvalue = NULL;
      int index;
      int c;

      opterr = 0;
      while((c=getopt(argc,argv,"abc:"))!=-1)
      {
         switch(c)
          {
          case 'a':
             aflag=1;
             break;
          case 'b':
             bflag=1;
             break;
          case 'c':
             cvalue=optarg;
             break;
          case '?':
             if(isprint(optopt))
                fprintf(stderr,"Unknown option '-%c'.\n",optopt);
             else
                fprintf(stderr,
                     "Unknown option charactor '\\x%x'.\n",
                     optopt);
             return 1;
          default:
             abort();
          }
      }
      printf("aflag = %d, bflag = %d,
                cvalue = %s\n",aflag,bflag,cvalue);
      for(index=optind;index<argc;index++)
         printf("Non-option argument %s\n",argv[index]);
      return 0;
  }

getopt_long

getopt_long
函数getopt_long除了能够处理普通选项,还能处理长选项。它的原型如下:

   int getopt_long(int argc, char **argv, const char *shortopts,
               struct option *longopts, int *indexptr);

它从argv中解析出选项。参数shortopts描述了需要解析的短选项,它的表示方法同getopt函数一样,参数longopts描述了接受的长选项。当getopts_long函数遇到一个短选项,它的行为和getopts函数一样:返回选项字符,把参数存储到optarg中。
结构option是预先定义的结构,用来表明函数getopts_long能够接受的长选项和对该长选项的处理方法。它包含如下4个成员:
const char *name:字符串,选项的名称。
int has_arg:表示该长选项是否包含参数。它可取值no_argument、required_argument、optional_argument,分别表示无参数、有参数、可选参数。
int *flag
int val : 这两个参数合起来表示处理该选项的方法。如果指针flag为NULL,val就表示一个代表该选项的唯一整数。如果函数getopts_long的返回值是该整数,表明找到了该选项。如果希望某个长选项和另外一个短选项具有相同的意义,可以定义该长选项的val值和短选项字符相同。如果指针指向一个分配好的整数,那么当找到该选项时,这个整数就用来存储val给出的值,用来表明找到了该选项。这种情况下,函数getopts_long返回0。
函数getopts_long的参数longopts是一个指向结构option的指针,给出一组option类型的长选项,用{0,0,0,0}表示参数结束。
函数getopts_long的最后一个参数indexptr是一个整数指针,它在函数getopts_long正确调用后被设置成当前参数在longopts中的位置。比如,你可以用longopts[*indexptr].name引用找到参数的名称。
如果长选项有参数,它将被存储到optarg变量中。如果没有参数,变量optarg等于NULL。
当函数getopts_long不再能找出选项时,它返回-1。它仍然用optind表明剩下的参数在argv中的位置。
下面举例说明。

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

   /* Flag set by '--verbose'. */
   static int verbose_flag;

   int
   main(int argc,char **argv)
   {
      int c;
      while(1)
      {
         static struct option long_options[]=
         {
            {"verbose",no_argument,&verbose_flag,1},
            {"brief",no_argument,&verbose_flag,0},
            {"add",required_argument,0,0},
            {"append",no_argument,0,0},
            {"delete",no_argument,0,0},
            {"create",no_argument,0,0},
            {"file",no_argument,0,0},
            {0,0,0,0}
         };

         int option_index = 0;
         c = getopt_long(argc,argv,"abc:d:",
                             long_options,&option_index);
         if(c==-1)
            break;

         switch(c)
         {
         case 0:
            if(long_options[option_index].flag!=NULL)
               break;
            printf("option %s",long_options[option_index].name);
            if(optarg)
               printf(" with arg %s",optarg);
            printf("\n");
            break;
         case 'a':
            puts("option -a\n");
            break;
         case 'b':
            puts("option -b\n");
            break;
         case 'c':
            printf("option -c with value '%s'\n",optarg);
            break;
         case 'd':
            printf("option -d with value '%s'\n",optarg);
            break;
         case '?':
            break;
         default:
            abort();
         }
      }

      if(verbose_flag)
         puts("verbose flag is set");
      if(optind<argc)
      {
         printf("non-option argv elements: ");
         while(optind<argc)
            printf("%s ",argv[optind++]);
         putchar('\n');
      }

      exit(0);
   }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值