以下为个人学习笔记和习题整理
课程:计算机程序设计(C++)- 西安交通大学 @ 中国大学 MOOC
https://www.icourse163.org/course/XJTU-46006
# 课堂笔记
# 流与流库
# 流
流是指从一个位置向另一个位置传输的一连串数据的集合。
在输入输出过程中,会在内存中为每一个数据流开辟一个内存缓冲区,用来存数据。从而匹配不同工作效率的对象。
| graph LR | |
| A[键盘]  | |
| B[扫描仪] | |
| C[文件] | |
| A --> D[abc...输入流] | |
| B --> D | |
| C --> D | |
| D --> E[进程使用的内存区] | |
| F[显示器] | |
| G[文件] | |
| H[打印机] | |
| E --> I[abc...输出流] | |
| I --> F | |
| I --> G | |
| I --> H | 
# 输入输出流类库结构

- 定义了基本的格式控制符、状态设定函数等等
- 定义了输入流类、输出流类
- 定义了标准输入、输出流对象。自动包含 <ios>,<ostream>等
- 定义文件操作流类
# 标准输入流
从标准输入设备(键盘)流向程序的数据。
一般使用 cin 流对象进行输入。
| int a, b; | |
| cin >> a >> b; // 从键盘输入 2 个整数 | 
>> 的特点:
- 符号重载
- 以空格、回车做分隔符
cin 是 istream 类的对象,除了 >> 符号外,常用函数如下:
| 函数 | 功能 | 
|---|---|
| read | 无格式输入指定字节数 | 
| get | 从流中提取字符,包括空格 | 
| getline | 从流中提取一行字符 | 
| ignore | 提取并丢弃流中指定字符 | 
| peek | 返回流中下一个字符,但不从流中删除 | 
| gcount | 统计最后输入的字符个数 | 
| seekg | 移动输入流指针 | 
| tellg | 返回输入流中指定位置的指针值 | 
# istream 类的 get 函数
| // 无参数,直接返回数据 | |
| int get(); | |
| // 参数是引用类型的变量,读取一个字符,不跳过空白字符 | |
| istream& get( char& rch ); | |
| istream& get( char* pch, int nCount, char delim = '\n' ); | |
| // 参数 1:char 类型的指针,读取多个字符,放到 pch 中 | |
| // 参数 2:读取字符数量上限 | |
| // 参数 3:读多个字符至 '\n' 结束,不提取 '\n' | 
| #include<iostream> | |
| using namespace std; | |
| int main() | |
| { | |
| char c; | |
| cout<<"enter a sentence:"<<endl; | |
| while(1) | |
| 	{ | |
| c=cin.get();// 可以用 cin.get (c) 替换 | |
| if(c=="\n") | |
| 		{ | |
| break; | |
| 		} | |
| 		else | |
| 		{ | |
| cout<<c; | |
| 		} | |
| 	} | |
| return 0; | |
| } | 
| #include<iostream> | |
| using namespace std; | |
| int main() | |
| { | |
| char ch[80]; | |
| cout<<"enter a sentence:"<<endl; | |
| 	// enter a sentence: | |
| 	// Xi'an Jiaotong University|Shanghai Jiaotong University | |
| cin.get(ch,70,'|'); | |
| cout<<ch<<endl; | |
| 	// Xi'an Jiaotong University | |
| cin.ignore(1); // 扔掉 | | |
| cin.get(ch,70); | |
| cout<<ch<<endl; | |
| 	// Shanghai Jiaotong University | |
| return 0; | |
| } | 
# istream 类的 getline 函数
| istream& getline(char* pch, int nCount, char delim = '\n') | |
| // 参数 1:读取多个字符,放到 pch 中 | |
| // 参数 2:读取字符数量上限 | |
| // 参数 3:读取字符至 delim 结束,终止字符被舍弃 | 
| #include<iostream> | |
| using namespace std; | |
| int main() | |
| { | |
| char ch[80]; | |
| cout<<"enter a sentence:"<<endl; | |
| 	// enter a sentence: | |
| 	// Xi'an Jiaotong University|Shanghai Jiaotong University | |
| cin.getline(ch,70,'|'); // 读 69 个字符或遇 '|' 结束 | |
| cout<<ch<<endl; | |
| 	// Xi'an Jiaotong University | |
| 	// 不需要 cin.ignore (1); | |
| cin.getline(ch,70); // 读 69 个字符或遇 '\n' 结束 | |
| cout<<ch<<endl; | |
| 	// Shanghai Jiaotong University | |
| return 0; | |
| } | 
# 比较
| cin.get(<字符数组>, <字符个数n>, <终止字符>) | |
| cin.getline(<字符指针>, <字符个数n>, <终止字符>) | 
- 相同之处: - 从输入流提取 n-1个字符放入数组,因为最后一个位置要放字符数组的结束标准。
- 读取成功,则函数返回值是非 0 值。
- 若遇到文件结束符,则返回值为 0。
 
