现代的图形界面出现之前是命令行界面。Dos和Unix就是例子。命令行(command line)是在一个命令行环境下,用户输入的用于运行程序的行。假定有一个程序在名为fuss 的文件中,那么在UNIX下运行该程序的命令行如下:
$ fuss
或者在windows命令行模式下,如windows xp命令提示符:
c> fuss
命令行参数(command-line argument)是同一行中的附加项。如下例:
% fuss -r Ginger
一个C程序可以读取这些附加项为自己所用。
C程序通过使用main()的参数读取这些项目。程序清单11.27给出了一个典型的例子。
程序清单11.27 repeat.c程序
/*repeat.c --带有参数的main()函数*/
#include <stdio.h>
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: %s\n",count,argv[count]);
printf("\n");
return 0;
}
把这个程序编译为可执行文件repeat;下面是从命令行运行该程序的结果:
c>repeat Resistance is futile
The command line has 3 arguments:
1: Resistance
2: is
3: futile
C编译器允许main( )没有参数,或者有两个参数(有些实现允许更多的参数,但这将是对标准的扩展)。有两个参数时,第一个参数是命令行中的字符串数。按照惯例(但不是必须的),这个int参数被称为argc(代表argument count)。系统使用空格判断一个字符串结束、另一个字符串开始。因此,repeat例子中包括命令名在内有4个字符串,fuss例子有3个。第二个参数是一个指向字符串的指针数组。命令行中的每个字符串被存储到内存中,并且分配一个指针指向它。按照惯例,这个指针数组被称为argv(代表argument value)如果可以(有些操作系统不允许这样做),把程序本身的名字赋值给argv[0]。接着把随后的第一个字符串赋给argv[1]。
回忆一下,printf()的%s说明符需要提供字符串的地址作为参数。每个元素,argv[0],argv[1]正是一个这样的地址。
该形式和有形式参数的其他函数一样。很多程序员使用不同的方式声明argv:
int main (int argc,char **argv)
这种对argv的声明和char *argv[]等价。它意味着argv是一个指向“指向字符的指针”的指针。示例程序中那种形式的效果也一样。它有一个包含几个元素的数组。数组名是指向第一个元素的指针,因此argv指向argv[0],而argv[0]是一个指向字符的指针。因此,即便在原始的定义中,argv仍是一个指向“指向字符的指针”的指针。两种形式都可以用,但我们认为第一种形式更清楚地表明argv代表一系列字符串。
顺便提一下,很多环境(包括UNIX和DOS)允许使用引号把多个单词集中在一个参数里。例如:
repeat "I am hungry" now
这个命令会把字符串 "I am hungry" 分配给argv[1],把字符串"now"分配给argv[2]。