最近在学习《Unix网络编程》vol2时,发现书中例子经常使用一个命令行解析getopt函数,因为函数声明比较特别,根据自己摸索,遂总结出使用方法。
该函数是由Unix标准库提供的函数,查看命令man 3 getopt
#include
int getopt(int argc, char * const argv[], const char *optstring);
extern char *optarg;
extern int optind, opterr, optopt;
getopt函数的参数:
外部变量:
根据下面的程序理解这四个参数:
在man 3 getopt
给出了该函数的例子
#include
#include
#include
#include
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("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;
}
运行结果:
➜ 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