如何构建符合 POSIX 实用程序约定的Shell-CLI —— Argtable3 源码解析(1)

总结

在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了

面试真题

Spring源码笔记

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

arg_hdr

typedef struct arg_hdr {

char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */

const char* shortopts; /* String defining the short options */

const char* longopts; /* String defiing the long options */

const char* datatype; /* Description of the argument data type */

const char* glossary; /* Description of the option as shown by arg_print_glossary function */

int mincount; /* Minimum number of occurences of this option accepted */

int maxcount; /* Maximum number of occurences if this option accepted */

void* parent; /* Pointer to parent arg_xxx struct */

arg_resetfn* resetfn; /* Pointer to parent arg_xxx reset function */

arg_scanfn* scanfn; /* Pointer to parent arg_xxx scan function */

arg_checkfn* checkfn; /* Pointer to parent arg_xxx check function */

arg_errorfn* errorfn; /* Pointer to parent arg_xxx error function */

void* priv; /* Pointer to private header data for use by arg_xxx functions */

} arg_hdr_t;

最基本的一个类型,所有的其他类型都包含这个类型。一一解释下里面的参数的含义:

  • shortopts: 参数的短名称,比如ls -a 中的a就是短名称;

  • longopts: 参数中的长名称,比如ls —all 中的all就是长名称;

  • datatype: 参数的数据类型有, , NULL, ,(时间类型传入format字符串),(rex类型传入匹配串),等;

  • glossary: 对于参数的描述;

  • mincount: 参数最少的个数(可以规定是否必须有参数比如设置为0为非必须,1…n为必须);

  • maxcount: 参数最多的个数,采用Unix风格的,如kernel.exe -l 1 -l 2 -l 3

  • 其他参数非必须。

arg_xxx结构体族

// 整数

struct arg_int

{

struct arg_hdr hdr;

int count;

int *ival;

};

// 文字

struct arg_lit

{

struct arg_hdr hdr;

int count;

};

// 双精度浮点数

struct arg_dbl

{

struct arg_hdr hdr;

int count;

double *dval;

};

// 字符串

struct arg_str

{

struct arg_hdr hdr;

int count;

const char **sval;

};

struct arg_rex

{

struct arg_hdr hdr;

int count;

const char **sval;

};

struct arg_file

{

struct arg_hdr hdr;

int count;

const char **filename;

const char **basename;

const char **extension;

};

struct arg_date

{

struct arg_hdr hdr;

const char *format;

int count;

struct tm *tm_val;

};

详细介绍 arg_int

struct arg_int

{

struct arg_hdr hdr;

int count;

int *ival;

};

结构体的第一个数据成员hdr保存了 Argtable3 库函数使用的私有数据。它包含参数的标签字符串等内容(可以理解为元数据)。

直接公开地访问这些数据是可以的,但很少需要这样做。

它的ival成员变量指向持有从命令行提取出的数组,count为数组的长度。ival 数组的存储在arg_int构造时分配。

这必须通过arg_int构造函数完成。

注意,你永远不应该自己手动实例化任何arg_xxx结构,而是始终使用提供的构造函数来分配结构,并在完成后使用 arg_freetable 释放它。

  • 举例

struct arg_int *s;

s = arg_intn(NULL, “scalar”, “”, 3, 5, “foo value”);

完成s后将指向一个包含5 个元素数组的内存块的结构体arg_int。

甚至,你还可以设置多个别名,短选项被赋予一串单个字符,而长选项被赋予一个逗号分隔的字符串。

例如:s = arg_intn("kKx", "scalar,foo", "<n>", 3, 5, "foo value");

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vo3FZ9oz-1633800152784)(example.png)]

如图所示,该s->hdr结构保留对构造函数的字符串参数的引用等。

s->count变量初始化为零,因为它表示s->ival解析命令行后存储在数组中的有效值的数量。

s->ival数组的大小由s->hdr.maxcount给出。

  • 实例代码

// 引入 argtable3

#include “argtable3.h”

/* global arg_xxx structs */

struct arg_int *int_arrays;

struct arg_end *end;

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

