11.8 命令行参数

现代的图形界面出现之前是命令行界面。DOS和UNIX就是例子。命令行(command line)是在一个命令行环境下,用户输入的用于运行程序的行。假定有一个程序在名为fuss的文件中,那么在UNIX下运行该程序的命令行如下:

阅读 ‧ 电子书库

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

或者在Windows命令行模式下,如Windows XP命令提示符:

阅读 ‧ 电子书库

命令行参数(command-line argument)是同一行中的附加项。如下例:

阅读 ‧ 电子书库

一个C程序可以读取这些附加项为自己所用(请参见图11.7)。

阅读 ‧ 电子书库

图11.7 命令行参数

C程序通过使用main()的参数读取这些项目。程序清单11.27给出了一个典型例子。

程序清单11.27 repeat.c程序

阅读 ‧ 电子书库

把这个程序编译为可执行文件repeat;下面是从命令行运行该程序的结果:

阅读 ‧ 电子书库

可以看出为什么该程序被称为repeat,但是您可能想知道它是怎么工作的。现在我们解释一下。

C编译器允许main()没有参数,或者有两个参数(有些实现允许更多的参数,但这将是对标准的扩展)。有两个参数时,第一个参数是命令行中的字符串数。按照惯例(但不是必须的),这个int参数被称为argc(代表argument count) 。系统使用空格判断一个字符串结束、另一个字符串开始。因此,repeat例子中包括命令名在内有4个字符串,fuss例子有3个。第二个参数是一个指向字符串的指针数组。命令行中的每个字符串被存储到内存中,并且分配一个指针指向它。按照惯例,这个指针数组被称为argv(代表argument value) 。如果可以(有些操作系统不允许这样做),把程序本身的名字赋值给argv[0]。接着,把随后的第一个字符串赋给argv[1],等等。对于我们的例子,有表11.1所示的关系:

表11.1 main()的第二个参数

 

 

argv[0] 指向 repeat(对于大多数系统)
argv[1] 指向 Resistance
argv[2] 指向 is
argv[3] 指向 futile

程序清单11. 27中的程序使用一个for循环来依次输出每个字符串。回忆一下,printf()的%s说明符需要提供字符串的地址作为参数。每个元素,argv[0],argv[1]等等,正是一个这样的地址。

该形式和有形式参数的其他函数一样。很多程序员使用不同的方式声明argv:

阅读 ‧ 电子书库

这种对argv的声明和char *argv[]等价。它意味着argv是一个指向“指向字符的指针”的指针。示例程序中那种形式的效果也一样。它有一个包含几个元素的数组。数组名是指向第一个元素的指针,因此argv指向argv[0],而argv[0]是一个指向字符的指针。因此,即便在原始的定义中,argv仍是一个指向“指向字符的指针”的指针。两种形式都可以用,但我们认为第一种形式更清楚地表明argv代表一系列字符串。

顺便提一下,很多环境(包括UNIX和DOS)允许使用引号把多个单词集中在一个参数里。例如:

阅读 ‧ 电子书库

这个命令会把字符串“I am hungry”分配给argv[1],把字符串“now”分配给argv[2]。

11.8.1 集成环境下的命令行参数

集成的Windows环境,比如Metrowerks CodeWarrior、Microsoft Visual C++和Borland C/C++,都不使用命令行运行程序。然而,有些环境有菜单选择,可以让您指定命令行参数。其他情况下,您可以在IDE中编译程序,然后打开MS-DOS窗口用命令行模式运行程序。

11.8.2 Macintosh的命令行参数

Macintosh操作系统不使用命令行,但是Metrowerks CodeWarrior允许您用ccommand()函数模拟命令行环境。您可以使用console.h头文件,以如下所示开始程序:

阅读 ‧ 电子书库

当程序到达ccommand()函数调用处时,它就会在屏幕上给出一个对话框,并且提供一个框,您可以在其中键入命令行。然后命令就把命令行单词放到argv字符串里,并且返回单词数。当前的工程名称会作为第一个单词出现在命令行框里,这样您就可以在该名字后键入命令行参数。ccommand()函数还可以模拟重定向。

为什么要在一台Mac上做这个?惟一的理由也许就是练习命令行用法,以备日后需要编写基于命令行的程序。既然Macintosh已经被移到基于UNIX的Mac OS X上,Mac程序员就需要对基于命令行的程序有更深入的了解。