再上一篇:第十四章 输入/输出流类库
上一篇:14.2 C++的基本流类体系
主页
下一篇:14.4 文件流
再下一篇:第十五章 MFC程序设计基础
文章列表

14.3 标准设备的输入/输出

《VC++程序设计基础》,讲述C++语言的语法和标准库,以及Visual C++ 函数库和MFC类库的使用,并附相关代码示例。

在第3章中介绍了数据的基本输入/输出方法,在前一节中介绍了按指定的数制进行输入/输出和利用格式控制函数实现格式控制输出。实际上C++的输入/输出流提供了多种输入/输出手段,以适应各种程序设计的需要。本节集中介绍使用标准输入/输出流时要注意的问题以及实现输入/输出的各种成员函数的使用方法。

数据的输入/输出可以分为三大类:字符类、字符串类和数值(整数、实数和双精度数)类。每一类又可以分为多种类型,如长整型、短整型、有符号型和无符号型等。不同类型数据的输入是由类istream通过多次重载 >>” 运算符来实现的。不同类型数据的输出是由类ostream通过多次重载 “<<” 运算符来实现的。

14.3.1 不同类型数据的输入

在C++中,允许用户自行定义类istream的对象,但只要程序中包含头文件iostream.h,系统自动为该程序产生输入流cin和输出流cout。通常用户只要利用流cin就可完成不同类型数据的输入。下面通过示例来说明使用cin时要注意的事项。

例14.6 使用cin的示例。

#include

void main(void )

{

int i,j;

cout << "输入一个整数(十进制):";

cin >> i; //提取十进制数

cout << "输入一个整数(十六进制):";

cin>>hex>>j; //提取十六进制数

cout <<"i="<

cout <<"j="<

}

程序执行时,设输入的两个数为:256和ff。可以一行内输入也可以分为两行输入,程序都能正确执行。但当输入:r ff时,程序的输出为:

i=0

j=31376764

显然,当输入的数据格式与要提取的数据格式不一致时,程序肯定输出错误的结果。在使用cin输入数据时,要注意以下几点。

(1)cin是缓冲流,把用户输入的数据送到缓冲区中,仅当输入一行的结束符(Enter键)时,才开始进行提取数据的处理,只有把输入缓冲区中的数据提取完后,才开始要求新的输入。如上面的两个输入数,在一行内输入或在两行内输入,均可正确提取。

(2)输入数据时,在缺省的情况下,把空格作为数据之间的分格符,在输入的数据之间可以用一个或多个空格分开。例如:

char c1,c2,str1[80];

cin >>c1>>c2>>str1;

则输入给变量c1和c2的字符不能是空格,输入给str1的字符串中也不能包含空格。

(3)输入的数据类型必须与对应要提取的数据类型(变量类型)一致,否则会出现错误。这种错误只是在流的状态标志字中置位,并不中止程序的执行。若程序中没有相应的出错处理程序,则导致计算结果不正确。如上例中当输入:

r ff

在为变量i提取值时,遇到字符r,认为输入的整数已结束,把0赋给变量i,而输入流中的字符r仍没有处理。当从输入流中为变量j提取数据时,仍提取到字符r,导致赋给变量j的值不正确。

(4)在输入数据时,换行符(Enter键)起两方面的作用:一方面告诉系统,已输入到缓冲区中的数据可以进行提取操作了;另一方面,从输入流中提取数据时,它也作为空格字符处理。例如:

int i,j,k;

cin >>i>>j>>k;

当输入的数据为:

1 3 6< Enter键>

或分三行输入:

1< Enter键>

3< Enter键>

6< Enter键>

都是将1,3,6分别赋给变量i,j,k。两者的效果相同。

14.3.2 输入操作的成员函数

当希望把输入的空格也作为一个字符赋给字符变量或者要把所输入的包含空格的字符串赋给字符数组时,显然采用前面的输入方法已很难解决。解决这种问题的方法是利用类istream中的成员函数。常用的输入字符或字符串的成员函数有:

int istream::get(); //A

istream& istream::get(char &); //B

istream& istream::get(unsigned char &); //C

istream& istream::get( signed char &); //D

istream& istream::get(char *,int,char ='\n'); //E

istream& istream::get(unsigned char *,int,char ='\n'); //F

istream& istream::get( signed char *,int,char ='\n'); //G

istream& istream::getline( char *,int,char ='\n'); //H

istream& istream::getline(unsigned char *,int,char ='\n'); //I

istream& istream::getline( signed char *,int,char ='\n'); //J

A行的函数从输入流中提取一个字符,并将所提取的字符作为返回值。B、C、D行的三个函数的功能是相同的,都是从输入流中提取一个字符,并将提取的字符赋给输入参数的字符变量。E、F、G行的三个函数的功能是相同的,都是从输入流中提取一个字符串,并将提取的字符串赋给第一个输入参数(指向字符串的指针)所指向的存储区;第二个参数为至多提取的字符个数(指定值为n时,至多提取n-1个字符,尾部增加一个字符串结束符);第三个参数为结束字符,缺省值为换行符。当给出该字符时,依次从输入流中提取字符,当遇到该结束字符时,则结束提取字符的工作。H、I、J行的三个函数的功能相同,均从输入流中提取一个输入行,把输入行作为一个字符串送到第一个参数所指向的存储区。三个参数的作用与前三个函数相同。

