20-命令行处理技术
17.4.4 命令行处理技术
文件处理程序通常使用命令行参数来指定文件。命令行参数是用户在输入命令时,在命令行中输入的参数。例如,要在UNIX或Linux系统中计算文件包含的字数,可以在命令行提示符下输入下面的命令:
wc report1 report2 report3
其中,wc是程序名,report1、report2和report3是作为命令行参数传递给程序的文件名。
C++有一种让在命令行环境中运行的程序能够访问命令行参数的机制,方法是使用下面的main()函数:
int main(int argc, char *argv[])
argc为命令行中的参数个数,其中包括命令名本身。argv变量为一个指针,它指向一个指向char的指针。这过于抽象,但可以将argv看作一个指针数组,其中的指针指向命令行参数,argv[0]是一个指针,指向存储第一个命令行参数的字符串的第一个字符,依此类推。也就是说,argv[0]是命令行中的第一个字符串,依此类推。例如,假设有下面的命令行:
wc report1 report2 report3
则argc为4,argv[0]为wc,argv[1]为report1,依此类推。下面的循环将把每个命令行参数分别打印在单独一行上:
for (int i = 1; i < argc; i++)
cout << argv[i] << endl;
以i=1开头将只打印命令行参数;以i=0开头将同时打印命令名。
当然,命令行参数与命令行操作系统(如Windows命令提示符模式、UNIX和Linux)紧密相关。其他程序也可能允许使用命令行参数。
- 很多Windows IDE(集成开发环境)都有一个提供命令行参数的选项。通常,必须选择一系列菜单,才能打开一个可以输入命令行参数的对话框。具体的步骤随厂商和升级版本而异,因此请查看文档。
- 很多Windows IDE都可以生成可执行文件,这些文件能够在Windows命令提示符模式下运行。
程序清单17.17结合使用命令行技术和文件流技术,来计算命令行上列出的文件包含的字符数。
程序清单17.17 count.cpp
// count.cpp -- counting characters in a list of files
#include <iostream>
#include <fstream>
#include <cstdlib> // for exit()
int main(int argc, char * argv[])
{
using namespace std;
if (argc == 1) // quit if no arguments
{
cerr << "Usage: " << argv[0] << " filename[s]\n";
exit(EXIT_FAILURE);
}
ifstream fin; // open stream
long count;
long total = 0;
char ch;
for (int file = 1; file < argc; file++)
{
fin.open(argv[file]); // connect stream to argv[file]
if (!fin.is_open())
{
cerr << "Could not open " << argv[file] << endl;
fin.clear();
continue;
}
count = 0;
while (fin.get(ch))
count++;
cout << count << " characters in " << argv[file] << endl;
total += count;
fin.clear(); // needed for some implementations
fin.close(); // disconnect file
}
cout << total << " characters in all files\n";
return 0;
}
注意: 有些C++实现要求在该程序末尾使用fin.clear(),有些则不要求,这取决于将文件与ifstream对象关联起来时,是否自动重置流状态。使用fin.clear()是无害的,即使在不必使用它的时候使用。
例如,在Linux系统中,可以将程序清单17.17编译为一个名为a.out的可执行文件。该程序的运行情况如下:
$ a.out
Usage: a.out filename[s]
$ a.out paris rome
3580 characters in paris
4886 characters in rome
8466 characters in all files
$
注意,该程序使用cerr表示错误消息。另外,消息使用argv[0],而不是a.out:
cerr << "Usage: " << argv[0] << " filename[s]\n";
如果修改了可执行文件的名称,则程序将自动使用新的名称。
该程序使用is_open()方法来确定能够打开指定的文件,下面更深入地探讨这一主题。