由库代劳
很多程序都会使用命令行选项,因此有一个专门的库函数,可以用它来简化处理过程。这个库函数叫getopt()
,每一次调用都会返回命令行中下一个参数。
看一下它是怎么工作的,假设程序能够接收一组不同的选项:
C标准礼貌指南
unistd.h头文件不属于C标准库,而是POSIX库中的一员。POSIX的目标是创建一套能够在所有主流操作系统上使用的函数。
程序需要两个选项,一个选项接收值,-e
代表“引擎”;另一个选项代表了开或关,-a
代表“无敌模式”。可以循环调用getopt()
来处理这两个选项,像这样:
在循环中,用switch
语句处理每个有效选项。字符串ae:
告诉getopt()
函数“a
和e
是有效选项”,e
后面的冒号表示“-e
后面需要再跟一个参数”,getopt()
会用optarg
变量指向这个参数。
循环结束以后,为了让程序读取命令行参数,需要调整一下argv
和argc
变量,跳过所有选项,最后argv
数组将变成这样:
经过一番处理,0号参数不再是程序名了。
argv[0]
会指向选项后的第一个命令行参数。
披萨拼图
有人偷吃了我们的代码披萨,你能补全披萨并复原order_pizza
程序吗?
披萨拼图解答
有人偷吃了我们的代码披萨,请补全披萨并复原order_pizza
程序。
试驾
现在就试试“点披萨”程序吧:
程序正确运行了!
好啦,这一章你学了不少东西,不但深入理解了标准输入、标准输出和标准错误,而且学会了使用重定向和自己创建的数据流读写文件。最后,还学会了处理命令行参数和选项。
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 -- -4
。getopt()
看到—就会停止读取选项,程序会把后面的内容当成普通的命令行参数读取。
要点
main()
函数有两个版本,一个有命令行参数,一个没有。命令行参数通过两个变量传递给
main()
函数,一个是参数的计数,另一个是指针(指向参数字符串)数组。命令行选项是以“
-
”开头的命令行参数。
getopt()
函数会帮助你处理命令行选项。为了定义有效的选项,可以传给
getopt()
一个字符串,例如ae:
。选项之后的 “:”(冒号)表示该选项需要接收一个参数。
getopt()
会用optarg
变量记录选项参数。读取完全部的选项以后,应该用
optind
变量跳过它们。