这些函数可以从输入流中提取任何字符,包括空格字符。

例14.7 读取字符和字符串。

#include

void main(void )

{

char c1,c2,c3;

char str1[80],str2[100];

cout << "输入三个字符:";

c1=cin.get();

cin.get(c2);

cin.get(c3);

cin.get(); //A

cout << "输入第一行字符串:";

cin.get(str1,80);

cin.get(); //B

cout <<"输入第二行字符串:";

cin.getline(str2,80); //D

cout <<"c1="<

cin.get(c1);

cin.ignore(80,'\n'); //A

cout << "输入第一行字符串:";

cin.getline(str1,80);

num=cin.gcount();

cout <<"c1="<

cout<< "str1="<

cout <<"num="<

}

A行把输入行中的其余字符取空,以便后面的输入从新的一行开始。程序执行时,若输入以下两行:

abcd Abort

computer depart.

则输出以下结果:

c1=a

str1= computer depart.

num=17

14.3.3 不同类型数据的输出

不同类型数据的输出是通过类ostream的对象使用重载运算符“<<”进行插入操作来实现的。C++有标准输出流cout,cerr和clog。通常的情况下,使用这三个标准输出流可完成各种类型的数据输出。用户也可以自己定义输出流。

标准输出流输出整数时,缺省的设置为:数制为十进制、域宽为0、数字右对齐、以空格填充。输出实数时,缺省的设置为:精度为六位小数、浮点输出、域宽为0、数字右对齐、以空格填充。当输出的实数的整数部分超过七位或有效数字在小数点右边第四位之后时,则转换为科学计数法输出。输出字符或字符串时,缺省的设置为:域宽为0、字符右对齐、以空格填充。域宽为0的含义是按数据的实际占用的字符位数输出,在输出的数据之间没有空格。

前面已多次使用标准输出流,这里不再举例说明了。

14.3.4 输出字符的成员函数

在类ostream 中定义了几个成员函数,用户可以使用这些成员函数来输出字符。部分成员函数如下:

ostream& ostream ::put(char);

ostream& ostream ::put(unsigned char);

ostream& ostream ::put(signed char);

ostream& ostream ::flush();

前三个成员函数的功能是相同的,其参数是要输出的字符。如:

int i=96;

cout.put((char)i);

成员函数flush刷新一个输出流。例如:

cout. flush();

对于标准输出流,通常只有cout 和clog需要调用flush来强制刷新输出流的缓冲区。14.3.5重载提取和插入运算符

在 C++中允许用户重载运算符“<<”和“>>”,以便用户利用标准的输入/输出流来输入/输出自行定义的数据类型,实现对象的输入和输出。在重载这二个运算符时,在用户自定义的类中,将重载这两个运算符的函数说明为该类的友元函数。

重载提取运算符的一般格式为:

friend istream & operater >>(istream &, ClassName &);

函数的返回值必须是对类istream的引用,这是为了在cin中可以连续使用 “>>” 运算符。函数的第一个参数也必须是类istream的引用,它将作为运算符的左操作数;第二个参数为用户自定义类的引用,并作为运算符的右操作数。

重载插入运算符的一般格式为:

friend ostream & operater <<(ostream &, ClassName &);

函数的返回值必须是对类ostream的引用,这是为了在cout中可以连续使用 “<<” 运算符。第一个参数也必须是类ostream的引用,它将作为 “<<” 运算符的左操作数;第二个参数为用户自定义类的引用(也可以是类的对象),并作为 “<<” 运算符的右操作数。

例14.9 重载提取和插入运算符,实现对象的输入和输出。

#include

class Money{

int Dollar,Cents;

public:

friend ostream & operator << (ostream & ,Money &);

friend istream & operator >> (istream & ,Money &);

Money(int m=0, int c=0){ Dollar=m;Cents=c;}

};

ostream & operator << (ostream &os ,Money &m)

{

os <<"¥"<

return os;

}

istream & operator >> (istream &is ,Money & m)

{

is >>m.Dollar>>m.Cents;

return is;

}

void main(void )

{

Money m1(200,55),m2;

cout <<"输入两个整数元、分(int int ):";

cin >>m2; //A

cout <

}

执行程序时,若输入数据为:

125 56

则程序的输出为:

¥200元 55分

¥125元 56分

经重载提取和插入运算符后,实现了对象的直接输入和输出。对于 A行中表达式cin>>m2,编译器将其变换为:

m2.operator >>(cin,m2)

通过调用重载运算符函数来实现对象 m2的各个成员的输入。对于 B行中的表达式 cout<

m1.operator<<(cout,m1)

从该例可以看出,不管如何重载 “<<”和“>>” 运算符,要实现数据的输入和输出,在重载运算符的函数体内,还是要通过cout和cin来完成数据的输出和输入。