输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)

目录

引入

输入输出缓冲区的作用

c++io流

介绍

为什么要把流进行面向对象的设计呢?

原理

使用的注意点

istream类型对象转换为逻辑条件判断值

引入

转换运算符

文件io

介绍

示例

注意点

说明

利用字节流特性 

字符串io

介绍

istringstream

ostringstream

示例


引入

在原先c语言中,我们一般使用scanf和printf来进行输入输出,并且有输入输出缓冲区的存在

输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第1张图片

(代码实际上应该是底层中的内存)

输入输出缓冲区的作用

  • 它可以让原本没有"行"概念的计算机在解析缓冲区内容后,返回一个"行"
  • 不同的操作系统和环境可能有不同的底层 I/O 实现方式,但通过使用标准库函数和输入输出缓冲区,程序员可以将底层的实现细节隐藏起来,使程序在不同平台上运行更加可靠和可移植
  • 通过在内存中累积一定量的数据,程序可以减少频繁的 I/O 操作,从而提高效率

而这种数据运输的过程,被比喻为""

  • 输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第2张图片
  • (来源于 -- 如何理解编程语言中「流」(stream)的概念? - 知乎 (zhihu.com))
  • 流是一种抽象概念,它表示数据的有序序列,这些数据可以被读取、写入或处理,数据可以是各种类型的,这些序列形成一个数据传输通道(可以理解为是一个管道),程序可以逐个字节或块地读取和写入数据,而不必关心数据的来源或去向
  • 它可以描述 数据在 程序 和 外部源/目标 之间的传输
  • 流分为两种,输入流用于从[外部源]读取数据存入[计算机内部],而输出流用于将数据写入[外部设备]
  • 其中,C语言的标准库提供的用于处理输入输出的函数,可以被认为是操作流的接口
  • 而在C++中,也引入了面向对象的流库,其中流对象成为了数据输入和输出的关键接口

c++io流

介绍

  • 输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第3张图片其中,流被抽象成类的对象
  • c++的io流库形成了一个庞大的继承体系,最基本的基类是ios_base,在这之上派生出各种类
  • 一般我们是使用iostream中的cin,cout全局流对象进行输入输出操作(其中c表示console,意思是控制台)

​​​​​​​

  • c中有fscanf/fprintf等f系列函数,用于处理文件;有sscanf/sprintf等s系列函数,用于处理字符串
  • 所以c++也沿用了这个设计,fstream包括了对文件进行io的函数,sstream包括了对字符串进行io的函数

