输入和输出流(Part Ⅱ)

标准输入流

  • 标准输入流是从标准输入设备(键盘)流向程序的数据

cin流

  • 在头文件iostream.h中定义了cin,cout,cerr,clog4个流对象,cin是输入流,cout,cerr,clog是输出流
  • cin是istream类的派生类的对象,它从标准输入设备(键盘)获取数据,程序中的变量通过流提取符">>“从流中提取数据。流提取符”>>"从流中提取数据时通常跳过输入流中的空格、tab键、换行符等空白字符。
  • 注意:只有在输入完数据再按Enter键后,该行数据才被送入键盘缓冲区,形成输入流,提取运算符">>"才能从中提取数据。

用于字符输入的流成员函数

  • 除了可以用cin输入标准类型的数据外,还可以用istream类流对象的一些成员函数,实现字符的输入

用get函数读入一个字符

流成员函数get有3种形式:无参数的,有一个参数的,有3个参数的

  • 无参数的get函数
    其调用形式为:cin.get()。用来从指定的输入流中提取一个字符(包括空白字符),函数的返回值就是读入的字符。若遇到输入流中的文件结束符,则函数值返回文件结束标志EOF(EOF是在iostream头文件中定义的符号常量,代表-1) 。

例:用get函数读入字符

#include <iostream>
using namespace std;
int main()

{
	int c;
	cout << "enter a sentence : " << endl;
	while ((c = cin.get()) != EOF)
		cout.put(c);
	return 0;
}

C语言中的getchar函数与流成员函数cin.get( )的功能相同

  • 有一个参数的get函数
    其调用形式为cin.get(ch),其作用是从输入流中读取一个字符,赋给字符变量ch。如果读取成功则函数返回非0值(真),如失败(遇文件结束符) 则函数返回0值(假)。
#include <iostream>
using namespace std;
int main()
{
	char c;
	cout <<"enter a sentence :" << endl;
	while (cin.get(c)) cout.put(c); //读取一个字符赋给字符变量c,如果读取成功,cin.get(c)为真
	cout << "end" << endl;
	return 0;
}
  • 有3个参数的get函数
    其调用形式为cin.get(字符数组,字符个数n,终止字符)cin.get(字符指针,字符个数n,终止字符)
    其作用是从输入流中读取n-1个字符,赋给指定的字符数组(或字符指针指向的数组),如果在读取n-1个字符之前遇到指定的终止字符,则提前结束读取。如果读取成功则函数返回非0值(真),如失败(遇文件结束符) 则函数返回0值(假)。
#include <iostream>
using namespace std;
int main()
{
	char ch[20];
	cout << "enter a sentence : " << endl;
	cin.get(ch, 10, '//n'); //指定换行符为终止字符
	cout << ch << endl;
	return 0;
}

用成员函数getline函数读入一行字符

  • getline函数的作用是从输入流中读取一行字符,其用法与带3个参数的get函数类似。即cin.getline(字符数组(或字符指针),字符个数n,终止标志字符)
#include <iostream>
using namespace std;
int main()
{
	char ch[20];
	cout << "enter a sentence:" << endl;
	cin >> ch;
	cout << "The string read with cin is:"<< ch << endl;
	cin.getline(ch, 20, '/');//读19个字符或遇'/'结束
	cout << "The second part is:" << ch << endl;
	cin.getline(ch, 20); //读19个字符或遇'/n'结束
	cout << "The third part is:" << ch << endl;
	return 0;
}

istream类的其他成员函数

eof函数

  • eof是end of file的缩写,表示"文件结束"。从输入流读取数据,如果到达文件末尾(遇文件结束符),eof函数值为非零值(表示真),否则为0(假)。

例:逐个读入一行字符,将其中的非空格字符输出

#include <iostream>
using namespace std;
int main()
{
    char c;
    while (!cin.eof()) //eof( )为假表示未遇到文件结束符
        if ((c = cin.get()) != ' ') cout.put(c); //检查读入的字符是否为空格字符
    return 0;
}

peek函数

  • peek是"观察"的意思,peek函数的作用是观测下一个字符。其调用形式为c=cin.peek( );。cin.peek函数的返回值是指针指向的当前字符,但它只是观测,指针仍停留在当前位置,并不后移。如果要访问的字符是文件结束符,则函数值是EOF(-1)。

putback函数

  • 其调用形式为cin.putback(ch);,其作用是将前面用get或getline函数从输入流中读取的字符ch返回到输入流,插入到当前指针位置,以供后面读取。

例:peek函数和putback函数的用法

#include <iostream>
using namespace std;
int main()
{
	char c[20];
	int ch;
	cout << "please enter a sentence:" << endl;
	cin.getline(c, 15, '/');
	cout << "The first part is:" << c << endl;
	ch = cin.peek(); //观看当前字符
	cout << "The next character(ASCII code) is:" << ch << endl;
	cin.putback(c[0]); //将'I'插入到指针所指处
	cin.getline(c, 15, '/');
	cout << "The second part is:" << c << endl;
	return 0;
}

