最近在学习《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