c++精解和程序设计第八章

                第八章  流和文件

8.1标准输入/输出流

流:用于程序输入或输出的字符序列。
换行符:把一个流分成一系列行的字符。

8.1.1每次读取一个字符

get函数用于每次读取一个字符。
put函数用于每次显示一个字符。
注意:直到get函数读取标注流结束的文件结束字符以后,eof函数才会返回真值。

例子:处理流中的各个字符

#include<iostream>
#include<string>
using namespace std;
#define ENDFILE "CTRL-Z"
int main()
{
    const char NWLN='\n'; //换行符字符串
    char next;     //下一个字符串在当前行
    int charCount; //字符串的数字在当前位置
    int lineCount; //保持栈的数据行在文件中
    lineCount =0;
    cout<<"Enter a line or press"<<ENDFILE<<": ";
    cin.get(next);  //得到第一个字符在新的行
    while(!cin.eof())
    {
        charCount=0;  //初始化新的行
        while(next!=NWLN)
        {
            cout.put(next);
            charCount++; //增加字符数量
            cin.get(next); //得到下一个字符串
        } //结束里面的while
        cout.put(NWLN); //标记当前显示字符串的结束
        lineCount++;
        cout<<"Number of characters in line "<<lineCount<<" is "<<charCount<<endl;
        cout<<"Enter a line or press "<<ENDFILE<<": ";
        cin.get(next);  //得到新的字符串
    }//结束外面的while
    cout<<endl<<endl<<"Number of lines processed is "<<lineCount<<endl;
    return 0;
}

8.1.2程序风格—使用流作为条件

c++程序员可选择使用eof函数来测试流是否结束,也可以通过流名直接作为条件以测试流的状态。
注意:输入操作(cin.get(next))只在循环重复条件中出现。

8.2外部文件

8.2.1交互式与批处理

批处理:通过外部文件而不是与用户交互读取数据。
回显:读到的数据值的马上显示。
硬拷贝:程序输出到纸上的永久拷贝。

8.2.2外部文件的目录名

若要访问程序中的文件,必须知道文件的目录名。目录名由文件的路径及其之后的文件名构成。
文件名必须遵循特定计算机系统所应用的协议。

8.2.3将流连接到文件

c++中,使用open语句连接一个流对象到一个外部文件。
为了安全,避免原始文件丢失,做好文件的备份或拷贝是一个好主意。
程序中,在读或写外部文件之前,应该首先为程序所要处理的每个流/文件声明一个流对象。

例子:拷贝文件

#include<cstdlib>
#include<fstream>
#include<iostream>
using namespace std;
//将流对象与外部文件名相关联
#define inFile "InData.txt"  //inFile的目录名
#define outFile "OutData.txt"  //outFile的目录名
//使用函数
//复制一行文本
int copyLine(ifstream&, ofstream&);
int main()
{
    int lineCount; //输出:生产线数量
    ifstream ins;  //ins是一个输入的流
    ofstream outs;  //outs是一个输出的流
    //打开输入和输出的文件,存在任意的错误
    ins.open(inFile); //连接ins到文件inFile
    if(ins.fail())
    {
        cerr <<"*** ERROR:Cannot open "<<inFile<<"for input."<<endl;
        return EXIT_FAILURE; //错误返回
    }
    outs.open(outFile);  //连接outs到文件outFile
    if(outs.fail())
    {
        cerr<<"*** ERROR:Cannot open "<<outFile<<"for output."<<endl;
        return EXIT_FAILURE;  //错误返回
    }
    //复制每个元素从inData到outData.
    lineCount=0;
    while(!ins.eof())
    {
        if(copyLine(ins,outs)!=0)
            lineCount++;
    }
    //在屏幕上显示信息
    cout<< "Input file copied to output file."<< endl;
    cout<<lineCount<<"lines copied."<<endl;
    ins.close();  //关闭输入文件流
    outs.close();  //关闭输出文件流
    return 0; //成功返回
}