运行结果:

ignore函数

  • 其调用形式为cin,ignore(n,终止字符),函数作用是跳过输入流中n个字符,或在遇到指定的终止字符时提前结束(此时跳过包括终止字符在内的若干字符)
  • 如:ighore(5, 'A') //跳过输入流中5个字符,遇'A'后就不再跳了,也可以不带参数或只带一个参数。如:ignore( )(n默认值为1,终止字符默认为EOF)。相当于ignore(1,EOF)

例:用ignore函数跳过输入流中的字符

#include <iostream>
using namespace std;
int main()
{
	char ch[20];
	cin.get(ch, 20, '/');
	cout << "The first part is:"<< ch << endl;
	cin.ignore(); //跳过输入流中一个字符
	cin.get(ch, 20, '/');
	cout << "The second part is:" << ch << endl;
	return 0;
}

程序分析:

  • 不用ignore函数时程序省略第8行,此时字符数组ch中没有从输入流中读取有效字符。

运行结果:

对数据文件的操作与文件流

文件的概念

  • 所谓"文件(file)"一般指存储在外部介质上数据的集合。操作系统是以文件为单位对数据进行管理的。
  • 对用户来说,常用到的文件有两大类,一类是程序文件(program file),另一类是数据文件(data file)
  • 根据文件中数据的组织形式,可分为ASCII文件和二进制文件。ASCII文件又称文本(text)文件或字符文件,它的每一个字节放一个ASCII代码,代表一个字符。二进制文件又称内部格式文件或字节文件,是把内存中的数据按其在内存中的存储形式原样输出到磁盘上存放。
  • 对于字符信息,在内存中是以ASCII代码形式存放的,因此,无沦用ASCII文件输出还是用二进制文件输出,其数据形式是一样的。但是对于数值数据,二者是不同的。
  • 用ASCII码形式输出的数据是与字符一一对应的,一个字节代表一个字符,可以直接在屏幕上显示或打印出来。这种方式使用方便,比较直观,便于阅读,便于对字符逐个进行输入输出,但一般占存储空间较多,而且要花费转换时间(二进制形式与ASCII码间的转换)。用内部格式(二进制形式)输出数值,可以节省外存空间,而且不需要转换时间,但一个字节并不对应一个字符,不能直观地显示文件中的内容。如果在程序运行过程中有些中间结果数据暂时保存在磁盘文件中,以后又需要输入到内存的,这时用二进制文件保存是最合适的。如果是为了能显示和打印以供阅读,则应按ASCII码形式输出。此时得到的是ASCII文件,它的内容可以直接在显示屏上观看。
  • C++提供了低级的I/O功能和高级的l/O功能。高级的I/O功能是把若干个字节组合为一个有意义的单位(如整数、单精度数、双精度数、字符串或用户自定义的类型的数据),然后以ASCII字符形式输入和输出。例如将数据从内存送到显示器输出,就属于高级I/O功能,先将内存中的数据转换为ASCII字符,然后分别按整数、单精度数、双精度数等形式输出。这种面向类型的输入输出在程序中用得很普遍,用户感到方便。但在传输大容量的文件时由于数据格式转换,速度较慢,效率不高
  • 所谓低级的I/O功能是以字节为单位输入和输出的,在输入和输出时不进行数据格式的转换。这种输入输出是以二进制形式进行的。通常用来在内存和设备之间传输一批字节。这种输入输出速度快、效率高,一般大容量的文件传输用无格式转换的I/O。但使用时会感到不大直观,难以判定数据的内容。

文件流类与文件流对象

  • 文件流是以外存文件为输入输出对象的数据流。输出文件流是从内存流向外存文件的数据,输入文件流是从外存文件流向内存的数据。每一个文件流都有一个内存缓冲区与之对应。
  • 文件流本身不是文件,而只是以文件为输入输出对象的流。若要对磁盘文件输入输出,就必须通过文件流来实现。
  • 在C++的I/O类库中定义了几种文件类,专门用于对磁盘文件的输入输出操作。标准输入输出流类istream,ostream和iostream类外,还有3个用于文件操作的文件类:
  1. ifstream类,它是从istream类派生的。用来支持从磁盘文件的输入
  2. ofstream类,它是从ostream类派生的。用来支持向磁盘文件的输出
  3. fstream类,它是从iostream类派生的。用来支持对磁盘文件的输入输出
  • 要以磁盘文件为对象进行输入输出,必须定义一个文件流类的对象,通过文件流对象将数据从内存输出到磁盘文件,或者通过文件流对象从磁盘文件将数据输入到内存。
  • 在用磁盘文件时,由于情况各异,无法事先统一定义,必须由用户自己定义。此外,对磁盘文件的操作是通过文件流对象(而不是cin和cout)实现的。文件流对象是用文件流类定义的,而不是用istrearm和ostream类来定义的。
  • 可以用下面的方法建立一个输出文件流对象:ofstream outfile;

