V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
12tall
V2EX  ›  程序员

不只是 [C 语言] :请问各位大佬是如何处理 main 函数传入的参数的

  •  
  •   12tall · 2019-09-24 09:16:56 +08:00 · 3152 次点击
    这是一个创建于 1889 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问,如果传入 main 函数的参数较多,应该如何组合处理啊

    /*
    * demo.exe
    * 使用:demo.exe -name 12tall -age 12 -boy -newbie
    */
    int main(argc,char* argv[]){
      /*
      * 有一个思路:
      * 1. 参数分为两种:需要读取值的,例如 -name -age ;不需要读取值的,大胆称为 [状态参数] 吧,例如 -boy -newbie
      * 2. 一般需要传入值的参数都赋予默认值
      * 3.  [状态参数] 可以这样取值:-boy=01b、-girl=00b、-newbie=00b、-expert=10b ;这样就可以组成 00b~11b 四种状态  
      * 4. 然后对应着写 4 个状态处理的函数(参数就是需要取值的那些参数,例如 name、age ),放在一个存放函数指针数组里面,由状态参数组合成的最终值就是指向合适函数的索引
      */
    }
    
    第 1 条附言  ·  2019-09-24 10:15:48 +08:00

    我的表述有问题,应该是:
    鉴于if...else... 嵌套的层数太多不好理解
    请问如何组合程序获取到的参数,以确定接下来的代码怎么走

    第 2 条附言  ·  2019-09-24 18:00:47 +08:00

    写了一个例子,目标是做一个软盘读写的工具。感觉也没有精简太多,不包含解析参数的部分,只有最简单的状态处理
    整体思路是利用宏命令批量声明组合函数,然后再手工实现函数定义,并绑定到一个数组中
    然后程序就可以根据参数通过位掩码直接定位到函数
    但是感觉宏定义那块还是很僵硬!

    // 头文件bin2img.h
    #ifndef __BIN2IMG__
    #define __BIN2IMG__
    
    #define Params const char* fIn,const char* fOut,int offset
    typedef void (*pStateFunction)(Params);
    
    
    // format
    #define 	F_RAW   0b00000000
    #define 	F_FAT12  0b00000001
    // boot
    #define 	B_NORMAL  0b00000000
    #define 	B_BOOT  0b00010000
    // init
    #define 	I_NONE  0b00000000
    #define 	I_INIT  0b01000000
    
    // 批量声明函数,共2*2*2=8个
    #define  GenStateFunctions(_)\
    	void _(Params);
    // 磁盘格式
    #define FORMAT_LIST(_,$)\
    	_(F_RAW_##$)\
    	_(F_FAT12_##$)
    // 是否是启动盘
    #define BOOT_LIST(_,$)\
    	FORMAT_LIST(_,B_NORMAL_##$)\
    	FORMAT_LIST(_,B_BOOT_##$)
    // 初始化还是直接读写
    #define INIT_LIST(_)\
    	BOOT_LIST(_,I_NONE)\
    	BOOT_LIST(_,I_INIT)
    
    INIT_LIST(GenStateFunctions);
    #undef  INIT_LIST
    #undef BOOT_LIST
    #undef FORMAT_LIST
    #undef GenStateFunctions
    
    // 给函数指针数组赋值
    #define  SetStateFunction(index,func)\
    	funs[index]=func;
    
    // 默认帮助函数
    void ShowHelp(void);
    
    
    #elif
    #endif
    
    
    // c 文件
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #include "bin2img.h"
    
    pStateFunction funs[256] = { NULL };
    // argc 一般至少为1,因为程序名也会算做参数
    int main(int argc, char* argv[])
    {
    	// 添加状态函数,这里感觉韩式不够简洁
    	SetStateFunction(I_INIT, F_RAW_B_NORMAL_I_INIT);
    
    	// 测试函数
    	funs[I_INIT](NULL,NULL,0);
    	return 0;
    }
    
    // 函数的实现
    void F_RAW_B_NORMAL_I_INIT(const char* fIn, const char* fOut, int offset)
    {
    	printf("raw normal init");
    }
    
    
    void ShowHelp(void)
    {
    	printf("write binary file to image file or floppy\n");
    }
    
    
    

    收获还是有的~

    23 条回复    2019-09-24 19:22:36 +08:00
    momocraft
        1
    momocraft  
       2019-09-24 09:22:21 +08:00
    学习使用 getopt
    12tall
        2
    12tall  
    OP
       2019-09-24 09:34:05 +08:00
    @momocraft
    我重点表述错了,请问在已经拿到参数的情况下,怎么可以比较好地根据各项参数确定下一步状态,而不要写很多层 if...else...
    pkookp8
        3
    pkookp8  
       2019-09-24 09:46:29 +08:00 via Android
    入参
    设全局变量
    主流程
    if 某个全局变量
    特殊流程
    xpfd
        4
    xpfd  
       2019-09-24 09:55:04 +08:00
    写代码在保证功能的情况下 尽量写的简洁明了, 不用在意行数,反正计算机不费纸,考虑炫技的都是新手,写多了你就知道,当年自己挖的坑都得自己埋,写得太隐晦了还没注释,以后自己看都会骂自己蠢
    guyeu
        5
    guyeu  
       2019-09-24 10:11:01 +08:00
    你这个解决方案挺好的呀
    12tall
        6
    12tall  
    OP
       2019-09-24 10:11:10 +08:00
    @pkookp8 @xpfd 但是 if...else...嵌套四五层的话,会眼花缭乱的啊~
    richangfan
        7
    richangfan  
       2019-09-24 10:20:47 +08:00
    设置环境变量
    12tall
        8
    12tall  
    OP
       2019-09-24 10:23:21 +08:00
    @guyeu 谢谢,但还是感觉有点怪怪的,大概是因为没有验证过吧。犹豫就会败北~~~
    12tall
        9
    12tall  
    OP
       2019-09-24 10:24:15 +08:00
    @richangfan 能否详细介绍下,谢谢!
    guyeu
        10
    guyeu  
       2019-09-24 10:27:52 +08:00
    @12tall #8 这种操作叫位掩码,并不是你的独创。。
    shylockhg
        11
    shylockhg  
       2019-09-24 10:30:14 +08:00
    写个结构体,写进结构体里
    12tall
        12
    12tall  
    OP
       2019-09-24 10:34:09 +08:00
    @guyeu 学习了,掩码,谢谢大佬!
    richangfan
        13
    richangfan  
       2019-09-24 10:47:11 +08:00
    @12tall 《 UNIX 环境高级编程》这本操作系统入门书有写
    guyeu
        14
    guyeu  
       2019-09-24 10:52:36 +08:00
    @12tall #12 位掩码,bitmask
    imagecap
        15
    imagecap  
       2019-09-24 10:58:17 +08:00
    定义个参数的 class, 先用 getopt 把参数解析好,让后再根据执行的自己的逻辑代码。
    class arguments
    {
    public:
    bool parse( int argc, char* argv[]) {
    // getop
    }

    public:
    std::string name;
    int age;
    bool sex;
    }



    int main( int argc, char* argv[] )
    {
    arguments args;
    if( !args.parse( argc, argv ) )
    return -1;

    if( args.age > 20 )
    {
    ...
    }
    else
    {

    }


    return 0;
    }
    12tall
        16
    12tall  
    OP
       2019-09-24 11:00:50 +08:00
    @shylockhg @wayixia 谢谢啊!
    skydev
        17
    skydev  
       2019-09-24 11:54:07 +08:00
    用 args.hxx 吧,像 python 的 argsparse 一样。Github 搜一下
    12tall
        18
    12tall  
    OP
       2019-09-24 12:33:05 +08:00
    @skydev 谢谢啦
    xpfd
        19
    xpfd  
       2019-09-24 18:02:39 +08:00
    @12tall 怎么会眼花缭乱? 一个 if 一种情况啊 多简洁明了
    xpfd
        20
    xpfd  
       2019-09-24 18:11:33 +08:00
    你后面的这种写法只适用于 进来的参数都比较统一 变化不大的情况 处理函数的参数也都单一的情况,如果进来的参数五花八门 处理函数返回值 还有参数要求也不一样的情况就难受了
    superalsrk
        21
    superalsrk  
       2019-09-24 18:18:43 +08:00
    同 17L, 几乎每个语言都有类似 argsparse 的东西, 几乎都算是一个标准了
    tommyZZM
        22
    tommyZZM  
       2019-09-24 18:51:53 +08:00
    有解析的库的,引用一下就好了
    类似这种 https://github.com/vietjtnguyen/argagg,C++
    12tall
        23
    12tall  
    OP
       2019-09-24 19:22:36 +08:00
    @xpfd
    @superalsrk
    @tommyZZM

    感谢各位大佬啊,还是自己水平不够吧,第一版就是用的 ifelse 结果把自己绕进去了,还要再继续努力啊
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1989 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 16:18 · PVG 00:18 · LAX 08:18 · JFK 11:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.