zoukankan      html  css  js  c++  java
  • Linux getopt函数处理传入参数

    1、Linux传入参数处理

    在介绍使用getopt函数处理应用程序传入参数前,先来看一下Linux环境下编写的应用程序是如何处理传入的参数的

    Linux环境编写应用程序时,main函数一般会有两个参数,用于描述执行应用程序时传入的参数,书写形式如下:

    int main(int argc, char *argv[])
    • argc:表示传入参数的个数
    • argv:指针数组,每一项存放一个传入参数字符串的地址

    在shell中启动这个应用程序,shell接受用户输入命令行,将命令行分解成单词,然后把这些单词放入到一个数组,操作系统将这个存放单词数组的长度和数组作为参数传递给了main函数。因此,实际情况下,argv[0]指向的一定是运行当前应用程序的全路径名称,argv[1]~argv[argc-1]指向的才是传入参数,实际传入参数的个数为argc-1

    例如有一个名为hello_world应用程序,在shell中按照 "./hello_world 3" 执行该程序,此时,argc = 2,argv[0]指向的是 "./hello_world" 字符串存放地址,argv[1]指向的才是传入参数 "3" 字符串存放地址

    显然,我们可以在main函数内自己编写程序,通过解析argc,argv参数来获取执行应用程序所传入的参数。但对于Linux这种广泛使用的操作系统,它已经在库函数中为用户提供了用于命令行参数解析的函数,我们直接调用这些函数,便可轻松的解析各种命令行参数模式

    这里所讲的getopt函数,就是标准库中实现的一个用于解析命令行参数的函数,它支持需要关联值和不需要关联值的选项,而且简单易用

    (所谓的需要关联值的选项,以gcc编译器为例子,gcc的-o选项表示输出可执行程序名称,这个后面就需要跟一个名称才能正常使用,后面一个参数就是-o命令的关联值;所谓的不需要关联值,以ls命令为例子, ls的-l命令表示列出当前目录所有文件,这个后面不需要跟一些其他信息,这种被称作不需要关联值的选项)

    2、getopt函数的原型

    getopt函数有三个参数,函数的原型如下:

    int getopt(int argc, char * const argv[],
                      const char *optstring);
    
    extern char *optarg;
    extern int optind, opterr, optopt;

    getopt函数本质上其实就是对main函数传入的argc和argv参数进行处理,它将传递给程序的main函数的argc和argv作为参数,同时接受一个选项指定字符串optstring。optstring字符串告诉getopt哪些选项可用,以及它们是否有关联值。

    optstring是一个字符串列表,每个字符代表一个单字符选项。如果一个字符后面紧跟一个冒号(:),则表示一个该选项有一个关联值作为下一个参数。

    例如:getopt(argc, argv, "if:l")

    它允许-i、-f、-l作为参数,其中-f选项后要紧跟一个参数,也就是它的关联值。这里参数的传递可以不按照optstring字符串列表写入的顺序来传

    getopt的返回值是argv数组中的下一个选项字符,循环调用getopt可以依次得到argv中每一个选项。函数的处理行为如下:

    • 如果选项处理完毕,返回值为-1。循环遇到-1,参数判断完毕,可以退出循环
    • 如果选项有一个关联值,全局变量optarg指向这个值
    • 如果遇到不在optstring中选项,getopt返回一个问号(?),并将无法识别选项存放到全局变量optopt,有些getopt版本会在遇到未知选项时打印错误信息
    • 如果选项要求有关联值,但是用户没传入一个关联值,默认情况下getopt通常返回一个问号(?)。我们可以将选项字符串的第一个字符设置成冒号,这个没传入关联值时,返回的是冒号(:)而不是问号(?)

    optind表示下一个待处理参数的索引,getopt利用它来记录自己的进度,一般情况下在程序中很少用到

    3、函数的使用

    编写一个简单的例子,来演示getopt函数使用

    #include <stdio.h>
    #include <unistd.h>
    
    
    int main(int argc, char *argv[])
    {
        int res;
    
        while((res = getopt(argc, argv, ":io:l")) != -1)
        {
            switch(res)
            {
                case 'i':
                case 'l':
                        printf("option: %c
    ", res);
                        break;
                        
                case 'o':
                        printf("option: %c %s
    ", res, optarg);
                        break;
                        
                case ':':
                        printf("option need a value
    ");
                        break;
                        
                case '?':
                        printf("unknown option: %c
    ", optopt);
                        break;
                        
                default:
                        break;
            }
        }
    }

    演示程序中的main函数内使用getopt函数对传入参数进行解析,支持参数有-i、-o、-l,其中-o参数后要有一个关联值。这里optstring参数的第一个字符设置成冒号,是用来分辨输入-o选项,但没传入关联值情况,这种情况(:)被返回

    --->如果传入-i、-l参数,打印参数信息

    --->如果传入-o参数,打印参数信息和关联值信息

    --->如果传入-o参数,并没传入关联值,打印出提示信息

    --->如果传入无效参数时,打印出不识别提示信息

    4、小结

    调用getopt函数可以方便的处理我们程序中传入的不同参数,它按照我们指定的方式来解析main函数中传入的argc和argv参数,并返回选项字符。支持的参数在getopt的optstring参数指定,通过参数后面冒号(:)的有无来表示该参数后面是否需要紧跟关联值信息。但getopt函数也有自己的局限性,它仅支持的是单字符参数,如果想接受比单字符选项含义更明确的参数时,就不适用了。不过,如果你有这种需求,可以去研究下C库中getopt函数的另一个增强版本——getopt_long,它接受以下划线(--)开始的长参数

  • 相关阅读:
    字节跳动在 Go 网络库上的实践
    TCP报文段的首部格式 20字节的固定首部
    网易公开课 文件描述符 索引
    网易新闻App架构重构实践:DDD正走向流行
    货 | 携程是如何做AB实验分流的
    Pusher Channels Protocol | Pusher docs https://pusher.com/docs/channels/library_auth_reference/pusher-websockets-protocol
    避免重复提交?分布式服务的幂等性设计! 架构文摘 今天 点击蓝色“架构文摘”关注我哟 加个“星标”,每天上午 09:25,干货推送! 来源:https://www.cnblogs.com/QG-whz/p/10372458.html 作者:melonstreet
    前置时间(Lead Time),也称前置期、备货周期
    滴滴业务研发的精益实践
    DevOps运动的缘起 将DevOps想象为一种编程语言里面的一个接口,而SRE类实现了这个接口
  • 原文地址:https://www.cnblogs.com/053179hu/p/14285069.html
Copyright © 2011-2022 走看看