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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容