软件开发中难免会对命令行输入参数做解析、判断。本文给出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 周日