在图形界面普及之前都使用命令行界面。DOS和UNIX就是例子。Linux终端提供类UNIX命令行环境。命令行(command-line)是在命令行环境中,用户为运行程序输入命令的行。假设一个文件中有一个名为fuss的程序。在UNIX环境中运行该程序的命令行是:
$ fuss
或者在Windows命令提示模式下是:
C> fuss
命令行参数(command-line argument)是同一行的附加项。如下例:
$ fuss -r Ginger
一个C程序可以读取并使用这些附加项(见图11.7)。
程序repeat.c是一个典型的例子,该程序通过main()的参数读取这些附加项。
/* repeat.c -- main() with arguments */#include int main(int argc, char *argv[]){ int count; printf("The command line has %d arguments:n", argc - 1); for (count = 1; count < argc; count++) printf("%d: %sn", count, argv[count]); printf("n"); return 0;}
把该程序编译为可执行文件repeat。下面是通过命令行运行该程序后的输出:
C>repeat Resistance is futileThe command line has 3 arguments:1: Resistance2: is3: futile
由此可见该程序为何名为repeat。下面我们解释一下它的运行原理。
C编译器允许main()没有参数或者有两个参数(一些实现允许main()有更多参数,属于对标准的扩展)。main()有两个参数时,第1个参数是命令行中的字符串数量。过去,这个int类型的参数被称为argc(表示参数计数(argument count))。系统用空格表示一个字符串的结束和下一个字符串的开始。因此,上面的repeat示例中包括命令名共有4个字符串,其中后3个供repeat使用。该程序把命令行字符串存储在内存中,并把每个字符串的地址存储在指针数组中。而该数组的地址则被存储在main()的第2个参数中。按照惯例,这个指向指针的指针称为argv(表示参数值[argument value])。如果系统允许(一些操作系统不允许这样),就把程序本身的名称赋给argv[0],然后把随后的第1个字符串赋给argv[1],以此类推。在我们的例子中,有下面的关系:
argv[0] points to repeat (for most systems)argv[1] points to Resistanceargv[2] points to isnargv[3] points to futile
程序清单11.31的程序通过一个for循环依次打印每个字符串。printf()中的%s转换说明表明,要提供一个字符串的地址作为参数,而指针数组中的每个元素(argv[0]、argv[1]等)都是这样的地址。
main()中的形参形式与其他带形参的函数相同。许多程序员用不同的形式声明argv:
int main(int argc, char **argv)
char **argv与char *argv[]等价。也就是说,argv是一个指向指针的指针,它所指向的指针指向char。因此,即使在原始定义中,argv也是指向指针(该指针指向char)的指针。两种形式都可以使用,但我们认为第1种形式更清楚地表明argv表示一系列字符串。
顺带一提,许多环境(包括UNIX和DOS)都允许用双引号把多个单词括起来形成一个参数。例如:
repeat "I am hungry" now
这行命令把字符串"I am hungry"赋给argv[1],把"now"赋给argv[2]。