/* the global arg_xxx structs are initialised within the argtable */

void *argtable[] = {

int_arrays = arg_intn(“a”, “array”, “”, 2, 3, “please input an integer”),

end = arg_end(20)

};

int exitcode = -1;

int nerrors = arg_parse(argc, argv, argtable);

if (nerrors == 0) {

exitcode = 0;

int *a = int_arrays->ival;

int len = int_arrays->count;

printf(“input numbers are as following:\n”);

for (int i = 0; i < len; ++i) {

printf("%d ", a[i]);

}

}

return exitcode;

}

运行

./argtable -a 1 -a 2 --array 3

输出

input numbers are as following:

1 2 3

其他的参数结构体使用方法大同小异。

The Argument Table (参数表)

在构建完各种类型参数的结构体之后,我们需要统一将它们组装到一个结构体数组里面,类型为void **

struct arg_lit *a = arg_litn(“a”, NULL, 0, 1, “the -a option”);

struct arg_lit *b = arg_litn(“b”, NULL, 0, 1, “the -b option”);

struct arg_lit *c = arg_litn(“c”, NULL, 0, 1, “the -c option”);

struct arg_int *scal = arg_intn(NULL, “scalar”, “”, 0, 1, “foo value”);

struct arg_lit *verb = arg_litn(“v”, “verbose”, 0, 1, “verbose output”);

struct arg_file *o = arg_filen(“o”, NULL,“myfile”, 0, 1, “output file”);

struct arg_file *file = arg_filen(NULL, NULL, “”, 1, 2, “input files”);

struct arg_end *end = arg_end(20);

// 这就是我们的参数列表

void *argtable[] = {a, b, c, scal, verb, o, file, end};

其中,arg_end 结构体是一个特殊的结构体,因为它不代表任何命令行选项。

它主要标记 argtable 数组的结尾,同时它也存储在处理命令行参数时遇到的任何解析器错误。

传递给arg_end构造函数的整数参数是它将存储的最大错误数,任何更多的错误都将被丢弃并替换为单个错误消息“错误太多”。

arg_end必须要有。

你还可以使用arg_nullcheck检查参数表中是否有空指针,(感觉这个功能很鸡肋)

if (arg_nullcheck(argtable) != 0)

printf(“error: insufficient memory\n”);

解析命令行

我们使用arg_parse函数来做到这一点,它返回它遇到的解析错误的数量。

int nerrors = arg_parse(argc, argv, argtable);

如果没有错误的话(nerrors == 0),那么我们已经成功解析了命令行,你想要在命令行中提取的数据也都存在了参数表这个void**里面,正常地访问它即可。

设置默认值

对此的解决方法很简单,直接在调用arg_parse之前设置arg_table的值,在命令行中有用户输入的值才会被覆盖。

其余的,就是你一开始设置的默认值。

错误处理

如果 arg_parse 函数报告错误,那么我们需要显示它们,因为 arg_parse 本身不会这样做。

使用arg_print_errors即可,arg_end的内部结构无需关心。

函数定义

void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname);

最后如何让自己一步步成为技术专家

说句实话,如果一个打工人不想提升自己,那便没有工作的意义,毕竟大家也没有到养老的年龄。

当你的技术在一步步贴近阿里p7水平的时候,毫无疑问你的薪资肯定会涨,同时你能学到更多更深的技术,交结到更厉害的大牛。

推荐一份Java架构之路必备的学习笔记,内容相当全面!!!

成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

5532380874)]

成年人的世界没有容易二字,前段时间刷抖音看到一个程序员连着加班两星期到半夜2点的视频。在这个行业若想要拿高薪除了提高硬实力别无他法。

你知道吗?现在有的应届生实习薪资都已经赶超开发5年的程序员了,实习薪资26K,30K,你没有紧迫感吗?做了这么多年还不如一个应届生,真的非常尴尬!

进了这个行业就不要把没时间学习当借口,这个行业就是要不断学习,不然就只能被裁员。所以,抓紧时间投资自己,多学点技术,眼前困难,往后轻松!

【关注】+【转发】+【点赞】支持我!创作不易!

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值