#include <unistd.h>
int getopt(int argc, char * const argv[],
const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
#include <getopt.h>
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);
getopt() : _POSIX_C_SOURCE >= 2 || _XOPEN_SOURCE
getopt_long(), getopt_long_only() : _GNU_SOURCE
getopt 用于解析命令行参数,如 -a -t -s0 等等
optstring中后面的冒号表示需要接变量,并存于optarg中。如果接二个冒号,则表示变量可有可无。
一个: 要加内容 有无空格都行
两个: 可加可不加内容 如果加内容 中间不要有空格
扫描模式:
1. 如果第一个字符为加号: 停止于发现第一个非选项
2. 如果第一个字符为减号:全部扫描;此为默认模式。
碰到'--',则忽略扫描模式,必须停止扫描。
返回值:
成功,返回option;
结束,返回-1;
发现不认识的option,返回?号
碰到option后面缺参数,则返回?号。
或返回:号(optstring中第一个字符(如果有加减号,在加减号后面)为冒号时返回,即为:或+:或-:)。
返回值:
如果找到了一个选项,那么getopt()返回选项字符。如果所有命令行选项都已被解析,那么getopt()返回-1。如果getopt()遇到一个非optstring中的选项字符,则返回‘?’。如果getopt()遇到一个缺少参数的选项,则返回值取决于optstring中的第一个字符:如果它是‘:’,那么‘:’返回;否则返回‘?’.
getopt_long()和getopt_long_only()也返回在识别短选项时的选项字符。对于长选项,它们返回Val if标志为NULL,否则返回0。错误和-1返回与getopt()相同,加上“?”用于模糊匹配。或者是无关的Parame-ter
外部参数:
char *optarg:如果有参数,则包含当前选项参数字符串
int optind:argv的当前索引值。当getopt函数在while循环中使用时,剩下的字符串为操作数,下标从optind到argc-1。
int opterr:这个变量非零时,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。
int optopt:当发现无效选项字符之时,getopt()函数或返回 \’ ? \’ 字符,或返回字符 \’ : \’ ,并且optopt包含了所发现的无效选项字符。
根据下面的程序理解这四个参数:
在man 3 getopt
给出了该函数的例子
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int flags = 0, opt;
int nsecs = 0, tfnd = 0;
while((opt = getopt(argc, argv, "nt:")) != -1) {
switch (opt) {
case 'n':
flags = 1;
break;
case 't':
nsecs = atoi(optarg);
tfnd = 1;
break;
default:
printf("optind = %d\n", optind);
printf("optopt = %c\n", (char)optopt);
printf("opterr = %d\n", opterr);
fprintf(stderr, "usage: %s [-t nsecs] [-n] name\n", argv[0]);
exit(EXIT_FAILURE);
}
}
printf("flags = %d; tfnd = %d; nsecs = %d; optind = %d\n", flags, tfnd, nsecs, optind);
printf("optind = %d\n", optind);
printf("argc = %d\n", argc);
#if 1
if(optind >= argc) {
fprintf(stderr, "Expected argument after options\n");
exit(1);
}
#endif
printf("name argument = %s\n", argv[optind]);
/* Other code omitted */
return 0;
}
- getopt函数的第三个字符串参数 “nt:”:在man page中这样解释:-n, with no associated value; and -t val, which expects an associated value。中文意思为:-n 不用一个关联值;-t 需要有一个关联的value参数。
运行结果:
➜ test ./a.out -a name //首先 -a 是一个非法的选项
./a.out: invalid option -- 'a' //输出错误信息,因为非法选项
optind = 2 //此时argv[optind]是我们的操作数,也就是我们传递给主函数的参数
optopt = a //当发现无效项字符时,optopt会包含该字符,正如我们传递的‘a’这个无效项。
opterr = 1 //opterr变量非零,getopt()函数为“无效选项”和“缺少参数选项,并输出其错误信息。
usage: ./a.out [-t nsecs] [-n] name
再次运行:
➜ test ./a.out -t //根据getopt函数的第三个参数,因为‘t’字符后有‘:’冒号,因此在‘-t’选项后需要跟随一个参数。因此此次运行的错误为“缺少参数”,如下提示:
./a.out: option requires an argument -- 't' //输出了错误信息,因为“缺少参数”
optind = 2 //argv[optind]为空,因为此次运行没有传递参数
optopt = t //当发现无效项字符时,optopt会包含该字符,正如我们传递的‘t’缺少参数的选项。
opterr = 1 //opterr变量非零,getopt()函数为“无效选项”和“缺少参数“选项,并输出其错误信息。
usage: ./a.out [-t nsecs] [-n] name
再次运行:
➜ test ./a.out -t 123 -n //此时,根据字符串”-nt:“应该得知,-t 后应加参数,-n不用加
flags = 1; tfnd = 1; nsecs = 123; optind = 4 //在switch语句中将flags=1,tfnd=1,因为optarg变量保存这当前选项参数的字符串,因此此时optarg保存的是‘-t’参数的参数并用atoi函数转称整数,因此nsecs=123。
optind = 4 //argv[optind]为空,因为没有向主函数传递参数
argc = 4 //一共四个字符串
Expected argument after options //该程序希望我们至少传递一个参数,因此在if语句中退出。
再次运行:
➜ test ./a.out -t 123 -n hello //‘-t’后加参数,‘-n’不用加,向main函数传递参数叫hello
flags = 1; tfnd = 1; nsecs = 123; optind = 4
optind = 4 //argv[optind] = ”hello“
argc = 5 //五个字符串
name argument = hello //打印参数name argument= hello
其实可以传递多个参数(如果需要,因为此函数只打印第一个参数),例如:
➜ test ./a.out -t 123 -n hello world hello C
//optind = 3
//optind = 4
flags = 1; tfnd = 1; nsecs = 123; optind = 4
optind = 4
argc = 8
name argument = hello