【Linux 命令行参数解析函数getopt()】原理及直白理解

最近写代码恰好碰见getopt()这个函数,去网上找了很久,说实话,其他人写的有点看不懂,所以将我认为可以便于理解的地方描述一下:

c 复制代码
int getopt(int argc, char * const argv[], const char *optstring);

首先理解这个函数的功能(不能保证大家都能理解)

  1. 获取命令行信息,并读取命令行中的选项;

    (命令行组成或许存在盲区,这是某位博主的这是他的博客

    Option就是选项,Option argument是参数:

  2. 每读取到一个选项,会返回一个int整型 ,这个整型不是选项位置,而是选项对应的ASCII码值

  3. 这个函数附带了一些全局变量,这些全局变量中的optarg 会对应着解析到的某个选项对应的参数

其次我们需要理解函数原型

该函数的参数说明如下:

argc(参数个数):
  1. 类型:int
  2. 说明:这是从main函数传递过来的命令行参数个数。在C语言中,argc包含了程序名(即argv[0]),因此如果命令行中有3个参数(不包括程序名),则argc的值为4。
argv(参数内容):
  1. 类型:char * const argv[]
  2. 说明:这是从main函数传递过来的命令行参数数组。argv是一个指向指针的指针,每个指针指向一个C风格的字符串(以null字符\0结尾)。argv[0]通常是程序的名称,随后的元素是传递给程序的命令行参数。
optstring(选项字符串):
  1. 类型:const char *
  2. 说明:这是一个字符串,它定义了getopt函数可以识别的选项。选项字符串中的每个字符都代表一个有效的选项。如果某个选项字符后面跟着一个冒号(:),则表示该选项需要一个参数。如果字符后面跟着两个冒号(::),则表示该选项的参数是可选的。
getopt函数的返回值主要有以下几种情况:
  1. 选项字符:当成功解析一个选项时,getopt返回该选项的字符(实际上是其ASCII码值,但通常直接作为字符使用)。
  2. EOF或-1:当所有选项都解析完毕后,getopt返回EOF(在POSIX系统中,EOF通常定义为-1)。这表示没有更多的选项需要处理。
  3. '?':如果遇到不符合optstring指定的选项,并且opterr未被设置为0,getopt会打印一个错误消息,并返回'?'字符。这通常用于表示未知的选项。

getopt函数的全局变量:

  1. optarg:指向当前选项参数的指针(如果有的话)。
  2. optind:再次调用getopt时的下一个argv指针的索引。
  3. opterr:如果设置为0,则getopt不会打印错误消息。
  4. optopt:最后一个未知选项。

getopt函数的行为:

  1. 当成功解析一个选项时,返回该选项的字符(实际上是其ASCII码值,但通常直接作为字符使用)。
  2. 当所有选项都解析完毕后,返回-1或EOF。
  3. 如果遇到不符合optstring指定的选项,getopt将显示一个错误消息(除非opterr被设置为0),并将optopt设为?字符。

getopt参数示例(这个案例很清晰,如果要做大总结,我觉得这个函数的名称其实就足够:命令行参数解析函数)

假设我们有以下optstring:"ab:c::de",并考虑以下命令行参数:

bash 复制代码
./program -a -b argb --c=argc -d -e arge foo bar

在C程序中,我们可能会这样使用getopt:

c 复制代码
#include <stdio.h>  
#include <stdlib.h>  
#include <unistd.h>  
  
int main(int argc, char *argv[]) {  
    int opt;  
    while ((opt = getopt(argc, argv, "ab:c::de")) != -1) {  
        switch (opt) {  
        case 'a':  
            printf("Option -a\n");  
            break;  
        case 'b':  
            printf("Option -b with argument '%s'\n", optarg);  
            break;  
        case 'c':  
            // 注意:如果选项c后面有参数,它必须紧跟在c后面  
            if (optarg) {  
                printf("Option -c with argument '%s'\n", optarg);  
            } else {  
                printf("Option -c (no argument)\n");  
            }  
            break;  
        case 'd':  
            printf("Option -d\n");  
            break;  
        case 'e':  
            // 注意:选项e后面的'arge'不是选项e的参数,而是非选项参数  
            printf("Option -e\n");  
            break;  
        case '?':  
            // getopt会打印错误消息,但我们也可以在这里添加自定义处理  
            fprintf(stderr, "Unknown option: %c\n", optopt);  
            exit(EXIT_FAILURE);  
        default:  
            abort(); // 其他情况下,应该不会发生  
        }  
    }  
  
    // optind现在是第一个非选项参数的索引  
    // 在这个例子中,它是"foo"的索引  
    for (int i = optind; i < argc; i++) {  
        printf("Non-option argument: %s\n", argv[i]);  
    }  
  
    return 0;  
}

运行上面的程序,输出将会是:

bash 复制代码
Option -a  
Option -b with argument 'argb'  
Option -c (no argument) // 因为-c后面没有直接跟随参数  
Option -d  
Option -e  
Non-option argument: foo  
Non-option argument: bar

注意,尽管命令行中包含--c=argc这样的长选项格式,但getopt只处理短选项(单个字符的选项)。如果你需要处理长选项,可能需要使用getopt_long函数或手动解析它们。

相关推荐
人才程序员几秒前
【Rust入门】生成随机数
开发语言·数据库·后端·单片机·rust
DevGu2 分钟前
linux ifconfig未找到命令
linux·运维·服务器
小森( ﹡ˆoˆ﹡ )7 分钟前
【neo4j图数据库】入门实践篇
数据库·人工智能·机器学习·nlp·neo4j
天蓝蓝的本我11 分钟前
SQL Server查看所有的数据库、所有的表 以及表的描述
数据库·sqlserver
快快小毛毛23 分钟前
弹性伸缩高性能计算服务一一黑石裸金属服务器
运维·服务器·网络·数据库·安全
武帝为此29 分钟前
【Spring Boot AOP通知顺序】
java·数据库·spring boot
DaGod12330 分钟前
set_source_files_properties QT_QML_SINGLETON_TYPE
数据库
千殃sama42 分钟前
Linux高并发服务器开发(八)Socket和TCP
linux·服务器·笔记·学习·tcp/ip
不爱洗脚的小滕43 分钟前
【MySQL】SQL注入的介绍
数据库·sql·mysql
夜流冰1 小时前
GNU/Linux - wic文件的使用
linux