- 从输入流提取 
- 不同之处: 
 当读到终止字符时,- cin.getline()—— 将指针移到终止字符之后。- cin.get()—— 将指针移到终止字符处。
 则下次继续读取时的位置就不同。
# 标准输出流
流向标准输出设备(显示器)的数据。
一般使用 cout 流对象进行输出操作。
例如,用流插入运算符 << 输出数据。
cout 是 ostream 类的对象,除了 << 符号外,常用函数如下
| 函数 | 功能 | 
|---|---|
| put | 无格式插入一个字节 | 
| write | 无格式插入一字节序列 | 
| flush | 刷新输出流 | 
| seekp | 移动输出流指针 | 
| tellp | 返回输出流中指定位置的指针值 | 
# 用流对象的成员函数控制输出格式
- 设置状态标志流成员函数 - setf- cout.unsetf(ios::状态标志); 
- 清除状态标志流成员函数 - unsetf- cout.unsetf(ios::状态标志); 
- 设置域宽流成员函数 - width
 设置显示数据占多少个字节宽- cout.width(n); - 只对下一次流输出有效,输出完成后该函数的作用就消失。 
- 设置实数的精度流成员函数 - precision- cout.precision(n); - 参数 - n在十进制小数形式输出时,代表有效数字。
 在以- fixed形式和- scientific形式输出时,代表小数位数。
