getopt、getopt_long、getopt_long_only使用实例

        现在开始慢慢学习下上层开发,因为要为底层写些工具。首先从命令行参数的过滤获取开始,有两个函数用来操作命令行参数,以前我获取命令行都是自己用argv和argc做个循环获取的,其中各种转换和判断有点繁琐。现在学习下这两个函数怎么使用,可以方便后期的开发;

        在学习这两个函数之前先说明下:Linux的命令行选项有两种类型:短选项和长选项,前者以 '-' 作为前导符,后者以 '--' 作为前导符


getopt函数

        getopt()函数是专门用来处理命令行参数短选项的,不能处理长选项参数;

        头文件:#include

        函数原型:int getopt(int argc,char * const argv[ ],const char * optstring);

        参数分析:

        int argc 和 char *argv[]  这两个参数是直接从main函数中接过来的;

        char *optstring  是对应的选项字符串,比如:"ab:c::d::",这就表示在输入的命令行中要和这个字符串对应起来;(至于怎么对应后面会分析)

        该函数有个返回值,比如,这样调用该函数:./a.out  -a -b btest -cctest -d;那么返回值就会分别为: a、b、c、d、-1;最后没有参数了会返回-1;所以这样就可以做个while循环和-1比较,获取到所有参数;然后通过switch()就可以很好的操作参数;

        上面提到的都是正常的返回,如果调用函数时有个短选项在optstring没有与其对应的,则该函数会返回:?;或者./a.out -n 后面没有跟参数(后面什么都没有,如果跟了-s,则会把-s当作-n的参数),这时候也会返回?;


        现在来说明char *optstring  对应的命令行参数选项字符串(名称不知道怎么叫,大概意思就是对应命令行参数);

        还是上面那字符串"ab:c::d", a 表示有个短选项 -a,其后面不跟参数(一定不能有参数);   b: 表示有个短选项 -b,其后面跟一个参数(一定要跟参数);   c:: 表示有个短选项 -c,其后面可以跟参数也可以不跟,跟参数时不能有空格; 这是根据字符后面的冒号来区分的,一个冒号是一定跟一个参数;两个冒号是随意跟不跟参数;没有冒号则一定不能跟冒号;

        上面可以对应这个调用:./a.out   -a  -b  btest  -cctest  -d

         -a 后面没有带参数;-b 后面带了个参数btest,其中有空格隔开;-c 后面带了个参数ctest,其中没有用空格隔开;-d 后面没有带参数;


        再来讲下几个自带的全局变量;

        char *optstr;这个变量不需要自己定义,我这里写char *是为了说明该参数的类型;这个参数指向短选项后面的参数,如上面调用:执行-a时,optstr=NULL; 执行-b时,optstr=btest;执行-c时,optstr=ctest;执行-d时,optstr=NULL;(如果有短选项后面的是数值,这时候该数值也是做字符串;如果要用数值,则需要转换)

        int  optind;这个变量也不需要自己定义就可以直接使用,或者用extern int optind 也可以;这个变量指向下一个需要解析的参数位置,初始值为1;(./a.out为参数0)

        int  opterr;这个变量好像是打印错误信息的;默认是1,这时候如果getopt()函数出错时(可能没有对应的短选项)则会报:./a.out: invalid option -- 'x' 类似这样的错误。如果不想出现这个错误信息可以设置opterr为0就可以。

        int  optopt;这个变量是存放出错时的信息;比如,./a.out  -n  则optopt=n;./a.out -n yzh -x 则optopt = x;


 这里利用下面的实例代码的运行来说明上面的一些分析(opterr = 0的情况):

[yzh@yzh test]$ ./a.out  -nyzh -s -g1 -c2 -x
n:sg::c::h   (这个是getopt()函数中第三个参数:对应选项字符串参数)
opt:n, optarg:yzh, optind:2, opterr:0, optopt:, argv[optind]:-nyzh
opt:s, optarg:(null), optind:3, opterr:0, optopt:, argv[optind]:-s
opt:g, optarg:1, optind:4, opterr:0, optopt:, argv[optind]:-g1
opt:c, optarg:2, optind:5, opterr:0, optopt:, argv[optind]:-c2
opt:?, optarg:(null), optind:6, opterr:0, optopt:x, argv[optind]:-x


下面是opterr为默认值时的打印

opt:c, optarg:2, optind:5, opterr:1, optopt:, argv[optind]:-c2

./a.out: invalid option -- 'x'
opt:?, optarg:(null), optind:6, opterr:1, optopt:x, argv[optind]:-x

实例代码:(这里只是为了说明知识点)

 #include
 #include
 
 void opt_usage()
 {   
     printf("\nDescription:\n");
     printf("\tA student info\n\n");
     printf("Usage:\n");
     printf("\t-n, student name\n");
     printf("\t-s, student sex\n");
     printf("\t-g, student in grade\n");
     printf("\t-c, student in class\n");
     printf("\t-h, help\n");
 }
 
 int main(int argc, char **argv)
 {
 //  extern char *optarg;
 //  extern int  optind;
 //  extern int  opterr;
 //  extern int  optopt;
     
     int opt, sex, grade, class;
     char *name=NULL;
     sex=1;
     
     printf("n:sg::c::h\n");
     while ((opt = getopt(argc, argv, "n:sg::c::h")) != -1) {
         printf ("\nopt:%c, optarg:%s, optind:%d, opterr:%d, optopt:%c, argv[optind]:%s\n",
                 opt, optarg, optind, opterr, optopt, argv[optind-1]);
         switch (opt) { 
             case 'n':
                 name = optarg;
                 break;
           case 's':
                 sex = 0;
                 break;
             case 'g':
                 grade = strtoul(optarg, NULL, 10);
                 break;
             case 'c':
                 class = strtoul(optarg, NULL, 10);
                 break;
             case 'h':
                 opt_usage();
                 return 0;
             default:
                 opt_usage();
                 return -1;
         }
     }
     printf("\n\nA student info:\n");
     printf("name:%s\n", name);
     printf("sex:%d\n", sex);
     printf("grade:%d\n", grade);
     printf("class:%d\n", class);
     opt_usage();
     return 0;
 }

