c语言 命令行 解析 参数 ksargv argc

ksargv解析命令行参数

V0.0.3.20210623


项目简介

介绍ksargv解析命令行参数步骤

源代码项目托管:https://github.com/kiraskyler/ksargv

正文

  • 查看示例代码
void template_version(e_argv_type* argv,  s_ksargv_value* values, unsigned int values_count, e_argv_erro erro);
char* version_option[] = {"-v", "-version", NULL};
e_argv_type version_type[] = {ARGV_STRING, ARGV_END};

void template_ip_port(e_argv_type* argv,  s_ksargv_value* values, unsigned int values_count, e_argv_erro erro);
char* ip_port_option[] = {"-ip", NULL};
e_argv_type ip_port_type[] = {ARGV_STRING, ARGV_INT, ARGV_END};

void template_am_i_great(e_argv_type* argv,  s_ksargv_value* values, unsigned int values_count, e_argv_erro erro);
char* am_i_great_option[] = {"-g", "-great", NULL};
e_argv_type am_i_great_type[] = {ARGV_BOOL, ARGV_END};

void template_score(e_argv_type* argv,  s_ksargv_value* values, unsigned int values_count, e_argv_erro erro);
char* score_option[] = {"-s", "-score", NULL};
e_argv_type score_type[] = {ARGV_DOUBLE, ARGV_END};

void template_keep(e_argv_type* argv,  s_ksargv_value* values, unsigned int values_count, e_argv_erro erro);
char* keep_option[] = {"-k", "-keep", NULL};
e_argv_type keep_type[] = {ARGV_END};


s_ksargv_elems argv_options[] =
{
    {
        .option = version_option,
        .args = version_type,
        .function = template_version,
    },
    {
        .option = ip_port_option,
        .args = ip_port_type,
        .function = template_ip_port,
    },
    {
        .option = am_i_great_option,
        .args = am_i_great_type,
        .function = template_am_i_great,
    },
    {
        .option = score_option,
        .args = score_type,
        .function = template_score,
    },
    {
        .option = keep_option,
        .args = keep_type,
        .function = template_keep,
    },
};
以argv_options 数组看,数组存储三个元素,option是字符串指针,描述命令行中输入的命令名称,args描述需要接受的命令行参数,同时也表示了接收的命令行参数数量。function函数是将命令行解析的结果回调函数,直接查看ksargv中的说明即可
/**
 * argv from <iksargv_parse_argv> argv
 * values is array store values, if something erro, it will be NULL, and values_count will be zero
 * values_count values array count, if something erro, it will be NULL, and values_count will be zero
 * erro store why this function is erro, if there is no erro, it will be set ARGV_ERRO_NONE, when
 *  it be set ARGV_ERRO, mybe you should check ksargv source code or connect coder
*/
typedef void (*f_ksargv_function)(e_argv_type* argv, s_ksargv_value* values, unsigned int values_count, e_argv_erro erro);

  • 存储字符串数组和不定长数组的结构体方法中,没有好主意可以直接初始化,只好提前定义好数组,在结构体初始化时使用数组指针,如有更简单的技巧请联系作者修改

  • 示例代码的主函数只有两行

    int main(int argc, char** argv)
    {
        ksargv_parse_argv(argv, argv_options, sizeof(argv_options) / sizeof(s_ksargv_elems));
        dbg_print_mem();
    }
    

    第一行是解析命令行,第二行是调试使用,可以打印出动态内存申请次数,如果申请和释放次数是一样的,输出0

  • 解析主函数

    int ksargv_parse_argv(char** argv, s_ksargv_elems* elems, unsigned int elems_count)
    {
        if(argv[0] == NULL || argv[1] == NULL || elems_count == 0)
            return 0;
        s_ksargv_elems_status* status = KSARGV_MALLOC(sizeof(s_ksargv_elems_status) * elems_count);
        if(status == NULL)
        {
            errno = ENOMEM;
            return -1;
        }
        memset(status, 0, sizeof(s_ksargv_elems_status) * elems_count);
        for(int i = 1; argv[i] != NULL; i++)
        {
            int elem_index;
            if((elem_index = ksargv_parse_argv_get_elem_index(argv[i], status, elems, elems_count)) >= 0)
            {
                status[elem_index].select = true;
                int args_count = ksargv_parse_argv_get_elem_argv_count(elems[elem_index].args);
                if(args_count == 0)              /* this option do not need args */
                    elems[elem_index].function(elems[elem_index].args, NULL, 0, ARGV_ERRO_NONE);
                else
                {
                    /* ready */
                    s_ksargv_value* values = KSARGV_MALLOC(sizeof(s_ksargv_value) * args_count);
                    if(values == NULL)
                    {
                        elems[elem_index].function(elems[elem_index].args, NULL, 0, ARGV_ERRO_LESS_ARGS);
                        errno = ENOMEM;
                        goto fall;
                    }
                    /* loop, convert argv */
                    for(int arg_index = 0; arg_index < args_count; arg_index++)
                    {
                        if(argv[i + 1] == NULL)
                        {
                            KSARGV_FREE(values);
                            elems[elem_index].function(elems[elem_index].args, NULL, 0, ARGV_ERRO_LESS_ARGS);
                            errno = ERESTART;
                            goto fall;
                        }
                        bool res = true;
                        values[arg_index].type = elems[elem_index].args[arg_index];
                        switch(elems[elem_index].args[arg_index])
                        {
                            case ARGV_STRING:
                                values[arg_index].value.str = argv[++i];
                                break;
                            case ARGV_INT:
                                values[arg_index].value.num_i = ksargv_parse_argv_get_int(argv[++i], &res);
                                break;
                            case ARGV_BOOL:
                                values[arg_index].value.num_b = ksargv_parse_argv_get_bool(argv[++i], &res);
                                break;
                            case ARGV_DOUBLE:
                                values[arg_index].value.num_d = ksargv_parse_argv_get_double(argv[++i], &res);
                                break;
                            default:
                                break;
                        }
                        if(res == false)
                        {
                            KSARGV_FREE(values);
                            elems[elem_index].function(elems[elem_index].args, NULL, 0, ARGV_ERRO_LESS_ARGS);
                            errno = ERESTART;
                            goto fall;
                        }
                    }
                    /* done, send */
                    elems[elem_index].function(elems[elem_index].args, values, args_count, ARGV_ERRO_NONE);
                    KSARGV_FREE(values);
                }
            }
        }
        KSARGV_FREE(status);
        return 0;
    fall:
        KSARGV_FREE(status);
        return -1;
    }
    
    • 首先将会申请内存存储状态,状态结构体中只含有一个命令行命令是否被选中过,如-a,确保一段-a只执行一次,应该不会有需要-a执行多次的需求吧,不会吧 不会吧 不会吧
    • 接下来遍历命令行的argv 逐个判断是否有现成的示例程序数组option字段
    • 将遍历得到的结果,根据示例程序的argv按照格式保存下来,如果格式不对,立刻退出,并回调到function函数,通知出现了错误。

使用说明

维护说明

注意

关于作者

Autho: KiraSkyler
Email: kiraskyler@outlook.com / kiraskyler@qq.com

贡献者/贡献组织

鸣谢

版权信息

该项目签署了GPL 授权许可,详情请参阅官网

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see https://www.gnu.org/licenses/.

更新日志

  • V0.0.0.20210101
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容