【ArgParse】一个开源的入参解析库
项目地址:argtable3
本地验证:
-
编译构建
-
新增验证
// examples/skull.c
#include "argtable3.h"
int main(int argc, char **argv)
{
const char* progname = "skull";
struct arg_lit *help = arg_lit0("h", "help", "this is help info");
struct arg_lit *litn = arg_litn("l", "literal", 0, 5, "./progname -l --literal");
struct arg_int *intn = arg_intn("i", "integer", "<int>", 0, 5, "./program -i 10 -i 20 -i 30");
struct arg_dbl *dbln = arg_dbln("d", "double", "<double>", 0, 5, "./program -d 3.14 -d 2.718 -d 1.414");
struct arg_str *strn = arg_strn("s", "string", "<string>", 0, 5, "./program -s hello -s world");
struct arg_rex *rexn = arg_rexn("r", "regular", "^[A-Za-z0-9]+$", "<regex>", 0, 5, ARG_REX_ICASE, "./program -r [digit] -r [letters]");
struct arg_file *filen = arg_filen("f", "file", "<file>", 0, 5, "./program file1.txt file2.txt file3.txt");
struct arg_date *daten = arg_daten("a", "date", "%Y-%m-%d", "<date>", 0, 5, "./program -a 2023-09-01 -a 2023-09-02 -a 2023-09-03");
struct arg_end *end = arg_end(20);
void* argtable[] = {help, litn, intn, dbln, strn, rexn, filen, daten, end};
int nerrors;
int exitcode=0;
/* verify the argtable[] entries were allocated sucessfully */
if (arg_nullcheck(argtable) != 0) {
/* NULL entries were detected, some allocations must have failed */
printf("%s: insufficient memory\n", progname);
exitcode=1;
goto exit;
}
/* Parse the command line as defined by argtable[] */
nerrors = arg_parse(argc, argv, argtable);
/* If the parser returned any errors then display them and exit */
if (nerrors > 0) {
/* Display the error details contained in the arg_end struct.*/
arg_print_errors(stdout,end,progname);
printf("Try '%s --help' for more information.\n", progname);
exitcode=1;
goto exit;
}
/* special case: '--help' takes precedence over error reporting */
if (help->count > 0) {
printf("Usage: %s", progname);
arg_print_syntax(stdout, argtable, "\n");
printf("Print certain system information. With no options, same as -s.\n\n");
arg_print_glossary(stdout, argtable," %-25s %s\n");
printf("\nReport bugs to <foo@bar>.\n");
exitcode=0;
goto exit;
}
/* special case: '--version' takes precedence error reporting */
if (litn->count > 0) {
printf("'%s' count: %d.\n", litn->hdr.glossary, litn->count);
exitcode=0;
goto exit;
}
if (intn->count > 0) {
printf("'%s' count: %d.\n", intn->hdr.glossary, intn->count);
for (int i = 0; i < intn->count; i++) {
printf("Integer %d: %d\n", i+1, intn->ival[i]);
}
exitcode=0;
goto exit;
}
if (dbln->count > 0) {
printf("'%s' count: %d.\n", dbln->hdr.glossary, dbln->count);
for (int i = 0; i < dbln->count; i++) {
printf("Double %d: %lf\n", i+1, dbln->dval[i]);
}
exitcode=0;
goto exit;
}
if (strn->count > 0) {
printf("'%s' count: %d.\n", strn->hdr.glossary, strn->count);
for (int i = 0; i < strn->count; i++) {
printf("String %d: %s\n", i+1, strn->sval[i]);
}
exitcode=0;
goto exit;
}
if (rexn->count > 0) {
printf("'%s' count: %d.\n", rexn->hdr.glossary, rexn->count);
for (int i = 0; i < rexn->count; i++) {
printf("Regular %d: %s\n", i+1, rexn->sval[i]);
}
exitcode=0;
goto exit;
}
if (filen->count > 0) {
printf("'%s' count: %d.\n", filen->hdr.glossary, filen->count);
for (int i = 0; i < filen->count; i++) {
printf("File %d: %s\n", i+1, filen->filename[i]);
}
exitcode=0;
goto exit;
}
if (daten->count > 0) {
printf("'%s' count: %d.\n", daten->hdr.glossary, daten->count);
for (int i = 0; i < daten->count; i++) {
printf("Date %d: %04d-%02d-%02d\n", i+1, daten->tmval[i].tm_year, daten->tmval[i].tm_mon, daten->tmval[i].tm_mday);
}
exitcode=0;
goto exit;
}
exit:
/* deallocate each non-null entry in argtable[] */
arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0]));
return exitcode;
}
-
源码修改
实测月份少1,年份是基于1900
// src/arg_date.c
char* arg_strptime(const char* buf, const char* fmt, struct tm* tm) {
while ((c = *fmt) != '\0') {
/* Clear `alternate' modifier prior to new conversion. */
alt_format = 0;
/* Eat up white-space. */
if (isspace(c)) {
while (isspace((int)(*bp)))
bp++;
fmt++;
continue;
}
if ((c = *fmt++) != '%')
goto literal;
again:
switch (c = *fmt++) {
case 'm': /* The month. */
LEGAL_ALT(ALT_O);
if (!(conv_num(&bp, &i, 1, 12)))
return (0);
/* tm->tm_mon = i- 1; @skull #2023-9-14 10:18:34 */
tm->tm_mon = i;
break;
case 'Y': /* The year. */
LEGAL_ALT(ALT_E);
if (!(conv_num(&bp, &i, 0, 9999)))
return (0);
/* tm->tm_year = i - TM_YEAR_BASE; @skull #2023-9-14 10:19:59 */
tm->tm_year = i;
break;
-
执行
再牛逼的梦想也架不住傻逼似的坚持