为什么要把流进行面向对象的设计呢?

  • 因为在c中,无法直接向自定义类型输入输出,它提供的接口都是针对内置类型
  • 所以在c++中增加了自定义类型直接和控制台交互的操作(也就是面向对象的设计)
  • 这样把流对象化,可以让"流"这个概念更加形象(cin>>a ,把输入流的内容流入到a中;cout<
原理
  • 实际上,自定义类型的io操作是通过重载运算符<<和>>实现的
  • 并且,c++中的cin,cout不是可以自动识别类型吗
  • 实际上是通过函数重载实现的
  • 输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第4张图片

使用的注意点

  • 输入的数据类型必须与要提取的数据类型一致,否则出错
  • 出错只是在流的状态字state中对应位置位(置1),程序继续
  • 空格和回车都可以作为数据之间的分格符,所以多个数据可以在一行输入,也可以分行输入,如果需要读取整个行,包括空格,可以使用getline函数

istream类型对象转换为逻辑条件判断值

引入

  • 多行输入可以用while(cin>>n)来实现,为什么呢?
  • 是因为通过重载的>>,返回一个cin对象的引用
  • 而这个引用可以作为while的条件,也就意味着cin可以被转换为bool值
  • 这个转换依靠了这个函数:
  • 而这个函数就是c++中的转换运算符

转换运算符

转换运算符是用于定义 类类型 到 另一种数据类型 的自定义转换的特殊成员函数

格式 : operator+类型名

class MyClass {
public:
    operator int() {
        return someValue;
    }
private:
    int someValue;
};
class MyClass {
public:
    operator AnotherClassType() {
        AnotherClassType result;
        // Define the logic to create and initialize result
        return result;
    }
};

所以一个简单的while(cin>>n)实际的调用过程:

  • cin调用operator>>,去流中提取数据,然后返回一个istream&
  • 这个对象调用operator bool,如果接收流失败,或者有结束标志,则返回false,其他返回true
  • 然后这个bool值作为while的判断条件

文件io

介绍

c++根据文件内容的数据格式分为二进制文件文本文件,基本上和c一样
c++ 标准库中有许多不同的标志,用于指定流对象的行为,可以组合在一起以设置不同的模式:
输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第5张图片
采用文件流对象操作文件的一般步骤:
  • 定义一个文件流对象
  • ifstream ifile(只输入用)
  • ofstream ofile(只输出用)
  • fstream iofile(既输入又输出用)
  • 使用文件流对象的成员函数打开一个磁盘文件,使得文件流对象和磁盘文件之间建立联系
  • 使用提取和插入运算符对文件进行读写操作,或使用成员函数进行读写
  • 关闭文件

示例

#include
#include
#include
#include

using namespace std;

struct info_data {
	char _data[50]; //不能使用string/vector
	int _port;
};

class information {
public:
	//ifstream& operator<<()
	information(const string& arr) //我们的文件操作首先需要一个文件路径
		:_filename(arr){}

	void  b_read(info_data& info) {
		ifstream i(_filename, ios_base::in | ios_base::binary);//用二进制读方式打开
		i.read((char*)&info, sizeof(info));//将流中数据读入info中
		i.close();
	}
	void b_write(const info_data& info) {
		ofstream i(_filename, ios_base::out | ios_base::binary| ios_base::app);//用二进制追加写方式打开
		i.write((const char*)&info, sizeof(info));//将info写入流中
		i.write("\n", sizeof("\n"));
		i.close();
	}

	void t_read(info_data& info) {
		ifstream i(_filename);
		i >> info._data >> info._port;//将流中数据读入info中
		i.close();
	}
	void t_write(const info_data& info) {
		ofstream i(_filename, ios_base::out | ios_base::app);//追加方式
		i << info._data << " " << info._port<

文件内容:

输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第6张图片

代码执行结果:

输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第7张图片

tmp实际存放数值:

注意点
  • 如果用string/vector存储数据(也就是字符串),一旦字符串长度有点长,就会在堆上开辟空间存放数据,只会存储一个地址指向那块空间,那存入文件的也是那个地址
  • 输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第8张图片
  • 但下次程序执行,读取文件时,会读取到上次运行时生成的地址,在这次就是无效地址,越界访问了
  • 注意,打开文件之后,如果不需要它了, 最好显式关闭文件
说明
  • 文本读取时,是按行读取;而二进制读取是读整个文件,所以tmp的_data成员是写入的所有字符,_port被默认初始化为0
  • 二进制存入的内容大概率我们都是看不懂的,所以如果需要文件能读懂,最好是文本读写

利用字节流特性 

void test3() {
	ifstream i("code.cpp");
	char c;
	while (i.get(c)) {
		cout << c;
	}
}

利用文件中存储的数据是字节流形式,可以通过get函数获取字符,然后把某个文件全部读出

输入输出缓冲区的作用,c++io流介绍,转换运算符(operator+类型)_第9张图片

字符串io

介绍

istringstream
  • 可以从一个字符串中提取数据
  • 也是一种反序列化的过程,通常包括从字节流中读取数据,解码数据并将其还原为原始数据结构的字段
ostringstream
  • 将数据格式化为字符串,可以像输出到标准输出流一样来构建字符串
  • 属于简单序列化的过程,序列化过程通常包括将数据的字段按照一定的协议编码为字节流,并将其写入文件或通过网络发送
  • 最后通过str()成员函数来获取格式化后的字符串

示例

void test2() {
	int a = 1;
	double b = 1.1;
	ostringstream o;//格式化写入
	o << a << " " << b;
	string str = o.str();
	cout << str << endl;

	ofstream i("test.txt", ios_base::out | ios_base::app);//将字符串写入文件
	i << str << endl;
	i.close();
}

文件内容:

代码结果:

你可能感兴趣的:(c++,c++,开发语言)