350 likes | 602 Views
第 8 章 文件与数据输入输出. 教学目标. (1) 了解文件和流的概念; (2) 了解输入输出流类或标准I/O函数库的结构和机制; (3) 了解文件的打开与关闭操作及文件读写的基本方法。. 基本内容. 8.1 输入输出与标准库 8.2 标准输入流 8.3 标准输出流 8.4 文件. 8.1 输入输出与标准库. 标准库构成 标准函数库 从 C 语言中继承下来 C 格式的输入输出函数、字符与字符串处理函数、数学函数、时间日期函数、动态分配函数以及一些实用函数 标准类库 标准 C++ 的 I/O 流类、字符串类、数字类、异常处理和杂项类以及 STL 容器类
E N D
教学目标 • (1) 了解文件和流的概念; • (2) 了解输入输出流类或标准I/O函数库的结构和机制; • (3) 了解文件的打开与关闭操作及文件读写的基本方法。
基本内容 • 8.1 输入输出与标准库 • 8.2 标准输入流 • 8.3 标准输出流 • 8.4 文件
8.1 输入输出与标准库 • 标准库构成 • 标准函数库 • 从C语言中继承下来 • C格式的输入输出函数、字符与字符串处理函数、数学函数、时间日期函数、动态分配函数以及一些实用函数 • 标准类库 • 标准C++的I/O流类、字符串类、数字类、异常处理和杂项类以及STL容器类 • 由编译器厂商提供,与平台、厂商和编译器版本无关
输入输出流类库iostream • iostream类库提供了数百种I/O功能,其接口部分分别包含在几个头文件中: • 无格式I/O和格式化I/O:头文件iostream • 格式化I/O :包含头文件iomanip • 文件处理操作 :包含头文件fstream
ios istream ostream ifstream iostream ofstream fstream 输入/输出流类的继承层次结构
8.2 标准输入流 • cin是类istream内置的标准流类对象,能构成从键盘到内存的标准输入流。通过流提取运算符“>>”,变量从流中提取数据。 • “>>”会自动忽略所有的空白字符,因此无法输入包含空格符的字符串。如: char name[20]; cin>>name; • 假如输入姓名“Tom Hanks”时,变量name中只有“Tom”
输入流对象的成员函数get() • 这个函数有3种重载形式: • cin.get() • 用于从指定的输入流中读取一个字符,函数的返回值即为读入的字符。 • cin. get(ch) • 用于从指定的输入流中读取一个字符,并将该字符赋给字符型变量ch。 • cin.get(字符数组buf, 字符个数n, 结束符delim) • 用于从指定的输入流中读取n-1个字符,并将这些字符赋给字符数组buf。如果还没有读取完n-1个字符之前就遇到结束符delim,则可提前结束读取过程。结束符delim的默认值为换行符‘\n’ 。
例8-2:包含空格的字符串的输入与输出 #include <iostream> using namespace std; int main() { char ch1, ch2, ch3, buf1[50], buf2[50]; cout << "请输入一个句子:"; cin >> buf1; cout << "使用运算符<<读取句子:" << buf1 << endl; ch1 = cin.get(); ch2 = cin.get(); cout << "使用cin.get()继续读取:" << ch1 << endl; cout << "使用cin.get()继续读取:" << ch2 << endl; cin.get(ch3); cout << "使用cin.get(ch3)继续读取:" << ch3 << endl; cin.get(buf2, 50); cout << "使用cin.get(buf2, 50)继续读取:" << buf2 << endl; return 0; }
输入流对象的成员函数 • get • Extracts characters from the stream up to, but not including, delimiters. • getline • Extracts characters from the stream (extracts and discards delimiters). • read • Extracts data from the stream. • ignore • Extracts and discards characters. • peek • Returns a character without extracting it from the stream. • gcount • Counts the characters extracted in the last unformatted operation.
8.3 标准输出流 • 输出流类ostream的标准输出流对象cout通过流插入运算符“<<”,把变量的值从内存输出到标准输出设备上。 • 系统会自动根据不同的数据类型采用不同的默认方式输出。 • 特殊要求的输出格式,需要格式化I/O • 使用流操纵符对输出操作进行格式化 • 使用ios类的格式控制成员函数进行格式化
1. 使用流操纵符对输出操作进行格式化 • 不带参数的流操纵符 • endl • dec/oct/hex 十/八/十六进制 • 带参数的流操纵符 (注意:需包含头文件iomanip) • setbase(int base) 设置数制转换基数为base • setfill(int ch) 将填充字符设置为ch • setprecision(int p) 设置数字精度 • setw(int w) 将域宽设置为w • setiosflags(fmtflags flags) 开启flags中指定的标志 • resetiosflags(fmtflags flags) 关闭flags中指定的标志 其中,流格式状态标志字(flags): • ios::left 在域中左对齐输出,右边显示填充字符 • ios::dec 指定整数应作为十进制(基数10)值 • ios::hex 指定整数应作为十六进制(基数16)值 • ios::showpos 指定正数和负数前面分别加上+和-号 • ios::fixed 指定浮点数以小数方式输出 • ios::scientific 指定浮点数输出采用科学记数法
例8-4:改变整数的进制 #include <iostream> using namespace std; int main() { int n = 30; cout << "整数:" << n << endl; cout << "以十六进制显示为:" << hex << n << endl; cout << "以十进制显示为:" << dec << n << endl; cout << "以八进制显示为:" << oct << n << endl; return 0; }
例8-3:设置实型数的精度 #include <iostream> #include <iomanip> #include <cmath> using namespace std; int main() { double r = sqrt( 2.0 ); int i; cout << "r = " << r << endl; // 设置输出为定点小数方式 cout << setiosflags( ios::fixed) ; cout << "以定点小数方式,采用不同精度输出:" << endl; for ( i = 0; i <= 4; i++ ) cout << setprecision( i ) << "r = " << r << endl; // 取消定点小数输出方式并设置为科学记数方式 cout << resetiosflags( ios::fixed) << setiosflags( ios::scientific) ; cout << "以科学记数方式,采用不同精度输出:" << endl; for ( i = 0; i <= 4; i++ ) cout << setprecision( i ) << "r = " << r << endl; return 0; }
例8-5:设置输出宽度、填充字符和对齐方式 #include <iostream> #include <iomanip> using namespace std; int main() { double pi=3.14159; // 以默认方式输出 cout << pi << endl; // 设置输出宽度后进行输出 cout << setw(10) << pi << endl; // 使用填充字符并设置输出宽度后进行输出 cout << setfill('*') << setw(10) << pi << endl; // 设置左对齐方式及输出宽度后进行输出 cout << setiosflags(ios::left) << setw(10) << pi << endl; // 取消左对齐方式 cout << resetiosflags(ios::left); // 设置右对齐方式及输出宽度后进行输出 cout << setiosflags(ios::right) << setw(12) << pi << endl; return 0; }
2. 使用ios类的格式控制成员函数对输出操作进行格式化 • 格式化函数 • width(w) 设置显示字段宽度为w • precision(p) 设置浮点数精度为p • fill(ch) 设置填充字符为ch • setf(flags) 设置输出格式状态为flags • unsetf(flags) 清除格式标记flags • 其中,流格式状态标志字(flags)同前。
#include <iostream> using namespace std; int main() { cout.precision(4); cout.width(10); cout << 10.12345 <<endl; cout.fill('*'); cout.width(10); cout << 10.12345 <<endl; cout.width(10); cout << "Hi!" <<endl; cout.width(10); cout.setf(ios::left); cout << 10.12345<<endl; cout.setf(ios::uppercase | ios::scientific); cout<< 10.12345<<endl; cout.unsetf(ios::uppercase); cout << 10.12345<<endl; return 0; } 运行结果: 10.12 *****10.12 *******Hi! 10.12***** 1.0123E+001 1.0123e+001
规 则 • 成员函数width(w)和流操纵符setw(w)都只对其后的第一个输出项有效 • 用成员函数setf或流操纵符setiosflags设置输出格式后,如果要改为同组另一状态,应调用unsetf或resetiosflags先终止 • ios::left • ios::right
输出流对象的成员函数 • put • Inserts a single byte into the stream. • write • Inserts a series of bytes into the stream. • flush • Flushes the buffer associated with this stream. • seekp • Changes the stream’s put pointer. • tellp • Gets the value of the stream’s put pointer.
8.4 文件 • 8.4.1 文件和流 • 8.4.2文件的打开和关闭 • 8.4.3文件的读写
ios istream ostream ifstream iostream ofstream fstream 8.4.1 文件和流 • C++把每一个文件都看成一个有序的字节流,对文件的操作可采用与输入输出流相关的方法。 • 头文件fstream包含了流类ifstream(从文件输入)、ofstream(向文件输出)和fstream(从文件输入/输出)的定义。 文件I/O流类的继承层次结构 #include <fstream>
8.4.2 文件的打开和关闭 • 文件的处理由三个步骤组成:打开文件,数据读写,关闭文件。 • 1. 打开文件,两种方法: • 1)先建立文件流对象,再调用成员函数open()将它与某一个文件关联 ifstream infile; // 输入文件流对象 ofstream outfile; // 输出文件流对象 fstream iofile; // 输入输出文件流对象 outfile.open("a.dat"); • 2)在建立文件流对象的同时通过构造函数来打开文件。如: ofstream outfile ("a.dat"); • 测试文件是否被正确打开的方法如下: if ( ! outfile) { … // 处理文件打开失败情况的代码 } • 2. 关闭文件:成员函数close() outfile.close( );
8.4.3 文件的读写 • 使用插入与提取运算符对文件进行读写 • >>读文件 • 写文件 << • 使用类成员函数对文件流进行操作 • get读/put写 一次读写一个字节 • istream& get ( char& rch); • ostream& put ( char ch); • getline 一次读一行 • istream& getline(char* pch, int nCount, char delim = '\n' );
// 例8-6:写文件 #include <iostream> #include <fstream> using namespace std; int main() { ofstream outfile("grade.txt"); if(!outfile) { cout << "文件打开失败!"<<endl; return 1; } outfile << "程序设计" << " " << 95 << endl; outfile << "大学英语" << " " << 90.5 << endl; outfile << "高等数学" << " " << 93 << endl; outfile << "普通物理" << " " << 87.5 << endl; outfile.close(); return 0; }
// 例8-7:读文件 #include <iostream> #include <fstream> using namespace std; int main() { ifstream infile("grade.txt"); if(!infile) { cout << "文件打开失败!"<<endl; return 1; } char course[20]; float score; infile >> course >> score; cout << course << " " << score << endl; infile >> course >> score; cout << course << " " << score << endl; infile >> course >> score; cout << course << " " << score << endl; infile >> course >> score; cout << course << " " << score << endl; infile.close(); return 0; } 注意:VC++ 6.0编译器不能正确判断if(! infile)
// 例8-8:使用成员函数get()完成文件读操作 #include <iostream> #include <fstream> using namespace std; int main() { char ch; int count=0; // 计数器 ifstream infile("grade.txt"); if(!infile) { cout << "文件打开失败"<<endl; return 1; } while(!infile.eof( )) { infile.get(ch); // 从文件流中读入下一个字符 cout<<ch; // 屏幕输出从文件中读入的字符 if(ch>='0' && ch<='9') count++; // 若是数字字符,计数器加1 } cout<<endl<<"文件中共有数字字符:"<<count<<"个。"<<endl; infile.close(); return 0; }
扩展阅读 • 8.5 二进制文件 • 二进制文件以位(bit)为单位,整个文件是由0和1组成的无格式的原始数据序列。在二进制方式下的输入输出过程中,系统不对数据进行任何转换。 • 文本文件以字节(byte)为单位,整个文件实际保存的是一串ASCII字符。可用文字处理器进行编辑。在文本方式下的输入输出过程中,系统进行字符转换。
openmode 说 明 ios::app 将所有输出写入文件末尾 ios::ate 打开文件以便输出,并移到文件末尾(通常用于添加数据) 数据可以写入文件中的任何地方 ios::in 打开文件以便输入 ios::out 打开文件以便输出 ios::trunc 删除文件现有内容(是ios::out的默认操作) ios::binary 用二进制而不是文本模式打开文件 ios::nocreate 如果文件不存在,则文件打开失败 ios::noreplace 如果文件存在,则文件打开失败 文件打开方式
// 例8-9:文件拷贝的程序 #include <iostream> #include <fstream> using namespace std; int main() { char s[50], d[50]; cout<<"请输入准备复制的文件名(含后缀名):"; cin>>s; cout<<"请输入新生成的文件名(含后缀名):"; cin>>d; ifstream infile(s, ios::binary); ofstream outfile(d, ios::binary); if(!infile || !outfile) { cout << "文件打开失败!"<<endl; return 1; } char ch; while(!infile.eof() ) { infile.get (ch); // 成员函数get( )用于从输入流中读取一个字符到变量ch outfile.put(ch); // 成员函数put( )将字符变量ch中的字符写到输出流中 } infile.close(); outfile.close(); return 0; }
上机指导 • 8.5 Visual C++的帮助功能
应用举例 • 例8-10 打开一个由若干个整数组成的文本文件“number.txt”,找出其中所有的质数并存入另一个文本文件“prime.txt”中。 • 例8-11 编写程序,可以读入一个C/C++语言的源文件,并在每一行前面加上行号后保存到另一个名为print.txt的文件中。
// 例8-10:文件操作 #include <iostream> #include <fstream> using namespace std; int isprime(int a) // 素数判别函数 { for(int i=2; i<=a/2; i++) if(a%i == 0) return 0; return 1; } int main() { ifstream infile("number.txt"); ofstream outfile("prime.txt"); if(!infile || !outfile) { cout << "文件打开失败!"<<endl; return 1; } int num; while(!infile.eof() ) { infile>>num; if(isprime(num)) outfile<<num<<" "; } infile.close(); outfile.close(); return 0; }
// 例8-11:源文件加行号 #include <iostream> #include <iomanip> #include <fstream> using namespace std; int main() { ifstream infile("test.cpp"); ofstream outfile("print.txt"); if(!infile || !outfile) { cout << "文件打开失败!"<<endl; return 1; } char ch; int line = 1; outfile << setw(4) << line << " "; while(!infile.eof() ) { infile.get(ch); if(!infile.eof()) outfile << ch; if (ch == '\n') // 当遇到换行时,输出新的行号 { line++; outfile << setw(4) << line << " "; } } infile.close(); outfile.close(); return 0; }
结 束 语 学好程序设计语言的唯一途径是 你的编程能力与你在计算机上投入的时间成 上机练习 正比