- 填充字符流成员函数 - fill- cout.fill(ch); - 用 - ch去填充无输出内容的位置。
在
cout.setf(ios::状态标志)和cout.unsetf(ios::状态标志)中常用的状态标志如下:
| 状态标志 | 功能 | 
|---|---|
| left | 输出数据在本域宽范围内左对齐 | 
| right | 输出数据在本域宽范围内右对齐 | 
| dec | 设置整数的基数为 10 | 
| oct | 设置整数的基数为 8 | 
| hex | 设置整数的基数为 16 | 
| showpoint | 浮点数输出时,强制显示小数点 | 
| uppercase | 在以科学表示法格式 E 和以十六进制输出字母时用大写表示 | 
| scientific | 用科学表示法格式显示浮点数 | 
| fixed | 用定点格式(固定小数位数)显示浮点数 | 
在引用这些值之前要加上
ios::,如果有多项标志,中间则用|分隔。
| #include<iostream> | |
| using namespace std; | |
| int main() | |
| { | |
| 	// 设左对齐,以一般实数方式显示 | |
| cout.setf(ios::left|ios::showpoint); | |
| 	// 设置除小数点外有效数字为 5 | |
| cout.precision(5); | |
| cout<<123.456789<<endl; | |
| 	// 123.46 | |
| 	// 设置显示区域宽 10 | |
| cout.width(10); | |
| 	// 在显示区域空白处用 * 填充 | |
| cout.fill('*'); | |
| 	// 清除状态左对齐 | |
| cout.unsetf(ios::left); | |
| 	// 设置右对齐 | |
| cout.setf(ios::right); | |
| cout<<123.456789<<endl; | |
| 	// ****123.46 | |
| 	// 设左对齐,以固定小数位数显示 | |
| cout.setf(ios::left|ios::fixed); | |
| 	// 设置实数显示 3 位小数 | |
| cout.precision(3); | |
| cout<<999.123456<<endl; | |
| cout<<99.123456<<endl; | |
| 	// 999.123 | |
| 	// 99.123 | |
| 	// 清除状态左对齐和定点格式 | |
| cout.unsetf(ios::left|ios::fixed); | |
| 	// 设置左对齐,以科学计数法显示 | |
| cout.setf(ios::left|ios::scientific); | |
| 	// 设置保留 3 位小数 | |
| cout.precision(3); | |
| cout<<123.45678<<endl; | |
| 	// 1.235e+002 | |
| return 0; | |
| } | 
# 用 C++ 流格式控制符控制输出格式
多数 C++ 流格式控制符与前面的成员函数有等价对应的关系,两者都可实现同样的功能。C++ 流格式控制符一般与符号 << 联用。
| 控制符 | 功能 | 
|---|---|
| dec | 设置后面的整数按 10 进制方式显示 | 
| hex | 设置后面的整数按 16 进制方式显示 | 
| oct | 设置后面的整数按 8 进制方式显示 | 
| endl | 输出一个换行符并刷新输出流 | 
| setfill(c) | 设置填充符 (默认为空格) | 
| setprecision(n) | 设置实数精度 n, 原理和成员函数 precision一样 | 
| setw(n) | 设置域宽 n | 
| setiosflags(flags) | 设置状态标志,多个用 |分隔 | 
| resetiosflags(flags) | 清除状态标志,多个用 |分隔 | 
setiosflags和resetiosflags的常用状态标志
| 状态标志 | 功能 | 
|---|---|
| ios::left | 按域宽左对齐输出 | 
| ios::right | 按域宽右对齐输出 | 
| ios::fixed | 固定小数位数输出 | 
| ios::showpos | 强制设置显示正号 | 
| ios::uppercase | 科学记数法或 16 进制输出数据时字母大写 | 
| ios::lowercase | 科学记数法或 16 进制输出数据时字母小写 | 
| #include <iostream> | |
| #include <iomanip> | |
| using namespace std; | |
| int main() | |
| { | |
| int a=128; | |
| 	// 以 10 进制形式输出 | |
| cout<<"dec:"<<dec<<a<<endl; | |
| 	// dec:128 | |
| 	// 以 16 进制形式输出 | |
| cout<<"hex:"<<hex<<a<<endl; | |
| 	// hex:80 | |
| 	// 以 8 进制形式输出 | |
| cout<<"oct:"<<oct<<a<<endl; | |
| 	// oct:200 | |
| char pt[]="xi'an"; | |
| 	// 域宽为 10,输出字符串 | |
| cout<<setw(10)<<pt<<endl; | |
| 	//      xi'an	 | |
| 	// 指定域宽 10,输出字符串,空白处以 "*" 填充 | |
| cout<<setfill('*')<<setw(10)<<pt<<endl; | |
| 	// *****xi'an | |
| double B=27.123456789; | |
| 	// 按指数形式输出,8 位小数 | |
| cout<<setiosflags(ios::scientific)<<setprecision(8); | |
| 	// 输出 B 值 | |
| cout<<"B="<<B<<endl; | |
| 	// B=2.71234568e+001 | |
| 	//4 位小数 | |
| cout<<"B="<<setprecision(4)<<B<<endl; | |
| 	// B=2.7123e+001 | |
| 	// 清除格式设定 | |
| cout<<resetiosflags(ios::scientific); | |
| 	// 改为小数形式输出,小数点后 6 位 | |
| cout<<"B="<<setiosflags(ios::fixed)<<setprecision(6)<<B; | |
| 	// B=27.123457 | |
| cout<<endl; | |
| return 0; | |
| } | 
# 文件操作基础
文件流类是用于操作文件的标准 C++ 类。
ifstream 从文件读取数据fstream 可读取插入ofstream 向文件插入数据
这三个类包含在头文件 <fstream> 中
- 文件操作的基本步骤- 定义一个文件流对象
- 打开文件
- 读 / 写文件
- 关闭文件
 
# 文件分类
- 文本文件: 
 是一种由若干行字符构成的计算机文件。其编码可以是 ASCII 码、UNICODE 码、GBK 编码等等。可以用文本编辑器编辑。
- 二进制文件: 
 除了上述以字符构成的文本文件,其他文件均称为二进制文件。典型的二进制文件有声音、动画、图像、视频等。
