C++ primer plus 第17 章 输入、输出和文件:文件输入和输出02:流状态检查和is_open():打开多个文件:命令行处理技术

C++ primer plus 第17 章 输入、输出和文件:文件输入和输出01

17.4.2 流状态检查和is_open()

17.4.3 打开多个文件

17.4.4命令行处理技术

程序清单17.17 count.cpp


提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档


17.4.2 流状态检查和is open()

C++文件流类从iosbase 类那里继承了一个流状态成员。正如前面指出的,该成员存储了指出流状态的信息:一切顺利、已到达文件尾、I/0 操作失败等。如果一切顺利,则流状态为零(没有消息就是好消息)。其他状态都是通过将特定位设置为1来记录的。文件流类还继承了iosbase 类中报告流状态的方法,表17.4对这些方法进行了总结。可以通过检查流状态来判断最后一个流操作是否成功。对于文件流,这包括检查试图打开文件时是否成功。例如,试图打开一个不存在的文件进行输入时,将设置ilbit位,因此可以这样进行检查:

fin.open(argv[file]):
if (fin.fail())// open attempt failed
{
...
}

由于 ifstrcam 对象和 istrcam 对象一样,被放在需要 bool类型的地方时,将被转换为 bool值,因此您也可以这样做:

fin.open(argvlfile]);
if (!fin)//open attempt failed
{
...
}


然而,较新的C++实现提供了一种更好的检查文件是否被打开的方法–is_open()方法:

if(!fin.is open())//open attempt failed
{
...
}

这种方式之所以更好,是因为它能够检测出其他方式不能检测出的微妙问题,接下来的“警告”将讨论这一点。
警告:以前,检查文件是否成功打开的常见方式如下:

if(fin.fail())...// failed to open
if(!fin.good())...// failed to open
if (!fin)...

//failed to openfin 对象被用于测试条件中时,如果 fin.good()为fàlsc,将被转换为falsc;否则将被转换为 tnue。因此上面三种方式等价。然而,这些测试无法检测到这样一种情形:试图以不合适的文件模式(参见本章后面的“文件模式”一节)打开文件时失败。方法is_open( )能够检测到这种错误以及 good()能够检测到的错误然而,老式C++实现没有is_open()。

17.4.3 打开多个文件

程序可能需要打开多个文件。打开多个文件的策略取决于它们将被如何使用。如果需要同时打开两个文件,则必须为每个文件创建一个流。例如,将两个排序后的文件拼接成第三个文件的程序,需要为两个输入文件创建两个 ifstream 对象,并为输出文件创建一个 ofstream 对象。可以同时打开的文件数取决于操
作系统。然而,可能要依次处理一组文件。例如,可能要计算某个名称在10个文件中出现的次数。在这种情况下,可以打开一个流,并将它依次关联到各个文件。这在节省计算机资源方面,比为每个文件打开一个流的效率高。使用这种方法,首先需要声明一个istream对象(不对它进行初始化),然后使用 open( )方法将这个流与文件关联起来。例如,下面是依次读取两个文件的代码:

ifstream fin;//ereate stream using default construetor
fin.open("fat.txt");//associate stream with fat.txt file
...
fin.close();//terminate association with fat.txt
fin.clear();//reset fin (may not be needed)
fin.open("rat.txt”);//associate stream with rat.txt file
...// do stuff
...
fin.close();

稍后将介绍一个例子,但先来看这样一种将一系列文件输入给程序的技术,即让程序能够使用循环来处理文件。

17.4.4命令行处理技术

文件处理程序通常使用命令行参数来指定文件。命令行参数是用户在输入命令时,在命令行中输入的参数。例如,要在UNIX或Linux系统中计算文件包含的字数,可以在命令行提示符下输入下面的命令:
wc reportl report2 report3其中,wc是程序名,report1、report2和report3 是作为命令行参数传递给程序的文件名。C++有一种让在命令行环境中运行的程序能够访问命令行参数的机制,方法是使用下面的main()函数:

int main(int argc,char *argv])

argc为命令行中的参数个数,其中包括命令名本身。argv变量为一个指针,它指向一个指向char 的指针。这过于抽象,但可以将 argv看作一个指针数组,其中的指针指向命令行参数,argv[0]是一个指针,指向存储第一个命令行参数的字符串的第一个字符,依此类推。也就是说,argv[0]是命令行中的第一个字符串,依此类推。例如,假设有下面的命令行:
we reportl report2 report3
则argc为4,argv[0]为wc,argv[1]为reportl,依此类推。下面的循环将把每个命令行参数分别打印在单独一行上:

for (int i=l;i < argc; i++)
cout << argvli]<< endl;

以i-1开头将只打印命令行参数:以i=0开头将同时打印命令名。当然,命令行参数与命令行操作系统(如 Windows命令提示符模式、UNIX和Linux)紧密相关。其他程序也可能允许使用命令行参数。
很多 WindowsIDE(集成开发环境)都有一个提供命令行参数的选项。通常,必须选择一系列菜单,才能打开一个可以输入命令行参数的对话框。具体的步骤随厂商和升级版本而异,因此请查看文档。
很多 WindowsIDE都可以生成可执行文件,这些文件能够在 Windows 命令提示符模式下运行。
程序清单 17.17结合使用命令行技术和文件流技术,来计算命令行上列出的文件包含的字符数。

程序清单17.17 count.cpp

// count.cpp -- counting characters in a list of files
#include <iostream>
#include <fstream>
#include <cstdlib>          // or stdlib.h
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; 
}

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值