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

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

1、手动解析版本

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#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函数完成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/**
解析命令选项示例
#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 周日