C++ 语言对这两种文件都可以进行创建、读写等操作。
# 定义一个文件流对象
ifstream 对象只进行读操作ofstream 对象只进行写操作fstream 对象既可以读文件,也可以写文件
# 打开文件
- 文件流类的成员函数 open(打开文件)
| void open (const char * filename, openmode mode) | 
- filename是文件名(如- e:\c++\file.txt),若缺少路径,则默认为当前目录。
- mode指文件打开方式,内容如下:
| 方式 | 功能 | 
|---|---|
| ios::in | 为输入(读)而打开文件 | 
| ios::out | 为输出(写)而打开文件 | 
| ios::ate | 打开文件,初始位置在文件尾部 | 
| ios::app | 所有输出附加在文件末尾 | 
| ios::trunc | 如果文件已存在则先删除该文件全部数据 | 
| ios::binary | 二进制方式打开文件 | 
每打开一个文件都有一个文件指针,
指针的开始位置由打开方式指定,
每次读写都从文件指针的当前位置开始。
- 还可以用文件流类的构造函数来打开文件,其参数和默认值与 open函数完全相同。
| // 在工程默认目录打开文件 grade.txt,只用于输入 | |
| ifstream file1; | |
| file1.open("grade.txt", ios::in); | |
| //ifstream 就是用于输入的,故第二个参数 ios::in 可以省略 | |
| // 打开文本文件 c:\msg.txt,只用于输出 | |
| ofstream file2; | |
| file2.open("c:\\msg.txt"); // 第二个参数 ios::out 省略 | |
| // 以二进制输入方式打开文件 c:\abc.bmp | |
| fstream file3; | |
| file3.open("c:\\abc.bmp",ios::binary|ios::in); | |
| // 二进制方式 | 只用于读入 | |
| // 用构造函数来打开二进制文件,用于输出 | |
| ofstream file("example.bin", ios::out|ios::binary); | 
# 关闭文件
- 关闭文件操作包括:把缓冲区数据完整地写入文件,添加文件结束标志,切断流对象和外部文件的连接。 
- 当一个流对象的生存期结束,系统也会自动关闭文件; 
- 若流对象的生存期没有结束,用 - close()关闭文件后,该流对象可以重用。
# 文本文件的读写
下面以 ifstream 、 ofstream 为例说明。
由于 ifstream 、 ofstream 类继承自流类 istream 和 ostream ,因此也可以使用常见的 IO 操作。
比如 >> 、 get 、 getline 常用于文本文件输入,而操作 << 、 put 常用于输出。
- 用符号 <<和put函数向文本文件写入一些文字
| #include <iostream> | |
| #include <fstream> // 必须包含的头文件 | |
| using namespace std; | |
| int main() | |
| { | |
| 	// 打开文件 | |
| ofstream out("file.txt"); | |
| 	// 如果 file.txt 文件存在,则打开,否则自动创建一个 | |
| if(!out) { | |
| cout<<"打开文件失败!"<<endl; | |
| return 1; | |
| 	} | |
| 	// 写文件 | |
| out<<"Welcome to "; | |
| char ch[]="Xi'an Jiaotong University."; | |
| int i=0; | |
| while(ch[i]!=0) // 使用 put 函数的示例 | |
| 	{ | |
| out.put(ch[i]); | |
| i++; | |
| 	} | |
| 	// 真正编程时只要用一条语句 out<<ch 即可 | |
| out.close(); // 关闭文件 | |
| return 0; | |
| } | 
- 用符号 >>和get函数读取文本文件
| #include <iostream> | |
| #include <fstream> | |
| using namespace std; | |
| int main() | |
| { | |
| 	// 打开文件 | |
| ifstream in("file.txt"); | |
| if(!in) | |
| 	{ | |
| cout<<"不可以打开文件"<<endl; | |
| return 1; | |
| 	} | |
| 	// 读文件 | |
| char ch[80]; | |
| in>>ch; // 读取第一个单词 Welcome | |
| cout<<ch; | |
| in>>ch; // 读取第二个单词 to | |
| cout<<ch; | |
| while(in) // 剩余部分用 get 函数读出并显示 | |
| 	{ | |
| char c=in.get(); | |
| if(in) { | |
| 			// 之所以要有 if 判断, | |
| 			// 是为了不输出最后一次读取的非正文数据 | |
| cout<<c; | |
| 		} | |
| 	} | |
| in.close(); // 关闭文件 | |
| return 0; | |
| } | 
- 如何判断读到达文件尾部
 当没有读到文件尾部时,ifstream对象in相当于一个true值,甚至直到读取完所有有效数据后,in仍然相当于true。这时再读取一次文件后,in才变成了相当于false值的对象。
