第 22讲 C++的输入和输出教学目的和要求:
了解 I/O标准流类 。
掌握格式化输入输出及重载输入输出运算符 。
教学内容提要:
1,I/O标准流类;
2,文件流类;
3,预定义类型的输入输出;
4,用户自定义类型的输入输出教学重点:格式化输入输出及重载输入输出运算符 。
教学难点:格式化输入输出及重载输入输出运算符 。
教学进度,P242~P261
教学过程:
22.1 C++为何建立自己的输入输出系统
因为在 C++中用户需要定义众多的自定义类型,但是 C语言的输入输出系统不支持用户自定义的类型。请看下面的类,
class my_class{
int i;
float f;
char *str;
} obj;
对此类类型,在 C语言中下面的语句是不能接受的,
printf(" % my_class",obj);
C++的流类比 C的输入输出函数具有更大的优越性。
22.2 C++的流库及其基本结构
22.2.1 C++的流在 C++中,流类是为输入输出提供的一组类,
它们都放在流库中。
流总是与某一设备相联系的(例如键盘、屏幕或硬盘等),通过使用流类中定义的方法,就可以完成对这些设备的输入输出操作。
流具有方向性,与输入设备 (如键盘 )相联系的流称为输入流 ;与输出设备 (如屏幕 )相联系的流称为输出流 ;与输入输出设备 (如磁盘 )相联系的流称为输入输出流。
C++中包含几个预定义的流对象,,
标准输入流 cin 与标准输入设备相关联
标准输出流 cout 与标准输出设备相关联
非缓冲型的标准出错流 cerr 与标准错误输出设备相关联 (非缓冲方式 )
缓冲型的标准出错流 clog 与标准错误输出设备相关联 (缓冲方式 )
在缺省情况下,指定的标准输出设备是屏幕,标准输入设备是键盘。
22.2.2 流类库
C++流类库具有两个平行的基类,即
streambuf类和 ios类,所有其他的流类都是从它们直接或间接地派生出来的其中,
ios类为输入输出操作在用户一方的接口,
负责高层操作,
streambuf类为输入输出操作在物理设备一方的接口,负责低层操作。
ios
istream ostream
istrstream
ifstream
istream_withassign ostream_withassign
ofstream
ostrstream
iostream
stdiostreamfstream strstream
streambuf
stdiobuffilebuf strstreambuf
图 各类之间的关系
22.3 预定义类型的输入输出
22.3.1无格式输入输出基于 C++类库的输入输出需使用两个流对象 cin和 cout,还要用与之相配套的两个输入输出运算符,>>”和,<<”,其一般的格式为
cin>>变量 ; // 输人
cout<< 常量或变量 ; // 输出
1,输出运算符从运算符角度来看,输出通过输出运算符,<<”
来完成的,输出运算符,<<” 也称插入运算符,
它是一个双目运算符,有两个操作数,左操作数为 ostream类的一个对象 ( 如 cout),右操作数为一个系统预定义类型的常量或变量 。 例如
cout<<"This is a string.\n";
完成的功能为写字符串,This is a string.,到流对象 cout,cout为标准输出流,通常为屏幕。
2,输入运算符从运算符角度来看,输入操作通过输入运算符,>>”来完成 。 输入运算符,>>”
也称提取运算符,它也是一个双目运算符,
有两个操作数,左面的操作数是 istream
类的一个对象 (cin),右面的操作数是系统预定义的任何数据类型的变量 。 例如,
int x;
cin>>x;
此时,用户从键盘输入的数值会自动地转换为变量 x的类型,并存入变量 x内。
22.3.2 格式化输入输出
C++提供了两种进行格式控制的方法:
一种是使用 ios类中有关格式控制的成员函数进行格式控制;
另一种是使用称为操纵符的特殊类型的函数进行格式控制。
1,用 ios类的成员函数进行格式控制格式控制主要是通过对状态标志字的操作来完成的。
在 ios类的 public部分定义了一个枚举,
它的每个成员分别定义状态标志字的一个位,每一位都称为一个状态标志位。
enum{
skipws =0x0001,/ / 跳过输入中的空白,可用于输出
left =0x0002,// 左对齐输出,可用于输出
right =0x0004,// 右对齐输出,可用于输出
internal =0x0008,// 在符号位和基指示符后填入字符,
//可用于输出
dec =0x0010,// 转换基制为十进制数,可用于输入
//或输出
oct =0x0020,// 转换基制为八进制数,可用于输入
//或输出
hex =0x0040,// 转换基制为十六进制数,可用于输
//入或输出
showbase =0x0080,// 在输出时显示基指示符,可用于
//输入或输出
showpoint =0x0100,// 在输出时显示小数点,可用于输出
uppercase =0x0200,//十六进制输出时,表示制式和表示数
//值的字符 一律为大写,可用于输出
showpos =0x0400,//对正整数显示正号,可用于输出
scientific =0x0800,//用科学表示法显示浮点数,可用于输出
fixed =0x1000,//用定点形式显示浮点数,可用于输出
unitbuf =0x2000,//在输出操作后立即刷新所有流,可用
//于输出
stdio =0x4000,//在输出操作后刷新 stdout和 stderr,可用
//于输出
};
这些枚举元素的值有一个共同的特点,
分别使二进制表示的状态标志字的不同位为,1”,如,
skipws 0x0001 0000 0000 0000 0001
left 0x0002 0000 0000 0000 0010
right 0x0004 0000 0000 0000 0100
表 控制输入输出格式的成员函数函 数 原 型 功 能
long ios∷ setf(long flags);
long ios∷ unsetf(long flags);
long ios∷ flags();
long ios∷ flags(long flags);
int ios∷ width();
int ios∷ width(int w);
int ios∷ precision(int p);
char ios∷ fill();
char ios∷ fill(char ch);
设置状态标志 flags
清除状态标志,并返回前状态标志测试状态标志设置标志 flags,并返回前状态标志返回当前的宽度设置值设置域宽 w,返回以前的设置设置小数位数 p,返回以前的小数位数返回当前的填充字符设置填充字符 ch,返回当前的填充字符例 22.1 成员函数进行格式控制 。
#include<iostream.h>
main()
{ cout<<"x_width="<<cout.width()<<endl;
cout<<"x_fill="<<cout.fill()<<endl;
cout<<"x_precision="<<cout.precision()<<endl;
cout<<123<<" "<<123.45678<<endl;
cout<<"_________________________________\n";
cout<<"*** x_width=10,x_fill=,x_precision=4 ***\n";
cout.width(10);
cout.precision(4);
cout<<123<<" "<<123.45678<<" "<<234.567<<endl;
cout<<"x_width="<<cout.width()<<endl;
cout<<"x_fill="<<cout.fill()<<endl;
cout<<"x_precision="<<cout.precision()<<endl;
cout<<"_________________________________\n";
cout<<"*** x_width=10,x_fill=&,x_precision=4 ***\n";
cout.fill('&');
cout.width(10);
cout<<123<<" "<<123.45678<<endl;
cout.setf(ios::left);
cout.width(10);
cout<<123<<" "<<123.45678<<endl;
cout<<"x_width="<<cout.width()<<endl;
cout<<"x_fill="<<cout.fill()<<endl;
cout<<"x_precision="<<cout.precision()<<endl;
return 0;
}
程序运行结果如下,
x_width=0
x_fill=
x_precision=0
123 123.45678
-----------------------------
*** x_width=10,x_fill=,x_precision=4 ***
123 123.4568 234.567
x_width=0
x_fill=
x_precision=4
-----------------------------
*** x_width=10,x_fill=&,x_precision=4 ***
&&&&&&&123 123.4568
123&&&&&&& 123.4568
x_width=0
x_fill=&
x_precision=4
C++提供的预定义操纵符如下,
1,dec 以十进制形式输入或输出整型数,可用于输入或输出
2,hex 以十六进制形式输入或输出整型数,可用于输入或输出。
3,oct 以八进制形式输入或输出整型数,可用于输入或输出
4,ws 用于在输入时跳过前导的空白符,可用于输入。
5,endl 插入一个换行符并刷新输出流,仅用于输出。
6,ends 插入一个空字符’ \0’,通常用来结束一个字符串,仅用于输出
7,flush 刷新一个输出流,仅用于输出
8,setbase(int n) 设置转换基格式为为 n( n的取值为 0,8、
10或 16),n的缺省值为 0,即表示采用十进制,仅用于输出。
9,resetiosflags(long f) 关闭由参数 f指定的格式标志,可用于输入或输出。
10,setiosflags(long f) 设置由参数 f指定的格式标志,可用于输入或输出。
11,setfill(int ch) 设置 ch为填充字符,缺省时为空格,可用于输入或输出
12,setprecision(int n) 设置小数部分的位数,可用于输入或输出
13,setw(int n) 设置域宽为 n,可用于输入或输出例 22.2 操纵符的使用 。
#include<iostream.h>
#include<iomanip.h>
main()
{cout<<setw(10)<<123<<567<<endl; //①
cout<<123<<setiosflags(ios::scientific)<<setw(20) //②
<<123.456789<<endl;
cout<<123<<setw(10)<<hex<<123<<endl; //③
cout<<123<<setw(10)<<oct<<123<<endl; //④
cout<<123<<setw(10)<<dec<<123<<endl; //⑤
cout<<resetiosflags(ios::scientific)<<setprecision(4) //⑥
<<123.456789<<endl;
cout<<setiosflags(ios::left)<<setfill('#')<<setw(8) //⑦
<<123<<endl;
cout<<resetiosflags(ios::left)<<setfill('$')<<setw(8) //⑧
<<456<<endl;
return 0;
}
程序运行结果为,
123567 ①
123 1.234567e+02 ②
123 7b ③
7b 173 ④
173 123 ⑤
123.4568 ⑥
123##### ⑦
$$$$$456 ⑧
22.4.1 重载输出运算符,<<”
定义输出运算符,<<”重载函数的一般格式如下,
ostream& operator<<(ostream& out,class_name&
obj)
{
out<<obj.item1;
out<<obj.item2;
..,
out<<obj.itemn;
return out;
}
22.4 用户自定义类型的输入输出
22.4.2 重载输入运算符,>>”
定义输入运算符函数,>>”重载函数的一般格式如下,
istream& operator>>(istream& in,class_name&
obj)
{
in>>obj.item1;
in>>obj.item2;
.,,
in>>obj.itemn;
return in;
}
例 22.5 输出运算符,<<”重载 。
#include<iostream.h>
class coord {
int x,y;
public:
coord(int i=0,int j=0) { x=i; y=j;}
friend ostream& operator<<(ostream& stream,coord& ob);
};
ostream& operator<<(ostream& stream,coord& ob)
{ stream<<ob.x<<","<<ob.y<<endl; return stream; }
main()
{ coord a(55,66),b(100,200);
cout<<a<<b;
return 0; }
例 22.6 输入运算符,<<”重载 。
#include<iostream.h>
class three_d {
public:
three_d(int a,int b,int c)
{ x=a; y=b; z=c; }
friend ostream& operator<<(ostream& output,three_d& ob);
friend istream& operator>>(istream& itput,three_d& ob);
private:
int x,y,z;
};
ostream& operator<<(ostream& output,three_d& ob)
{ output<<ob.x<<",";
output<<ob.y<<",";
output<<ob.z<<endl;
return output; }
istream& operator>>(istream& input,three_d& ob)
{
cout<<"Enter x,y,z value:";
input>>ob.x;
input>>ob.y;
input>>ob.z;
return input;
}
main()
{
three_d obj(10,20,30); // 定义类 three_d的对象 obj
cout<<obj; // 输出对象 obj的成员值
cin>>obj; // 输入对象 obj的各成员值,将原值覆盖
cout<<obj; // 输出对象 obj的成员值 ( 新值 )
return 0;
}
小结:
1,C++中的流类
2、格式化输入输出(成员函数和操作符)
3、重载输入输出运算符( >>和 <<)
作业:
P275~P276 7.12
了解 I/O标准流类 。
掌握格式化输入输出及重载输入输出运算符 。
教学内容提要:
1,I/O标准流类;
2,文件流类;
3,预定义类型的输入输出;
4,用户自定义类型的输入输出教学重点:格式化输入输出及重载输入输出运算符 。
教学难点:格式化输入输出及重载输入输出运算符 。
教学进度,P242~P261
教学过程:
22.1 C++为何建立自己的输入输出系统
因为在 C++中用户需要定义众多的自定义类型,但是 C语言的输入输出系统不支持用户自定义的类型。请看下面的类,
class my_class{
int i;
float f;
char *str;
} obj;
对此类类型,在 C语言中下面的语句是不能接受的,
printf(" % my_class",obj);
C++的流类比 C的输入输出函数具有更大的优越性。
22.2 C++的流库及其基本结构
22.2.1 C++的流在 C++中,流类是为输入输出提供的一组类,
它们都放在流库中。
流总是与某一设备相联系的(例如键盘、屏幕或硬盘等),通过使用流类中定义的方法,就可以完成对这些设备的输入输出操作。
流具有方向性,与输入设备 (如键盘 )相联系的流称为输入流 ;与输出设备 (如屏幕 )相联系的流称为输出流 ;与输入输出设备 (如磁盘 )相联系的流称为输入输出流。
C++中包含几个预定义的流对象,,
标准输入流 cin 与标准输入设备相关联
标准输出流 cout 与标准输出设备相关联
非缓冲型的标准出错流 cerr 与标准错误输出设备相关联 (非缓冲方式 )
缓冲型的标准出错流 clog 与标准错误输出设备相关联 (缓冲方式 )
在缺省情况下,指定的标准输出设备是屏幕,标准输入设备是键盘。
22.2.2 流类库
C++流类库具有两个平行的基类,即
streambuf类和 ios类,所有其他的流类都是从它们直接或间接地派生出来的其中,
ios类为输入输出操作在用户一方的接口,
负责高层操作,
streambuf类为输入输出操作在物理设备一方的接口,负责低层操作。
ios
istream ostream
istrstream
ifstream
istream_withassign ostream_withassign
ofstream
ostrstream
iostream
stdiostreamfstream strstream
streambuf
stdiobuffilebuf strstreambuf
图 各类之间的关系
22.3 预定义类型的输入输出
22.3.1无格式输入输出基于 C++类库的输入输出需使用两个流对象 cin和 cout,还要用与之相配套的两个输入输出运算符,>>”和,<<”,其一般的格式为
cin>>变量 ; // 输人
cout<< 常量或变量 ; // 输出
1,输出运算符从运算符角度来看,输出通过输出运算符,<<”
来完成的,输出运算符,<<” 也称插入运算符,
它是一个双目运算符,有两个操作数,左操作数为 ostream类的一个对象 ( 如 cout),右操作数为一个系统预定义类型的常量或变量 。 例如
cout<<"This is a string.\n";
完成的功能为写字符串,This is a string.,到流对象 cout,cout为标准输出流,通常为屏幕。
2,输入运算符从运算符角度来看,输入操作通过输入运算符,>>”来完成 。 输入运算符,>>”
也称提取运算符,它也是一个双目运算符,
有两个操作数,左面的操作数是 istream
类的一个对象 (cin),右面的操作数是系统预定义的任何数据类型的变量 。 例如,
int x;
cin>>x;
此时,用户从键盘输入的数值会自动地转换为变量 x的类型,并存入变量 x内。
22.3.2 格式化输入输出
C++提供了两种进行格式控制的方法:
一种是使用 ios类中有关格式控制的成员函数进行格式控制;
另一种是使用称为操纵符的特殊类型的函数进行格式控制。
1,用 ios类的成员函数进行格式控制格式控制主要是通过对状态标志字的操作来完成的。
在 ios类的 public部分定义了一个枚举,
它的每个成员分别定义状态标志字的一个位,每一位都称为一个状态标志位。
enum{
skipws =0x0001,/ / 跳过输入中的空白,可用于输出
left =0x0002,// 左对齐输出,可用于输出
right =0x0004,// 右对齐输出,可用于输出
internal =0x0008,// 在符号位和基指示符后填入字符,
//可用于输出
dec =0x0010,// 转换基制为十进制数,可用于输入
//或输出
oct =0x0020,// 转换基制为八进制数,可用于输入
//或输出
hex =0x0040,// 转换基制为十六进制数,可用于输
//入或输出
showbase =0x0080,// 在输出时显示基指示符,可用于
//输入或输出
showpoint =0x0100,// 在输出时显示小数点,可用于输出
uppercase =0x0200,//十六进制输出时,表示制式和表示数
//值的字符 一律为大写,可用于输出
showpos =0x0400,//对正整数显示正号,可用于输出
scientific =0x0800,//用科学表示法显示浮点数,可用于输出
fixed =0x1000,//用定点形式显示浮点数,可用于输出
unitbuf =0x2000,//在输出操作后立即刷新所有流,可用
//于输出
stdio =0x4000,//在输出操作后刷新 stdout和 stderr,可用
//于输出
};
这些枚举元素的值有一个共同的特点,
分别使二进制表示的状态标志字的不同位为,1”,如,
skipws 0x0001 0000 0000 0000 0001
left 0x0002 0000 0000 0000 0010
right 0x0004 0000 0000 0000 0100
表 控制输入输出格式的成员函数函 数 原 型 功 能
long ios∷ setf(long flags);
long ios∷ unsetf(long flags);
long ios∷ flags();
long ios∷ flags(long flags);
int ios∷ width();
int ios∷ width(int w);
int ios∷ precision(int p);
char ios∷ fill();
char ios∷ fill(char ch);
设置状态标志 flags
清除状态标志,并返回前状态标志测试状态标志设置标志 flags,并返回前状态标志返回当前的宽度设置值设置域宽 w,返回以前的设置设置小数位数 p,返回以前的小数位数返回当前的填充字符设置填充字符 ch,返回当前的填充字符例 22.1 成员函数进行格式控制 。
#include<iostream.h>
main()
{ cout<<"x_width="<<cout.width()<<endl;
cout<<"x_fill="<<cout.fill()<<endl;
cout<<"x_precision="<<cout.precision()<<endl;
cout<<123<<" "<<123.45678<<endl;
cout<<"_________________________________\n";
cout<<"*** x_width=10,x_fill=,x_precision=4 ***\n";
cout.width(10);
cout.precision(4);
cout<<123<<" "<<123.45678<<" "<<234.567<<endl;
cout<<"x_width="<<cout.width()<<endl;
cout<<"x_fill="<<cout.fill()<<endl;
cout<<"x_precision="<<cout.precision()<<endl;
cout<<"_________________________________\n";
cout<<"*** x_width=10,x_fill=&,x_precision=4 ***\n";
cout.fill('&');
cout.width(10);
cout<<123<<" "<<123.45678<<endl;
cout.setf(ios::left);
cout.width(10);
cout<<123<<" "<<123.45678<<endl;
cout<<"x_width="<<cout.width()<<endl;
cout<<"x_fill="<<cout.fill()<<endl;
cout<<"x_precision="<<cout.precision()<<endl;
return 0;
}
程序运行结果如下,
x_width=0
x_fill=
x_precision=0
123 123.45678
-----------------------------
*** x_width=10,x_fill=,x_precision=4 ***
123 123.4568 234.567
x_width=0
x_fill=
x_precision=4
-----------------------------
*** x_width=10,x_fill=&,x_precision=4 ***
&&&&&&&123 123.4568
123&&&&&&& 123.4568
x_width=0
x_fill=&
x_precision=4
C++提供的预定义操纵符如下,
1,dec 以十进制形式输入或输出整型数,可用于输入或输出
2,hex 以十六进制形式输入或输出整型数,可用于输入或输出。
3,oct 以八进制形式输入或输出整型数,可用于输入或输出
4,ws 用于在输入时跳过前导的空白符,可用于输入。
5,endl 插入一个换行符并刷新输出流,仅用于输出。
6,ends 插入一个空字符’ \0’,通常用来结束一个字符串,仅用于输出
7,flush 刷新一个输出流,仅用于输出
8,setbase(int n) 设置转换基格式为为 n( n的取值为 0,8、
10或 16),n的缺省值为 0,即表示采用十进制,仅用于输出。
9,resetiosflags(long f) 关闭由参数 f指定的格式标志,可用于输入或输出。
10,setiosflags(long f) 设置由参数 f指定的格式标志,可用于输入或输出。
11,setfill(int ch) 设置 ch为填充字符,缺省时为空格,可用于输入或输出
12,setprecision(int n) 设置小数部分的位数,可用于输入或输出
13,setw(int n) 设置域宽为 n,可用于输入或输出例 22.2 操纵符的使用 。
#include<iostream.h>
#include<iomanip.h>
main()
{cout<<setw(10)<<123<<567<<endl; //①
cout<<123<<setiosflags(ios::scientific)<<setw(20) //②
<<123.456789<<endl;
cout<<123<<setw(10)<<hex<<123<<endl; //③
cout<<123<<setw(10)<<oct<<123<<endl; //④
cout<<123<<setw(10)<<dec<<123<<endl; //⑤
cout<<resetiosflags(ios::scientific)<<setprecision(4) //⑥
<<123.456789<<endl;
cout<<setiosflags(ios::left)<<setfill('#')<<setw(8) //⑦
<<123<<endl;
cout<<resetiosflags(ios::left)<<setfill('$')<<setw(8) //⑧
<<456<<endl;
return 0;
}
程序运行结果为,
123567 ①
123 1.234567e+02 ②
123 7b ③
7b 173 ④
173 123 ⑤
123.4568 ⑥
123##### ⑦
$$$$$456 ⑧
22.4.1 重载输出运算符,<<”
定义输出运算符,<<”重载函数的一般格式如下,
ostream& operator<<(ostream& out,class_name&
obj)
{
out<<obj.item1;
out<<obj.item2;
..,
out<<obj.itemn;
return out;
}
22.4 用户自定义类型的输入输出
22.4.2 重载输入运算符,>>”
定义输入运算符函数,>>”重载函数的一般格式如下,
istream& operator>>(istream& in,class_name&
obj)
{
in>>obj.item1;
in>>obj.item2;
.,,
in>>obj.itemn;
return in;
}
例 22.5 输出运算符,<<”重载 。
#include<iostream.h>
class coord {
int x,y;
public:
coord(int i=0,int j=0) { x=i; y=j;}
friend ostream& operator<<(ostream& stream,coord& ob);
};
ostream& operator<<(ostream& stream,coord& ob)
{ stream<<ob.x<<","<<ob.y<<endl; return stream; }
main()
{ coord a(55,66),b(100,200);
cout<<a<<b;
return 0; }
例 22.6 输入运算符,<<”重载 。
#include<iostream.h>
class three_d {
public:
three_d(int a,int b,int c)
{ x=a; y=b; z=c; }
friend ostream& operator<<(ostream& output,three_d& ob);
friend istream& operator>>(istream& itput,three_d& ob);
private:
int x,y,z;
};
ostream& operator<<(ostream& output,three_d& ob)
{ output<<ob.x<<",";
output<<ob.y<<",";
output<<ob.z<<endl;
return output; }
istream& operator>>(istream& input,three_d& ob)
{
cout<<"Enter x,y,z value:";
input>>ob.x;
input>>ob.y;
input>>ob.z;
return input;
}
main()
{
three_d obj(10,20,30); // 定义类 three_d的对象 obj
cout<<obj; // 输出对象 obj的成员值
cin>>obj; // 输入对象 obj的各成员值,将原值覆盖
cout<<obj; // 输出对象 obj的成员值 ( 新值 )
return 0;
}
小结:
1,C++中的流类
2、格式化输入输出(成员函数和操作符)
3、重载输入输出运算符( >>和 <<)
作业:
P275~P276 7.12