getopt_long函数

        前面的getopt()函数只支持短选项参数,也就是说只能用 -a 1   或者 -b 或者 -ctest;而getopt_long()函数可以支持短选项参数,同时也可以支持长选项参数;如下面:假设struct  option long options[] 数组中有这样一条 {"name", required_argument, NULL, 'n'};那么调用时可以这么写:./a.out  --name yzh (长选项参数);也可以这么写:./a.out -n yzh(短选项参数);(提到的这个数组后面会说下);

        在getopt()函数分析时说的一些知识点,这里都可以使用。这里说下新的知识点:

        函数原型:int getopt_long(int argc, char *argv[],char *optstring,struct option *longopts, int *longindex);

        参数分析:前面两个参数  argc 和 argv都是从main函数接受过来的。第三个参数和getopt()函数中的一样,用作短选项和是否带参数的表示字符串,比如:"n:s::g::c:H";

        第四个参数: struct option *longopts;是一个#include头文件中定义好的数组,这个数组非常重要,是短选项和长选项的链接的关键;数组定义如下:

struct option{
         const char *name;
         int has_arg;
         int *flag;
         int val;
};
        name是长选项的名称,一般可以这样使用:--name 参数(如果后面有参数的话);

        has_arg:是表示该选项后面是否接参数,0 == no_argument 不接参数;1 == required_argument 后面一定要接参数;2 == optional_argument 后面可以接也可以不接参数;其中 no_argument、required_argument、optional_argument是宏定义,其实就是0、1、2;

        flag 一般设置为NULL,这样getopt_long()函数就会返回val的值了。如果不设置为NULL,则会把对应的val的值保持到flag指向的变量中(flag是int指针),这时候getopt_long()函数返回0;

        val  为对应的短选项字符,和getopt_long()函数中的第三个参数对应的;

        实例如下:

     struct option long_options[] = { 
         {"name", required_argument, NULL, 'n'},
         {"sex",  optional_argument, &sex, 's'},
         {"grade", optional_argument, NULL, 'g'},
         {"class", required_argument, NULL, 'c'},
         {"help", no_argument, NULL, 'H'},
         {0, 0, 0, 0}
     };
        getopt_long()函数的第五个个参数,一般设置为NULL;如果不为NULL,那么变量会被赋值长选项在longopts中的索引值;

实例代码:

#include
 #include
 #include
 #include
 
 void print_usage()
 {
     printf("\nUsage:\n");
     printf("\t--name=student name\n");
     printf("\t-s, --sex=student sex\n"
             "\t\tif no usage ,sex is 0 means man\n\n");
     printf("\t-g, --grade=student in grade\n");
     printf("\t-c, --class=student in class\n");
     printf("\t-h, --help\n");
 }
 
 int main(int argc, char* argv[])
 {
     int opt, grade, class, sex = -1; 
     char *name = NULL;
 
     struct option long_options[] = { 
         {"name", required_argument, NULL, 'n'},
         {"sex",  optional_argument, &sex, 's'},
         {"grade", optional_argument, NULL, 'g'},
         {"class", required_argument, NULL, 'c'},
         {"help", no_argument, NULL, 'H'},
         {0, 0, 0, 0}
     };  
     
     printf("n:s::g::c:H\n");
 
  while ((opt = getopt_long(argc, argv, "n:s::g::c:H", long_options, NULL)) != -1) {
         printf ("\nopt:%c, optarg:%s, optind:%d, opterr:%d, optopt:%c, argv[optind]:%s\n",
                                  opt, optarg, optind, opterr, optopt, argv[optind-1]);
         switch (opt) {
             case 'n':
                 name = optarg;
                 printf("name:%s\n", name);
                 break;
             case 's':
                 printf("sex:%d\n", sex);
                 if (sex == -1)sex = 0;
                 //printf("sex:%d, %s", sex, sex > 0 ? "gilr":"mem");
                 break;
             case 'g':
                 if (!strcmp(argv[optind-1], "-g"))grade = 1;
                 else
                     grade = strtoul(optarg, NULL, 10);
                 break;
             case 'c':
                 class = strtoul(optarg, NULL, 10);
                 break;
             case 'H':
                 print_usage();
                 return 0;
             default:
                 print_usage();
                 return -1;
         }
     }
     printf("A student info:\n"
             "name:%s\n"
             "sex:%s\n"
             "grade:%d\n"
             "class:%d\n",
             name, sex > 0 ? "gilr" : "men", grade, class)
         ;
     return 0;
 }
        转载地址: http://blog.csdn.net/yuzhihui_no1/article/details/47789771

你可能感兴趣的:(C语言)