当前位置: 首页 > 我的程序代码 > 正文

Linux C代码实现主函数参数选项解析

软件开发中难免会对命令行输入参数做解析、判断。本文给出2个此方面的示例。

1、手动解析版本

思路十分简单,使用argc、argv,逐个字符比较,得到要想的参数名字即进行判断、解析。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int debug;

void show_version(char* name)
{
    printf("%s by Late Lee, version: 1.0\n", name);
}

void usage(char* name)
{
    show_version(name);

    printf("         -h,  --help           short help\n");
    printf("         -v,  --version        show version\n");
}

int main(int argc, char *argv[])
{
    int i = 0;

    /* early check for debug and config parameter */
    if (argc > 1) {
        for (i = 1; i < argc; i++)
        {
            if ((strcmp(argv[i], "-D")==0) || (strcmp(argv[i], "--debug")==0))
            {
                debug = 1;
            }
        }
    }
    
    // 
    /* parse parameters, maybe not the best way but... */
    for (i = 1; i < argc; i++)
    {
        if (debug)
            printf("arg %d: \"%s\"\n",i,argv[i]);
        // help
        if ((strcmp(argv[i],"-h")==0) || (strcmp(argv[i],"--help")==0))
        {
            usage(argv[0]);
            return 0;
        }
        // version
        else if ((strcmp(argv[i],"-v")==0) || (strcmp(argv[i],"--version")==0))
        {
            show_version(argv[0]);
            return 0;
        }
        // debug
        else if ((strcmp(argv[i],"-D")==0) || (strcmp(argv[i],"--debug")==0))
        {
            debug=1;
        } 
        else if ((strcmp(argv[i],"fpga")==0))
        {
            printf("test of fpga...\n");
        }
        // string
        else if ((strcmp(argv[i],"-i")==0) || (strcmp(argv[i],"--iface")==0))
        {
            if (i+1<argc)
            {
                char interface[32] = {0};
                strncpy(interface, argv[i+1], 32);
                if (debug)
                    printf("Used interface: %s\n", interface);
                i++;
                continue;
            } else {
                printf("Error: Interface for -i missing.\n");
                return 1;
            }
        }
        // number
        else if ((strcmp(argv[i],"-ru")==0) || (strcmp(argv[i],"--rateunit"))==0)
        {
            if (i+1<argc && isdigit(argv[i+1][0])) {
                int rateunit = 0;
                rateunit = atoi(argv[i+1]);
                if (rateunit < 0 || rateunit > 1)
                {
                    printf("Error: Invalid parameter \"%d\" for --rateunit.\n", rateunit);
                    printf(" Valid parameters:\n");
                    printf("    0 - bytes\n");
                    printf("    1 - bits\n");
                    return 1;
                }
                if (debug)
                    printf("Rateunit changed: %d\n", rateunit);
                i++;
                continue;
            }
            else
            {
            }
        }
        // only one
        else if (strcmp(argv[i],"--enable")==0)
        {
            int enable = 0;
            enable = 1;
        }
        else
        {
            printf("Unknown parameter \"%s\". Use --help for help.\n",argv[i]);
            return 1;
        }
    }
}

2、利用getopt函数完成

/**
解析命令选项示例

#include <unistd.h>
extern char *optarg;   //选项的参数指针
extern int optind,    //下一次调用getopt的时,从optind存储的位置处重新开始检查选项。 
extern int opterr,   //当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt;   //当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt中,getopt返回'?’
int getopt(int argc, char * const argv[], const char *optstring);

使用:
$ ./a.out -Wall -o hello.c

*/
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>

int debug_level = 0;

#define _AUTHOR "Late Lee"
#define _VERSION_STR "1.0"
#define _DATE ""

// 默认打印error等级
enum
{
    MSG_ERROR = 0,
    MSG_WARNING,
    MSG_INFO,
    MSG_DEBUG,
    MSG_MSGDUMP,
    MSG_EXCESSIVE, 
};

void ll_printf(int level, const char *fmt, ...) __attribute__ ((format (printf, 2, 3)));

void ll_printf(int level, const char *fmt, ...)
{
    va_list ap;

    va_start(ap, fmt);
    if (debug_level >= level)
    {
#ifdef CONFIG_DEBUG_SYSLOG
        if (wpa_debug_syslog) {
            vsyslog(syslog_priority(level), fmt, ap);
        } else {
#endif /* CONFIG_DEBUG_SYSLOG */
        //debug_print_timestamp();
#ifdef CONFIG_DEBUG_FILE
        if (out_file) {
            vfprintf(out_file, fmt, ap);
            fprintf(out_file, "\n");
        } else {
#endif /* CONFIG_DEBUG_FILE */
        vprintf(fmt, ap);
        printf("\n");
#ifdef CONFIG_DEBUG_FILE
        }
#endif /* CONFIG_DEBUG_FILE */
#ifdef CONFIG_DEBUG_SYSLOG
        }
#endif /* CONFIG_DEBUG_SYSLOG */
    }
    va_end(ap);
}

void show_version(char* name)
{
    printf("%s by %s, version: %s\n", name, _AUTHOR, _VERSION_STR);
}

void usage(char* name)
{
    show_version(name);

    printf("    -h,    short help\n");
    printf("    -v,    show version\n");
    printf("    -d,    debug level\n");
    
    exit(0);
}

const char* my_opt = "hOo:W:d:";

int main(int argc, char *argv[])
{
    int c;
    const char* p1 = NULL;
    const char* p2 = NULL;
    const char* p3 = NULL;
    while(1)
    {
        c = getopt(argc, argv, my_opt);
        printf("optind: %d\n", optind);
        if (c < 0)
        {
            break;
        }
        printf("option char: %x %c\n", c, c);
        switch(c)
        {
        case 'd':
                debug_level = atoi(optarg);
                printf("debug level: %d\n", debug_level);
                break;
        case 'O':
                printf("optimization flag is open.\n\n");
                break;
        case 'o':
                printf("the obj is: %s\n\n", optarg);
                p1 = optarg;
                break;
        case 'W':
                printf("optarg: %s\n\n", optarg);
                p2 = optarg;
                break;
        case ':':
                fprintf(stderr, "miss option char in optstring.\n");
                break;
        case '?':
        case 'h':
        default:
                usage(argv[0]);
                break;
                //return 0;
        }
    }
    if (optind == 1)
    {
        usage(argv[0]);
    }
    
    ll_printf(MSG_ERROR, "p1: %s p2: %s\n", p1, p2);
    
    return 0;
}

 

李迟 2016.8.21 周日

本文固定链接: http://www.latelee.org/my-library/linux-c-parse-main-arguments.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: Linux C代码实现主函数参数选项解析 | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter