OOP课程笔记:第七章 输入输出流类库
第七章 输入输出流类库
1.简介
C++语言的 I/O 系统向用户提供一个统一的接口,使得程序的设计尽量与所访问的具体设备无关,在用户与设备之间提供了一个抽象的界面:输入输出流
用标准流进行输入输出时,系统自动地完成数据类型的转换。
对于输入流,要将输入的字符序列形式的数据变换成计算机内部形式的数据(二进制或 ASCII)后,再赋给变量变换后的格式由变量的类型确定。
对于输出流,将要输出的数据变换成字符串形式后,送到输出流(文件)中。
2.重载输入输出运算符
自定义的对象不能直接输入输出,需要对运算符 << >> 进行重载
重载输入运算符
在对象所在的类中 将重载这二个运算符的函数说明该类的 友元函数 。
friend istream & operater >>(istream&, ClassName& ); // 在类内的声明
istream & operater >>(istream &is , A &a) // 在类外的声明
cin >> a; // 调用1
operator >> (cin,a) // 调用2,效果同上 其中 istream 作为返回值类型, operator作为函数名
istream&作为左操作数,ClassName&作为右操作数
返回值类型:类 istream 的引用, cin 中可以连续使用运算符
cin >> a >> b;class incount {
int c1, c2;
public:
incount(int a = 0, int b = 0) { c1 = a; c2 = b; }
void show(void) { cout << "c1=" << c1 << "\t" << "c2=" << c2 << endl; }
friend istream& operator>>(istream&, incount&);// 重载输入函数声明
};
istream& operator>>(istream& is, incount& cc) {
is >> cc.c1 >> cc.c2;
return is;
}
void main(void) {
incount x1, x2;
x1.show();
x2.show();
cin >> x1;
cin >> x2;
x1.show();
x2.show();
}重载输出运算符
#include <iostream>
using namespace std;
class incount {
int c1, c2;
public:
incount(int a = 0, int b = 0) { c1 = a; c2 = b; }
void show(void) { cout << "c1=" << c1 << "\t" << "c2=" << c2 << endl; }
friend istream& operator>>(istream&, incount&);
friend ostream& operator<<(ostream&, incount&);
};
// 重载输入函数定义
istream& operator>>(istream& is, incount& cc) {
is >> cc.c1 >> cc.c2;
return is;
}
// 重载输出函数定义
ostream& operator<<(ostream& os, incount& cc) {
os << "c1=" << cc.c1 << "\t" << "c2=" << cc.c2 << endl;
return os;
}
int main() {
incount x1, x2;
cout << x1 << x2; // 调用输出函数
cin >> x1; // 调用输入函数
cin >> x2;
cout << x1 << x2;
return 0;
}3.文件流
C++在头文件 fstream.h 中定义了 C++ 的文件流类体系
文件分为使用 ASCII 和 二进制读取 两种方式
文本文件的打开与关闭
在文件操作前,需要将程序与被操作的文件联系起来使程序可以引用文件
在程序内定义一个文件类的对象,由该对象与文件发生联系,程序内所有的与文件的操作都是对该对象的操作 。
fstream infile ,outfile; // 两个对象,可以联系两个输入输出文件
ifstream infile; // 输入
ofstream outfile; // 输出ifstream infile;
infile.open(“myfile1.txt”)打开文件 myfile1.txt 用于输入,并将这个文件与输入文件类对象 infile 建立联系
在程序中,用到这个文件 myfile1.txt 的地方就用 infile来代替。
ifstream infile;
ofstream outfile;
infile.open("myfile1.txt");
outfile.open("myfile2.txt");
float x, y;
infile >> x >> y; // 从文件读取
outfile << x << 't' << y << endl; // 输出到文件
infile.close(); // 使用完则关闭文档
outfile.close();// 使用完则关闭文档使用 fstream 进行读写
当用类 fstream 定义文件对象时必须在成员函数 open() 中的参数中 给出打开方式(读或写)
pfile1.open(“file1.txt”,ios::in );//pfile1 联系到“ file1.txt”, 用于输入
pfile2.open(“file2.txt”,ios::out );//pfile2 联系到“ file2.txt”, 用于输出下文展示如何具体写入和读出数据到文件中
#include <iostream>
#include <fstream>
using namespace std;
int main() {
int a[10];
ifstream infile; // 定义输入文件流对象
ofstream outfile; // 定义输出文件流对象
infile.open("file1.txt"); // 打开输入文件"file1.txt"
outfile.open("file2.txt"); // 打开输出文件"file2.txt"
if (!infile) {
cout << "无法打开输入文件: file1.txt" << endl;
return 1;
}
if (!outfile) {
cout << "无法打开输出文件: file2.txt" << endl;
return 1;
}
for (int i = 0; i < 10; i++) {
infile >> a[i]; // 从"file1.txt"读取十个整数到数组a
}
for (int i = 0; i < 10; i++) {
outfile << a[i] << "\t"; // 将数组a的十个数写入"file2.txt",用制表符分隔
}
outfile << endl; // 写入换行符
infile.close(); // 关闭输入文件
outfile.close(); // 关闭输出文件
return 0;
}判断打开成功
在打开文件后,都要判断打开是否成功。若打开成功,则文件流对象值为非零值; 若打开不成功,则其值为 0
打开输入文件时,文件必须存在
打开输出文件时,若文件不存在,则建立文件;若文件存在,则删除原文件的内容,使其成为一个空文件
#include <iostream>
#include <fstream>
#include <cstdlib> // for exit()
using namespace std;
int main() {
fstream pfile1, pfile2; // 定义了两个文件类的对象
pfile1.open("file1.txt", ios::in);
pfile2.open("file2.txt", ios::out);
if (!pfile1) { // 若为0,打开文件操作失败
cout << "不能打开输入文件:file1.txt" << '\n';
exit(1);
}
if (!pfile2) {
cout << "不能打开输出文件:file2.txt" << '\n';
exit(1);
}
// 文件操作代码...
pfile1.close();
pfile2.close();
return 0;
}常见字符串读写
参见下方,类似于 cin 和 cout 的使用
cin.get(ch); //从键盘输入一个字符
infile.get(ch); //从文件输入一个字符
cout.put(ch); //向显示器输出一个字符
outfile.put(ch); //向文件输出一个字符
cin.getline(str,300); //从键盘输入一行字符
infile.getline(str,300);//从文件输入一行字符二进制读写操作
fstream infile,outfile;
infile.open(“inf1.dat”, ios::in|ios::binary); // 使用二进制输入方式打开
outfile.open(“outf1.dat”, ios::out|ios::binary);由于二进制文件中的数据不是 ASCII 码,故不能直接对其读写, 必须要通过特定的函数予以转换
具体使用时一般使用 char 类型转换
// 读取单个整数
int i;
infile.read(reinterpret_cast<char*>(&i), sizeof(int));
// 这里使用了强制类型转换:reinterpret_cast<char*>,该方式不做任何的检查
// 读取整数数组
int a[10];
infile.read(reinterpret_cast<char*>(a), 10 * sizeof(int));
// 写入一个整数
int i = 4;
outfile.write(reinterpret_cast<char*>(&i), sizeof(int));
// 写入一个数组
int a[10]={0,1,2,3,4,5,6,7,8,9};
outfile.write(reinterpret_cast<char*a, 10 * sizeof(int));在二进制的读取中,判断是否读到文件尾部使用 infile.eof()
当到达文件结束位置时,该函数返回一个非零值,否则返回零。
fstream infile;
infile.open("data1.dat",ios::in|ios::binary);
if(!infile)
cout<<"Open Error!\n"; exit(1);
char str[300];
while(!infile.eof()) // 没有结束就继续读取
infile.read(str, 300);完整的代码示例
#include <iostream>
#include <fstream>
#include <cstring> // For strcpy if needed
using namespace std;
int main() {
char filename1[256], filename2[256];
char buff[4096];
cout << "输入源文件名: ";
cin >> filename1;
cout << "输入目的文件名: ";
cin >> filename2;
fstream infile, outfile;
infile.open(filename1, ios::in | ios::binary);
if (!infile) {
cerr << "无法打开源文件: " << filename1 << endl;
return 1;
}
outfile.open(filename2, ios::out | ios::binary);
if (!outfile) {
cerr << "无法创建目标文件: " << filename2 << endl;
infile.close();
return 1;
}
while (true) {
infile.read(buff, sizeof(buff));
streamsize n = infile.gcount(); // 获取实际读取的字节数
if (n > 0) {
outfile.write(buff, n);
}
if (infile.eof()) {
break; // 到达文件末尾,退出循环
}
if (!infile) {
cerr << "文件读取错误" << endl;
break;
}
}
infile.close();
outfile.close();
cout << "文件复制完成" << endl;
return 0;
}
评论已关闭