一、定义:
#include <unistd.h>
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
getopt 参数说明:
- argc:通常由 main 函数直接传入,表示参数的数量
- argv:通常也由 main 函数直接传入,表示参数的字符串变量数组
- optstring:一个包含正确的参数选项字符串,用于参数的解析。例如 “abc:”,其中 -a,-b 就表示两个普通选项,-c
表示一个必须有参数的选项,因为它后面有一个冒号
外部变量说明:
- optarg:如果某个选项有参数,这包含当前选项的参数字符串
- optind:argv 的当前索引值
- opterr:正常运行状态下为 0。非零时表示存在无效选项或者缺少选项参数,并输出其错误信息
- optopt:当发现无效选项字符时,即 getopt() 方法返回 ? 字符,optopt 中包含的就是发现的无效选项字符
二、分析
让我们通过一系列的实例来掌握 getopt 方法的使用吧。
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int o;
const char *optstring = "abc:"; // 有三个选项-abc,其中c选项后有冒号,所以后面必须有参数
while ((o = getopt(argc, argv, optstring)) != -1) {
switch (o) {
case 'a':
printf("opt is a, oprarg is: %s\n", optarg);
break;
case 'b':
printf("opt is b, oprarg is: %s\n", optarg);
break;
case 'c':
printf("opt is c, oprarg is: %s\n", optarg);
break;
case '?':
printf("error optopt: %c\n", optopt);
printf("error opterr: %d\n", opterr);
break;
}
}
return 0;
}
分析:
命令 gcc OptDemo.c -o OptDemo 是使用 gcc 把 OptDemo.c 编译成可执行程序,命名为 OptDemo
第一次运行 ./OptDemo -a -b -c afei 正常执行和输出
第二次运行 ./OptDemo -abc 由于选项 c 后没有输入参数,于是报错
第三次运行 ./OptDemo -d 由于选项 d 不是我们在 optstring 中预定义的选项,于是报错
2. 可选参数
#include <stdio.h>
#include <unistd.h>
void usage() {
printf("Usage:\n");
printf("\tOptDemo [-a] [-b] [-c message]");
}
int main(int argc, char *argv[]) {
int o;
const char *optstring = "abc::"; // 有三个选项-abc,其中c选项后有两个冒号,表示后面可选参数
while ((o = getopt(argc, argv, optstring)) != -1) {
switch (o) {
case 'a':
printf("opt is a, oprarg is: %s\n", optarg);
break;
case 'b':
printf("opt is b, oprarg is: %s\n", optarg);
break;
case 'c':
printf("opt is c, oprarg is: %s\n", optarg);
break;
case '?':
printf("发生错误时提示用户正确的使用方式\n");
usage(); // 提示使用说明
break;
}
}
return 0;
}
分析:
注意这里 可选参数 选项 -c 后面跟参数的时候,一定不能有空格。
但是如果是 必选参数,即选项后面只有一个冒号,则是有没有空格都可以。
三、getopt_long
#include <unistd.h>
extern char *optarg;
extern int optind, opterr, optopt;
#include <getopt.h>
int getopt(int argc, char * const argv[],const char *optstring);
int getopt_long(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
int getopt_long_only(int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex);
1、参数说明
前三个参数和getopt
的参数相同,主要将第四个和第五个参数
longopts:表示长选项结构体。结构如下:
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
eg:
static struct option longOpts[] = {
{ "daemon", no_argument, NULL, 'D' },
{ "dir", required_argument, NULL, 'd' },
{ "out", required_argument, NULL, 'o' },
{ "log", required_argument, NULL, 'l' },
{ "split", required_argument, NULL, 's' },
{ "http-proxy", required_argument, &lopt, 1 },
{ "http-user", required_argument, &lopt, 2 },
{ "http-passwd", required_argument, &lopt, 3 },
{ "http-proxy-user", required_argument, &lopt, 4 },
{ "http-proxy-passwd", required_argument, &lopt, 5 },
{ "http-auth-scheme", required_argument, &lopt, 6 },
{ "version", no_argument, NULL, 'v' },
{ "help", no_argument, NULL, 'h' },
{ 0, 0, 0, 0 }
};
(1)name:表示选项的名称,比如daemon,dir,out等。
(2)has_arg:表示选项后面是否携带参数。该参数有三个不同值,如下:
a: no_argument(或者是0)时 ——参数后面不跟参数值,eg: --version,--help
b: required_argument(或者是1)时 ——参数输入格式为:--参数 值 或者 --参数=值。eg:--dir=/home
c: optional_argument(或者是2)时 ——参数输入格式只能为:--参数=值
(3)flag:这个参数有两个意思,空或者非空。
a:如果参数为空NULL,那么当选中某个长选项的时候,getopt_long将返回val值。
eg,可执行程序 --help,getopt_long的返回值为h.
b:如果参数不为空,那么当选中某个长选项的时候,getopt_long将返回0,并且将flag指针参数指向val值。
eg: 可执行程序 --http-proxy=127.0.0.1:80 那么getopt_long返回值为0,并且lopt值为1。
(4)val:表示指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值val。
longindex:longindex非空,它指向的变量将记录当前找到参数符合longopts里的第几个元素的描述,即是longopts的下标值。
测试
#include <stdio.h> /* for printf */
#include <stdlib.h> /* for exit */
#include <getopt.h>
int
main(int argc, char **argv)
{
int c;
int digit_optind = 0;
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
static struct option long_options[] = {
{"add", required_argument, 0, 0 },
{"append", no_argument, 0, 0 },
{"delete", required_argument, 0, 0 },
{"verbose", no_argument, 0, 0 },
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 0 },
{0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "abc:d:012",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
break;
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf("option %c\n", c);
break;
case 'a':
printf("option a\n");
break;
case 'b':
printf("option b\n");
break;
case 'c':
printf("option c with value '%s'\n", optarg);
break;
case 'd':
printf("option d with value '%s'\n", optarg);
break;
case '?':
break;
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
exit(EXIT_SUCCESS);
}