# 二进制文件的读写
要根据 文件的定义格式 对二进制文件进行读写
比如 BMP 位图文件,是典型的二进制文件。
其文件头部是格式固定的信息,其中
前 2 字节用来记录文件为 BMP 格式,
接下来的 8 个字节用来记录文件长度,
再接下来的 4 字节用来记录 BMP 文件头的长度,等等。
因此,BMP 文件的读取方法是依次读取 2 字节、8 字节、4 字节的数据,再转化为字符或整数。
- 对二进制文件进行操作时,打开文件要指定方式 - ios::binary
- 从二进制文件输入数据,可调用 - istream流类提供的成员函数,
| istream& read(char* buffer, int len) | 
- 向二进制文件输出数据可调用 ostream流类提供的成员函数,
| ostream& write(const char* buffer,int len) | 
两个函数格式上差不多,
第一个参数是一个字符指针,用于指向输入输出数据所放的内存空间的地址。
第二个参数是一个整数,表示要输入输出的数据的字节数。
| #include<iostream> | |
| #include<fstream> | |
| using namespace std; | |
| class Student // 定义类 | |
| { | |
| 	// 建立学生信息类,包含姓名、班级、性别、年龄四个私有属性。 | |
| char Name[10]; | |
| char Class[10]; | |
| char Sex; | |
| int Age; | |
| public: | |
| 		// 构造函数 | |
| Student() { } | |
| Student( char *Name, char *Class, char sex, int age) | |
| 		{ | |
| strcpy(this->Name,Name); | |
| strcpy(this->Class,Class); | |
| Sex=sex; | |
| Age=age; | |
| 		} | |
| 		// 输出自身信息 | |
| void Showme() | |
| 		{ | |
| cout<<Name<<'\t'<<Class<<'\t'<<Sex<<'\t'<<Age<<endl; | |
| 		} | |
| }; | |
| int main() { | |
| 	// 程序运行后,先创建文件并写入信息,而后从文件读出信息 | |
| Student stu[3]={ | |
| Student("王二小","电气11",'m',27), | |
| Student("刘大明","机械01",'f',24), | |
| Student("李文化","生物12",'m',39) | |
| }; | |
| 	// 打开文件 | |
| ofstream file1("file.dat",ios::binary); | |
| if(!file1) { | |
| cout<<"文件打开失败!"; | |
| return 1; | |
| 	} | |
| 	// 写文件 | |
| for(int i=0;i<3;i++) { | |
| file1.write((char*)&stu[i],sizeof(stu[i])); | |
| 	} | |
| file1.close(); // 关闭文件 | |
| 	/////// 以下为读文件并显示出来 ////////// | |
| Student stu2; // 建立对象 | |
| 	// 打开文件 | |
| ifstream file2("file.dat", ios::binary); | |
| if(!file2) { | |
| cout<<"文件打开失败!"; | |
| return 1; | |
| 	} | |
| 	// 读文件 | |
| while(file2) | |
| 	{ | |
| file2.read((char*)&stu2,sizeof(stu2)); | |
| if(file2) { | |
| stu2.Showme(); | |
| 		} | |
| 	} | |
| 	// 关闭文件 | |
| file2.close(); | |
| return 0; | |
| } | 
# 二进制文件的顺序读写、随机读写
istream 类和 ostream 类提供成员函数 ,控制读写位置指针的移动,实现文件的随机读写。
| 文件内容 | |
|---|---|
| 文件刚打开时:读写位置指针 ➡️ | |
| 读写数据后自动移动 | |
| 读写位置指针 ➡️ | |
| ... | |
- istream类操作流读指针的成员函数
| istream& istream::seekg( long pos); | |
| // 读指针从流的起始位置向后移动由 pos 指定字节 | |
| istream& istream::seekg( long off, ios::seek_dir ); | |
| // 读指针从流的 seek_dir 位置移动,off 指定字节 | 
| ios::seek_dir值 | 功能 | 
|---|---|
| cur | 当前读指针所在的当前位置 | 
| beg | 文件流的开始位置 (文件头部) | 
| end | 文件流的结尾处 | 
| istream input; | |
| input.seekg ( -10 , ios::cur ); | |
| // 读指针以当前位置为基准,向前移动 10 个字节 | |
| input.seekg ( 10 , ios::beg ); | |
| // 读指针从流的开始位置,向后移动 10 个字节 | |
| input.seekg ( -10 , ios::end ); | |
| // 读指针从流的结尾,向前移动 10 个字节 | 
- ostream类操作流写指针的成员函数
| ostream& ostream::seekp ( long pos ) ; | |
| // 写指针从流的起始位置向后移动由参数指定字节 | |
| ostream& ostream::seekp ( long off , ios::seek_dir ); | |
| // 写指针从流的 seek_dir 位置移动由 off 指定字节 | |
| ostream& ostream::tellp () ; | |
| // 返回写指针当前所指位置值 | 
| #include<iostream> | |
| #include<fstream> | |
| using namespace std; | |
| class Student { ... }; | |
| int main() | |
| { | |
| Student stu; // 建立对象 | |
| 	// 打开文件 | |
| ifstream file("file.dat",ios::binary); | |
| if(!file) { | |
| cout<<"文件打开失败!"; | |
| return 1; | |
| 	} | |
| 	// 定位文件指针到文件末尾 | |
| file.seekg(0,ios::end); | |
| 	// 得到文件指针位置 (文件大小) | |
| int len=file.tellg(); | |
| 	// 读文件 | |
| for(int k=len/sizeof(stu)-1;k>=0;k--) | |
| 	{ | |
| file.seekg(k*sizeof(stu)); | |
| file.read((char*)&stu,sizeof(stu)); | |
| stu.Showme(); | |
| 	} | |
| file.close(); // 关闭文件 | |
| return 0; | |
| } | 
# 课堂讨论
- 使用 cin>>,cin.get(),cin.getline()读取字符串有什么区别?getline函数必须读取一行数据吗?
cin>>不能获取含有空格的字符串;
cin.getline()可以获取含有空格的字符串,但是不能获取换行的字符串;
cin.get()以上两种的功能均可实现,并且可以获取换行的字符串;
cin.getline()的指针停止在中止字符之后,即把中止字符从输入流中拿掉;
cin.get()的指针停止在终止字符位置,即不会把中止字符从输入流中拿掉。getline函数不是必须读取一行数据,getline也可以读取单个字符
- 请总结读写文本文件的步骤。
| // 包含头文件 | |
| #include<fstream> | |
| // 创建对象 | |
| ifstream in; | |
| // 打开文件 | |
| in.open("file.txt"); | |
| // 读或写 | |
| in>>a; | |
| // 关闭文件 | |
| in.close(); | 
- 读取文本文件时,一定要知道文件的格式吗? 
- 文本文件读写方法可以用于二进制文件读写吗? 
不可以。二进制数据解释成文本,有些在 ASCII 表中不存在,有些是不可视的字符,会出现乱码。
# 随堂练习
- 下列说法错误的是 。 
- 有一段程序如下: - char str[200]; - cin.get( str, 100, '*' ); - 利用上面代码从标准输入流获取一段文本,下列说法错误的是: 
- 为了舍去流中的一些字符,应该使用的输入流的成员函数是 。 
- 用语句 - cin.getline(ch,70,'*');从标准输入流获取一段字符,遇到- *时,停止读入文本,同时- *被从流中取出丢掉。
- 设置输出格式时,利用 setf 成员函数不能设置的显示属性是 。 
- 使用流操纵符(流格式控制符)控制输出格式,是将控制符号作为数据的一部分插入到输出流中。 
- 只用于读文件的流类是 。 
- 不论 - ifstream或- ofstream对象,打开文件都可以使用构造函数或 open 函数,这两种方式所使用的函数的参数可以完全一致。
- 假定 - in为- ifstream类的对象,用- in打开一个文件后,下面的代码用于读取文件内容:- while(in) // 读取文件内容 - {- char c=in.get(); - if(in) { - cout<<c; - }- }- 请问上面程序段划线的语句中使用 - if判别语句的原因是:
- 在标准输入流中常使用符号 - >>、- get函数、- getline函数输入数据,这些方式也可用于从文件流向应用程序输入数据,且使用方式不变。
- 在标准输出流中常使用符号 - <<、- put函数向屏幕输出数据,这些方式也可用于向文件流写入数据,且使用方式不变。
- 不论何种方式打开一个二进制文件,在文件打开方式(即第二个参数)中必须有 。 
- 二进制文件使用的读写成员函数是 。 
