zoukankan      html  css  js  c++  java
  • [转载]Linux下getopt()函数的简单使用

    转载源地址:https://www.cnblogs.com/qingergege/p/5914218.html

    1、getopt()函数的出处就是unistd.h头文件(哈哈),写代码的时候千万不要忘记把他老人家include上。

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

    1)前两个参数就是main函数的两个参数;

    2)第三个参数是个字符串,看名字,我们可以叫他选项字符串(后面会说明)

    3)返回值返回的就是一个字符,什么字符呢,叫选项字符

    3、(⊙o⊙)…在此之前还要介绍他的几个兄弟~~~~呃呃呃

    小弟1、extern char* optarg;

    小弟2、extern int optind;

    小弟3、extern int opterr;

    小弟4、extern int optopt;

    队形排的不错。小弟1是用来保存选项的参数的(先混个脸熟,后面有例子);小弟2用来记录下一个检索位置;小弟3表示的是是否将错误信息输出到stderr,为0时表示不输出,小弟4表示不在选项字符串optstring中的选项(有点乱哈,后面会有例子)

    问题1:选项到底是个什么鬼?

    在linux下大家都用过这样一条指令吧:gcc helloworld.c -o helloworld.out; 这条指令中的-o就是命令行的选项,而后面的helloworld.out就是-o选项所携带的参数。当然熟悉shell指令的人都知道(虽然我并不熟悉),有些选项是不用带参数的,而这样不带参数的选项可以写在一起(这一点在后面的例子中会用到,希望理解),比如说有两个选项-c和-d,这两个选项都不带参数(而且明显是好基友),那么他们是可以写在一起,写成-cd的。实际的例子:当我们删除一个文件夹时可以使用指令 rm 目录名 -rf,本来-r表示递归删除,就是删除文件夹中所有的东西,-f表示不提示就立刻删除,他们两个都不带参数,这时他们就可以写在一起。

    问题2:选项字符串又是何方神圣?

    还是看个例子吧

    "a:b:cd::e",这就是一个选项字符串。对应到命令行就是-a ,-b ,-c ,-d, -e 。冒号又是什么呢? 冒号表示参数,一个冒号就表示这个选项后面必须带有参数(没有带参数会报错哦),但是这个参数可以和选项连在一起写,也可以用空格隔开,比如-a123 和-a   123(中间有空格) 都表示123是-a的参数;两个冒号的就表示这个选项的参数是可选的,即可以有参数,也可以没有参数,但要注意有参数时,参数与选项之间不能有空格(有空格会报错的哦),这一点和一个冒号时是有区别的。

    好了,先给个代码,然后再解释吧。

    复制代码
    #include <unistd.h>
    #include <stdio.h>
    int main(int argc, char * argv[])
    {
        
        int ch;
        printf("
    
    ");
        printf("optind:%d,opterr:%d
    ",optind,opterr);
        printf("--------------------------
    ");
           while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
           {
            printf("optind: %d
    ", optind);
               switch (ch) 
            {
                   case 'a':
                           printf("HAVE option: -a
    
    ");   
                           break;
                   case 'b':
                           printf("HAVE option: -b
    "); 
                           printf("The argument of -b is %s
    
    ", optarg);
                           break;
                   case 'c':
                           printf("HAVE option: -c
    ");
                           printf("The argument of -c is %s
    
    ", optarg);
                           break;
                   case 'd':
                       printf("HAVE option: -d
    ");
                         break;
                  case 'e':
                        printf("HAVE option: -e
    ");
                        printf("The argument of -e is %s
    
    ", optarg);
                      break;
                  case '?':
                           printf("Unknown option: %c
    ",(char)optopt);
                           break;
                   }
           }
    
    
    }
    复制代码

    编译后命令行执行:# ./main -b "qing er"

    输出结果为:

    optind:1,opterr:1
    --------------------------
    optind: 3
    HAVE option: -b
    The argument of -b is qing er

    我们可以看到:optind和opterr的初始值都为1,前面提到过opterr非零表示产生的错误要输出到stderr上。那么optind的初值为什么是1呢?

    这就要涉及到main函数的那两个参数了,argc表示参数的个数,argv[]表示每个参数字符串,对于上面的输出argc就为3,argv[]分别为: ./main 和 -b 和"qing er" ,实际上真正的参数是用第二个-b 开始,也就是argv[1],所以optind的初始值为1;

    当执行getopt()函数时,会依次扫描每一个命令行参数(从下标1开始),第一个-b,是一个选项,而且这个选项在选项字符串optstring中有,我们看到b后面有冒号,也就是b后面必须带有参数,而"qing er"就是他的参数。所以这个命令行是符合要求的。至于执行后optind为什么是3,这是因为optind是下一次进行选项搜索的开始索引,也是说下一次getopt()函数要从argv[3]开始搜索。当然,这个例子argv[3]已经没有了,此时getopt()函数就会返回-1。

    再看一个输入:

     ./main -b "qing er" -c1234

    输出结果为:

    optind:1,opterr:1
    --------------------------
    optind: 3
    HAVE option: -b
    The argument of -b is qing er

    optind: 4
    HAVE option: -c
    The argument of -c is 1234

    对于这个过程会调用三次getopt()函数,和第一个输入一样,是找到选项-b和他的参数"qing er",这时optind的值为3,也就意味着,下一次的getopt()要从argv[3]开始搜索,所以第二次调用getopt()函数,找到选项-c和他的参数1234(选项和参数是连在一起的),由于-c1234写在一起,所以他两占一起占用argv[3],所以下次搜索从argv[4]开始,而argv[4]为空,这样第三次调用getopt()函数就会返回-1,循环随之结束。

    接下来我们看一个错误的命令行输入: ./main -z 123

    输出为:

    optind:1,opterr:1
    --------------------------
    ./main: invalid option -- 'z'
    optind: 2
    Unknown option: z

    其中./main: invalid option -- 'z'就是输出到stderr的错误输出。如果把opterr设置为0那么就不会有这条输出。

    在看一个错误的命令行输入: ./main -zheng

    optind:1,opterr:1
    --------------------------
    ./main: invalid option -- 'z'
    optind: 1
    Unknown option: z
    ./main: invalid option -- 'h'
    optind: 1
    Unknown option: h
    optind: 2
    HAVE option: -e
    The argument of -e is ng

    前面提到过不带参数的选项可以写在一起,所以当getopt()找到-z的时候,发现在optstring 中没有,这时候他就认为h也是一个选项,也就是-h和-z写在一起了,依次类推,直到找到-e,发现optstring中有。

    最后要说明一下,getopt()会改变argv[]中参数的顺序。经过多次getopt()后,argv[]中的选项和选项的参数会被放置在数组前面,而optind 会指向第一个非选项和参数的位置。看例子

    复制代码
    #include <unistd.h>
    #include <stdio.h>
    int main(int argc, char * argv[])
    {
        
        int i;
        printf("--------------------------
    ");
        for(i=0;i<argc;i++)
        {
            printf("%s
    ",argv[i]);
        }
        printf("--------------------------
    ");
           //int aflag=0, bflag=0, cflag=0;
        
           int ch;
        printf("
    
    ");
        printf("optind:%d,opterr:%d
    ",optind,opterr);
        printf("--------------------------
    ");
           while ((ch = getopt(argc, argv, "ab:c:de::")) != -1)
           {
            printf("optind: %d
    ", optind);
               switch (ch) 
            {
                   case 'a':
                           printf("HAVE option: -a
    
    ");   
                           break;
                   case 'b':
                           printf("HAVE option: -b
    "); 
                           printf("The argument of -b is %s
    
    ", optarg);
                           break;
                   case 'c':
                           printf("HAVE option: -c
    ");
                           printf("The argument of -c is %s
    
    ", optarg);
                           break;
                   case 'd':
                       printf("HAVE option: -d
    ");
                         break;
                  case 'e':
                        printf("HAVE option: -e
    ");
                        printf("The argument of -e is %s
    
    ", optarg);
                      break;
                  case '?':
                           printf("Unknown option: %c
    ",(char)optopt);
                           break;
                   }
           }
        
           printf("----------------------------
    ");
          printf("optind=%d,argv[%d]=%s
    ",optind,optind,argv[optind]);
    
        printf("--------------------------
    ");
        for(i=0;i<argc;i++)
        {
            printf("%s
    ",argv[i]);
        }
        printf("--------------------------
    ");
        
    
    }
    复制代码

     命令行:./main zheng -b "qing er" han -c123 qing

    输出结果为:

    --------------------------
    ./main
    zheng
    -b
    qing er
    han
    -c123
    qing
    --------------------------


    optind:1,opterr:1
    --------------------------
    optind: 4
    HAVE option: -b
    The argument of -b is qing er

    optind: 6
    HAVE option: -c
    The argument of -c is 123

    ----------------------------
    optind=4,argv[4]=zheng
    --------------------------
    ./main
    -b
    qing er
    -c123
    zheng
    han
    qing
    --------------------------

    可以看到最开始argv[]内容为:

    ./main
    zheng
    -b
    qing er
    han
    -c123
    qing

    在执行了多次getopt后变成了

    ./main
    -b
    qing er
    -c123
    zheng
    han
    qing

    我们看到,被getopt挑出的选项和对应的参数都按顺序放在了数组的前面,而那些既不是选项又不是参数的会按顺序放在后面。而此时optind为4,即指向第一个非选项也非选项的参数,zheng

    花了40多分钟整理,希望能够给需要的人带来帮助。

    很多时候我都在寻思,为啥要花时间整理,明明已经非常忙碌了,有这点时间休息一下多好,多惬意?

    我总结的原因有一下几个:

    1、总结时会注意到之前没有关注的问题,可以加深对问题的理解。

    2、方便以后忘记的时候查阅

    3、与广大朋友们分享,想想我们从哪些大牛的博客里得到的太多了。我们应当向那些大神学习。把自己学到的分享出来,帮助其他人(虽然我很渣,但是三人行必有我师,应该还是会帮到些人吧)。

    共勉!努力!

    最后给大家介绍一个写的更加全面的文章:http://blog.csdn.net/huangxiaohu_coder/article/details/7475156

  • 相关阅读:
    还在使用golang 的map 做Json编码么?
    Golang 性能测试(2) 性能分析
    golang 性能测试 (1) 基准性能测试
    消息队列 NSQ 源码学习笔记 (五)
    消息队列 NSQ 源码学习笔记 (四)
    消息队列 NSQ 源码学习笔记 (三)
    消息队列 NSQ 源码学习笔记 (二)
    消息队列 NSQ 源码学习笔记 (一)
    你不知道的空格
    Supervisor 使用和进阶4 (Event 的使用)
  • 原文地址:https://www.cnblogs.com/FarmPick/p/9480447.html
Copyright © 2011-2022 走看看