文件的打开与关闭

打开磁盘文件

  • 打开文件是指在文件渎写之前做必要的准备工作,包括:
    (1)为文件流对象和指定的磁盘文件建立关联,以便使文件流流向指定的磁盘文件。
    (2)指定文件的工作方式,如,该文件是作为输入文件还是输出文件,是ASCII文件还是二进制文件等。
  • 以上工作可以通过两种不同的方法实现:
  1. 调用文件流的成员函数open,如:
ofstream outfile; //定义ofstream类(输出文件流类)对象outfile
outfile.open("f1.dat",ios::out); //使文件流与f1.dat文件建立关联
  • 第2行是调用输出文件流的成员函数open打开磁盘文件f1.dat,并指定它为输出文件,文件流对象outfile将向磁盘文件f1.dat输出数据。 ios::out是I/O模式的一种,表示以输出方式打开一个文件。或者简单地说,此时f1.dat是一个输出文件,接受从内存输出的数据。
  • 调用成员函数open的一般形式为:文件流对象.open(磁盘文件名,输入输出方式);
    磁盘文件名可以包括路径,如:“c:\new\f1.dat”,如果缺省路径,则默认为当前目录下的文件
  1. 在定义文件流对象时指定参数
  • 在声明文件流类时定义了带参数的构造函数,其中包含了打开磁盘文件的功能。因此,可以在定义文件流对象时指定参数,调用文件流类的构造函数来实现打开文件的功能。如:ostream outfile("f1.dat",ios::out);
  • 输入输出方式是在lOS类中定义的,它们是枚举常量,有多种选择:
方式作用
ios::in以输入方式打开文件
ios::out以输出方式打开文件(这是默认方式),如果已有此名字的文件,则将其原有内容全部清除
ios::app以输出方式打开文件,写入的数据添加在文件末尾
ios::ate打开一个已有的文件,文件指针指向文件末尾
ios::trunc打开一个文件,如果文件已存在,则删除其中全部数据,如文件不存在,则建立新文件。如已指定了ios::out方式,而未指定ios::app,ios::ate,ios::in,则同时默认此方式
ios:: binary以二进制方式打开一个文件,如不指定此方式则默认为ASCII方式
ios::nocreate打开一个已有的文件,如文件不存在,则打开失败。nocrcate的意思是不建立新文件
ios:: noreplace如果文件不存在则建立新文件,如果文件已存在则操作失败,noreplace的意思是不更新原有文件
ios::in l ios::out以输入和输出方式打开文件,文件可读可写
ios::out l ios::binary以二进制方式打开一个输出文件
ios::in l ios::binary以二进制方式打开一个输入文件

说明:

  1. 新版本的I/O类库中不提供ios::nocreate和ios::noreplace
  2. 每一个打开的文件都有一个文件指针,该指针的初始位置由I/O方式指定,每次读写都从文件指针的当前位置开始。每读入一个字节,指针就后移一个字节。当文件指针移到最后,就会遇到文件结束EOF(文件结束符也占一个字节,其值为-1),此时流对象的成员函数eof的值为非0值(一般设为1),表示文件结束了。
  3. 可以用"位或"运算符"I"对输入输出方式进行组合,如:
ios::in | ios::nocreate //打开一个输入文件,若文件不存在则返回打开失败的信息
ios::app | ios::nocreate //打开一个输出文件,在文件尾接着写数据,若文件不存在则返回打开失败的信息
ios::out | ios::noreplace //打开一个新文件作为输出文件,如果文件已存在则返回打开失败的信息
ios::in | ios::out | ios::binary //打开一个二进制文件,可读可写

但不能组合互相排斥的方式,如:ios::nocreate | ios::noreplace

  1. 如果打开操作失败,open函数的返回值为0(假);如果是用调用构造函数的方式 打文件的,则流对象的值为0。可以据此测试打开是否成功。如:
if(outfile.open("f1.dat",ios::app) == 0) cout<<"open error"if(!outfile.open("f1.dat",ios::app)) cout<<"open error"

关闭磁盘文件

  • 在对已打开的磁盘文件的读写操作完成后,应关闭该文件。关闭文什用成员函数close。
    如:outfile.close(); //将输出文件流所关联的磁盘文件关闭
  • 所谓关闭,实际上是解除该磁盘文件与文件流的关联,原来设置的工作方式也失效,这样,就不能再通过文件流对该文件进行输入或输出。此时可以将文件流与其他磁盘文件建立关联,通过文件流对新的文件进行输入或输出。
    如:outfile.open("f2.dat",ios::app | ios::nocrcate); 此时文件流outfile与f2.dat建立关联,并指定了f2.dat的工作方式。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值