Upload
whitney-grant
View
110
Download
4
Embed Size (px)
DESCRIPTION
第八章 输入输出类层次. 流:用于输入输出地一组类 主要内容:文本流、二进制流. ios. cout. ostream. istream. cin. clog. cerr. iostream. iostream.h. ifstream. ofstream. fstream. 流类的继承体系. 输入流和输出流 C ++无专门的输入输出语句,是由流库完成;流与特定的设备相联系。. 输出设备. 文件. 程序. 输入设备. cout.operator
Citation preview
第八章 输入输出类层次第八章 输入输出类层次
流:用于输入输出地一组类主要内容:文本流、二进制流
输入流和输出流C ++无专门的输入输出语句,是由流库完成;流与特定的设备相联系。
iostream.h
流类的继承体系
ios
ostream istreamclog
fstream
iostream
cerr
cin
ofstream ifstream
cout
输出流 cout : 输出流 ostream 类的一个预定义对象
与标准输出设备(终端屏幕)相联系
ostream 中重载了 << 运算符(插入运算符)
插入运算符 <<: ostream& operator<<( 类型 );
// 重载形式:注意优先级和结合顺序
程序
输入设备
输出设备
文件
cout<<“string”; cout.operator<<(“string”);
11.1.2 输入流 cin>>i; cin.operator>>(i);
>> 析取运算符:跳过开始空白字符。
char ch;
cin>>ch; // 输入“ x” ,读入‘ x’
注意: C ++编译器将根据对象类型选用相应版本的重载 <<(>>) 运算符函数,用户不必关心。
>> 读入一个字符串时,空格作为串的终止。
char buffer[20];
cin>>buffer; // 输入“ Jack Spart” ,读入“ Jack”
类型不符,返回零值,并终止程序。 int readints( ) { int v[10]; for(int i=0; i<10;i++) { if(cin>>v[i]) continue; return i; } //…… }
输入: 1 2 3 4 5. 6 7 8
11.1.4 重载插入和析取运算符(对用户定义类型) class Complex {
double rpart, ipart;
public:
friend ostream&operator<<(ostream &s, Complex &c);
//……
};第一个参数是流
第二个参数是要输入输出的对象
返回流的引用
#include<iostream.h> class Complex { double rpart, ipart; public: Complex(double r=0.0, double i=0.0) { ipart=i; part=r; } friend ostream&operator>>(ostream &, Complex &); friend ostream&operator<<(ostream &, Complex &); };
istream& operator>>(istream& s, Complex &c) { s>>’(‘>>c.rpart>>’,’>>c.ipart>>’)’; return s; } ostream& operator>>(ostream& s, Complex &c) { s<<’(‘<<c.rpart<<’,’<<c.ipart<<’)’; return s; } void main( ) { Complex c; cin>>c; cout<<“Complex:”<<c<<endl; }
11.2 格式化输入 / 输出用 ios 类中定义的格式成员函数: class ios { //…… public: int width(int w); // 设置字段宽度 int width( ) const; // 返回设置字段的宽度
char fill(char); // 设置填充字符 char fill( ) const; // 返回设置的填充字符
long flags(long f); long flags( ) const; long setf(long setbits, long field); long setf(long); long unsetf(long); int precision(int); // 设置浮点数精度 int precision( ) const; // 返回设置的浮点数精度 //…… };
函数的使用:
输入流: char buffer[20];
cin.width(20);
cin>>buffer;
输出流: cout.width(4);
cout<<‘(‘<<12<<‘) ’;
cout.width(4);
cout.fill(‘#’);
cout<<‘(‘<<12<<‘) ’;
( 12)
( ##12)
Width( ) 作用于输入 / 输出的数字或串
数据的长度超过 width ,忽略设置,按数据实际长度显示; cout.width(4); cout<<‘(‘<<121212<<‘) ’;每次插入操作后, width 被置 0 ; cout.width(4); cout.fill(‘#’); cout<<‘(‘<<12<<“),(“ <<12<<‘) ’;
(121212)
( ##12) , (12)
11.2.2 格式状态
Ios 中用枚举记录标志,控制 I/O
class ios {
public:
enum{
skipws=01, // 析取操作忽略空白字符 left=02, right=04, internal=010, // 值按右对齐,符号按左对齐 dec=020, oct=040, hex=0100, showbase=0200, showpoint=0400, //float,double 显示小数和尾数后的零 uppercase=01000, showpos=02000, // 在正整数前插入“ +” 号 scientific=04000, // 科学计数法,小数点前一位数字
//…… }; //…… };
可用下列函数设置、读取、取消标志位; long flags( ) // 返回当前格式化标志值 long flags(long f) // 设置标志值 f ,并返回上次标志值 long setf(long f) // 设置标志位 f ,并返回上次标志位 long unsetf(long f) // 取消在 f 中设置的标志位,并返回上次标志位
举例: void your_function( )
{
long old_options=cout.flags(ios::left | ios::oct | ios::showpoint);
//……
cout.flags(old_options);
}
相抵触的标志不能同时设置,如: ios::dec 和 ios::oct带伪参数的 setf( ) 指明设置哪类选项,自动清除与新设置矛盾的旧选项。 cout<<1234<<‘ ‘<<;
cout.setf(ios::oct, ios::basefield); cout<<1234<<‘ ‘<<; cout<<1234<<‘ ‘<<;
cout.setf(ios::hex, ios::basefield); cout<<1234<<‘ ‘<<;
原选项基础上增加 showbase
伪参数:基数设置位
作用范围:下一标志位设置
cout.flags(cout.flags( ) | ios::showbase);
cout.setf(ios::showbase);
结果: 1234 2322 2322 4d2
11.3 控制符函数控制不方便
int x=1, y=2cout.width(5);cout<<x;cout.width(4);cout<<y;
宽度控制符
预定义控制符有: hex dec oct—— 指定基数,缺省 dec ws—— 用于输入流,略去空白 endl—— 换行 ends—— 插入一个 NULL(0) 字符,结束一个字符串 flush—— 强制将流从缓冲区写入相应设备 setfill(char f)—— 设置填充字符,缺省委空格 setprecision(int p)—— 设浮点数精度,缺省为 6 …..
int x=1, y=2;
cout<<setw(5)<<x<<setw(4)<<y;
控制符如 endl
11.5 文件和流处理文件的类在 fstream.h 中定义。文件输入输出: 1 、创建流对象 2 、使用流的成员函数打开文件 文件与流建立起联系
输出流对象 my_file 与文件 hello.dat 相联系
#include<iostream.h> #lnclude<fstream.h> void main( ) { ofstream my_file; my_file.open(“hello.dat”, ios::out); //…… }
11.5.1 打开文件输入打开文件用 ifstream 类;输出打开文件用 ofstream 类;
输入 输出打开文件用 fstream 类。
打开文件: void open(char* name, int mode, int file_attrb);mode 为下列一些方式: ios::app—— 附加方式写到流 ios::ate—— 打开文件,并把文件指针移到文件尾 ios::in—— 为读打开 ios::out—— 为写打开 ios::trunc—— 如文件存在,舍去文件内容 ios::nocreate—— 文件不存在,则失败 ios::noreplace—— 文件存在,则失败file_attrb 文件属性 : 普通文件、只读文件、隐藏文件。
#include<iostream.h> #lnclude<fstream.h> void main( ) { ofstream my_file; my_file.open(“hello.dat”); my_file<<“Hello world”<<endl; my_file.close( ); }
ofstream my_file(“hello.dat”);
11.5.2 按正文方式读文件 #lnclude<fstream.h> void main( ) { char string1[20], string2[20]; ifstream my_file(“hello.dat”); my_file>>string1; my_file>>string2; cout<<string1<<‘ ‘<<string2<<endl; my_file.close( ); }
11.5.3 按二进制方式读 / 写文件 读写的数据无含义,不用 << 和 >> ,而是 get( ) 和 put( )
istream & get(char &c); ostream& put(char &c);写数据: #lnclude<fstream.h> void main( ) { char my_char; static char string[ ]=“Hello world”; int i=0; ofstream my_out_file(“hello.dat”); while(string[i]) my_out_file.put (string[i++] ); my_out_file.close( ); }
读数据: #lnclude<fstream.h> void main( ) { char my_char; int i=0; ifstream my_in_file(“hello.dat”); while(my_in_file) { my_in_file.get(my_char ); cout<<my_char; } my_in_file.close( ); }
11.5.4 使用 read( ) 和 write( ) 函数一次读写多个字符,其原型:
istream & read(unsigned char* char_buffer, int number_bytes);
ostream& write(const unsigned char* char_buffer , int number_bytes);
#lnclude<fstream.h>
#include<string.h>
void main( )
{
static char hello_buf[ ]=“hellow world.\n”;
ofstream my_out_file(“hello.dat”);
my_out_file.write(hello_buf, sizeof(hello_buff));
ifstream my_in_file(“hello.dat”);
my_in_file.read(hello_buf, sizeof(hello_buf));
my_in_file.close( ); my_out_file.close( );
}
11.5.5 使用文件指针 读指针 写指针用 istream 中成员函数 seekg( ) 定位;用 ostream 中成员函数 seekp( ) 定位。其原型: istream& seekg( streamoff file_offset, seek_dir org); ostream& seekp( streamoff file_offset, seek_dir org);seek_dir三种取值: ios::beg ios::end ios::cur
#lnclude<fstream.h> #include<string.h> const int INDEX=15; class Entry{ public: char name[20]; float owes; } my_data[INDEX], my_record;
读写指针在文件中位置 指出指针相对于何处
void main( ) { ifstream my_file1(“file.dat”); my_file1.seekg(9*sizeof(Entry), ios::beg); my_file1.read((char*) &my_record, sizeof(Entry)); my_file1.close( ); ofstream my_file2(“file.dat”); my_record.owes=442.96; my_file2.seekp(9*sizeof(Entry), ios::beg); my_file2.write((char*)& my_record, sizeof(Entry)); my_file2.close( ); }