13.7.6 命令行参数
很多时候,程序都要求用户在终端输入少量信息。这些信息可能包含一些数字,它们表示你想要计算的三角数或者是想要在字典中查询的单词。
除了让程序请求用户输入相关信息,还可以在程序执行时给该程序提供信息。这种能力是由命令行参数提供的。
我们提到过main函数唯一的与众不同之处在于它的名称很特别:它指明了程序开始执行的位置。事实上,main函数是在程序开始执行时,由运行时系统调用,就像在自己的程序中调用函数一样。当main执行完毕时,控制权返回给运行的系统,这样系统便知道程序已经执行完毕了。
当运行时系统调用main函数时,系统向该函数传递两个参数。第一个参数,按照规定称为argc(argument count的简写),是一个整型值,它指明了从命令行键入的参数个数。第二个传递给main的参数是一个字符指针数组,按照规定称为argv(argument vector的简写)。另外,这个数组中包含argc+1个字符指针。该数组的第一个元素是执行程序的名称指针,如果你的系统中没有程序名称,则是空串。数组的其他项指向由启动程序执行的命令行所指定的值。数组argv中的最后一个指针argv[argc]规定为空。
要访问命令行参数,必须将main函数适当地声明为带有两个参数。使用本书所有程序中用到的惯例声明就可以了,如下所示:
int main(int argc, char*argv[])
{
……
}
记住,argv的声明定义了一个包含“char指针”类型元素的数组。命令行参数的一个实际用途是,假设你开发了一个程序,它在字典中查询某个单词并显示单词的含义,那么可以使用命令行参数,这样在执行程序同时就可以指定想要查找含义的单词,如以下命令所示:
lookup aerie
这就不必提示用户键入一个单词,因为单词已经从命令行键入了。
如果执行上面的命令,那么系统自动向main函数传递argv[1]中字符串“aerie”的指针。你可能会想起,argv[0]包含的是指向程序名称的指针,在这个例子中是“lookup”。
main函数可能如下所示:
include<Foundation/Foundation.h>
int main(int argc, char*argv[])
{
struct entry dictionary[100]=
{{“aardvark”,“a burrowing African mammal”},
{“abyss”,“a bottomless pit”},
{“acumen”,“mentally sharp;keen”},
{“addle”,“to become confused”},
{“aerie”,“a high nest”},
{“affix”,“to append;attach”},
{“agar”,“a jelly made from seaweed”},
{“ahoy”,“a nautical call of greeting”},
{“aigrette”,“an ornamental cluster of feathers”},
{“ajar”,“partially opened”}};
int entries=10;
int entryNumber;
int lookup(struct entry dictionary[],char search[],
int entries);
if(argc!=2)
{
NSLog(@“No word typed on the command line.”);
return(1);
}
entryNumber=lookup(dictionary, argv[1],entries);
if(entryNumber!=-1)
NSLog(@“s”,dictionary[entryNumber].definition);
else
NSLog(@“Sorry,%s is not in my dictionary.”,argv[1]);
return(0);
}
执行程序时,main例程测试以确保在程序名称之后键入一个单词。如果没有,或键入了多个单词,那么argc的数值将不等于2。在这种情况下,程序将写明出错消息并终止运行,返回终止状态1。
如果argc等于2,将调用函数lookup,在字典中寻找argv[1]指向的单词。如果找到了该单词,则显示它的定义。
需要记住命令行参数总是存储为字符串。所以,带有命令行参数2和16的power程序:
power 2 16
的执行结果是将字符串“2”的指针保存在argv[1]中,将字符串“16”的指针保存在argv[2]。如果程序将参数解释为数字(就像我们猜想程序power一样),程序本身必须转换它。程序库中有一些例程可以用来实现这种转换,如sscanf、atof、atoi、strtod和strtol。在第二部分中,将学习如何使用名为NSProcessInfo的类来以字符串对象而不是C字符串的形式访问命令行参数。