由库代劳

很多程序都会使用命令行选项,因此有一个专门的库函数,可以用它来简化处理过程。这个库函数叫getopt(),每一次调用都会返回命令行中下一个参数。

看一下它是怎么工作的,假设程序能够接收一组不同的选项:

由库代劳 - 图1

由库代劳 - 图2C标准礼貌指南

unistd.h头文件不属于C标准库,而是POSIX库中的一员。POSIX的目标是创建一套能够在所有主流操作系统上使用的函数。

程序需要两个选项,一个选项接收值,-e代表“引擎”;另一个选项代表了-a代表“无敌模式”。可以循环调用getopt()来处理这两个选项,像这样:

由库代劳 - 图3

在循环中,用switch语句处理每个有效选项。字符串ae:告诉getopt()函数“ae是有效选项”,e后面的冒号表示“-e后面需要再跟一个参数”,getopt()会用optarg变量指向这个参数。

循环结束以后,为了让程序读取命令行参数,需要调整一下argvargc变量,跳过所有选项,最后argv数组将变成这样:

由库代劳 - 图4

由库代劳 - 图5

经过一番处理,0号参数不再是程序名了。

argv[0]会指向选项后的第一个命令行参数。

由库代劳 - 图6披萨拼图

有人偷吃了我们的代码披萨,你能补全披萨并复原order_pizza程序吗?

由库代劳 - 图7

由库代劳 - 图8披萨拼图解答

有人偷吃了我们的代码披萨,请补全披萨并复原order_pizza程序。

由库代劳 - 图9

由库代劳 - 图10试驾

现在就试试“点披萨”程序吧:

由库代劳 - 图11

程序正确运行了!

好啦,这一章你学了不少东西,不但深入理解了标准输入、标准输出和标准错误,而且学会了使用重定向和自己创建的数据流读写文件。最后,还学会了处理命令行参数和选项。

C程序员不是在创造小工具,就是在创造小工具的路上,Linux中大部分小工具都是用C语言写的。精心设计小工具,确保它们做一件事并把它做好。假以时日,你就能成为一名卓越的C程序员。

这里没有蠢问题

问:我能合并两个选项吗?例如用-td now代替-d now –t

:可以,getopt()函数会全权处理它们。

问:我可以改变选项之间的顺序吗?

:可以,因为我们用循环读取选项,所以-d now -t-t -d now-td now都一样。

问:也就是说,只要程序在命令行看到一个前缀为-值,就会把它当成选项处理?

:是的,前提是它必须在命令行参数之前出现。

问:如果我想在命令行参数使用负数怎么办?像set_temperature -c -4,程序会把4当作选项吗?

:为了避免歧义,可以用--隔开参数和选项,比如set_temperature -c -- -4getopt()看到—就会停止读取选项,程序会把后面的内容当成普通的命令行参数读取。

 

由库代劳 - 图12要点

  • main()函数有两个版本,一个有命令行参数,一个没有。

  • 命令行参数通过两个变量传递给main()函数,一个是参数的计数,另一个是指针(指向参数字符串)数组。

  • 命令行选项是以“-”开头的命令行参数。

  • getopt()函数会帮助你处理命令行选项。

  • 为了定义有效的选项,可以传给getopt()一个字符串,例如ae:

  • 选项之后的 “:”(冒号)表示该选项需要接收一个参数。

  • getopt()会用optarg变量记录选项参数。

  • 读取完全部的选项以后,应该用optind变量跳过它们。