//复制文件的一行到另一个文件
//pre: 输入打开以进行输入,输出打开输出
//post: ins的下一行被写到输出。最后的元素过程从ins是<nwln>;
//            最后的元素被写到outs是<nwln>
//返回:元素复制的数量
int copyLine(ifstream& ins,ofstream& outs)
{
    const char NWLN='\n';  //新行的元素
    char nextCh;  //输入:元素缓冲区
    int charCount=0; //元素复制的数量
    //复制所有的元素从输入流到输出流
    ins.get(nextCh);
    while((nextCh!=NWLN)&&!ins.eof())
    {
        outs.put(nextCh);
        charCount++;
        ins.get(nextCh);
    }//结束while
    //如果最后的元素读的是NWLN写它到输出
    if(!ins.eof())
    {
        outs.put(NWLN);
        charCount++;
    }
    return charCount;
}//结束复制流

cerr:标准错误流,通常连接到显示器。

8.2.4copyLine函数

所有文件流参数都必须进行引用传递。

8.2.5换行符的更多信息

8.2.6使用getline处理文件流

8.2.7程序风格—读取文件名

8.3使用外部文件进行程序间的通信

例子:准备一个工资文件
问题:写二个用于处理公司工资的程序。第一个程序读取由员工工资数据组成的数据文件,每位员工的数据以单独的数据记录存储,数据记录包含员工的名,姓,工时以及时薪,由三条数据记录组成的文件如下所示:
Jim Baxter 35.5 7.25
Adrian Cybriwsky 40.0 6.50
Ayisha Mertens 20.0 8.00
第一个程序为每位员工读取输入数据并且计算该员工的工作额,工作额是工时与时薪的乘积。然后,第一个程序将员工的名字和工资额写到输出文件,并且计算全公司薪水册的总工资数。处理完所有员工记录后,显示整个薪水册。处理上面的输入文件样本会产生如下的输出文件样本:
Jim Baxter $257.38
Adrian Cybriwsky $260.00
Ayisha Mertens $160.00
第二个程序读取上面的文件作为它的数据文件,并且基于其内容打印工资单。例如,发出的第一张工资单应该是开出给Jim Baxter的$257.38.

#include<fstream>  //文件流的需要
#include<cstdlib>  //EXIT_FAILURE的定义
#include<iostream>
using namespace std;
//联系流和外部的文件名
#define inFile "EmpFile.txt"  //员工文件
#define outFile "Salary.txt"  //工资文件
//函数域
float processEmp(ifstream&,ofstream&);
int main()
{
    ifstream eds;  //输入:员工数据流
    ofstream pds; //输出:工资数据流
    float totalPayroll;  //输出:总的工资
     //准备的文件
     eds.open(inFile);
     if(eds.fail())
     {
         cerr<<"*** ERROR:Cannot open "<< inFile<<"for input."<<endl;
         return EXIT_FAILURE;  //错误返回
     }
     pds.open(outFile);
     if(pds.fail())
     {
         cerr<<"***EROR: Cannot open "<<outFile<<" for output."<<endl;
         eds.close();
         return EXIT_FAILURE;  //错误返回
     }
     //统计全部员工和计算全部工资
     totalPayroll=processEmp(eds, pds);
     //显示结果
     cout<<"Total payroll is $"<<totalPayroll<<endl;
     //关闭文件
     eds.close();
     pds.close();
     return 0;
} //插入processEmp在这
float processEmp(ifstream& eds,ofstream& pds)
{
    string firstName; //输入:员工的姓
    string lastName;  //输入:员工的名
    float hours;  //输入:工作时间
    float rate;  //输入:时间频率
    float salary;  //输出:总工资
    float payroll;  //返回值-总共公司的工资
    payroll=0.0;
    //读取第一个员工的数据报告
    eds>>firstName>>lastName>>hours>>rate;
    while(!eds.eof())
    {
        salary=hours*rate;
        pds<<firstName<<" "<<lastName<<" "<<salary<<endl;
        payroll+=salary;
        //读取下一个员工的数据报告
        eds>>firstName>>lastName>>hours>>rate;
    }//结束while
    return payroll;
}//结束processEmmp

在运行该程序之前,使用编辑器键入数据文件并将此文件保存在与程序相同的目录下。确定在键入最后一行后按下了RETURN键。

8.4关于读取字符串数据的更多信息

磅字符"#"作为每位员工名字的结束标志。可认为磅字符是字符串定界符。
空字符串:包含零个字符的空字符串。

8.5输入/输出控制符

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值