C/C++|C++标准库 string 流之std::ostringstream 和 std::istringstream 流

我们在 sstream 头文件中定义了三个类型来支持内存IO(ostringstream\istringstream\stringstream),这些类型可以向 string 写入数据,这里我们主要讲: std::ostringstreamstd::istringstream( C++ Primer 中文版第五版)

以上的两个类型都继承自我们经常使用的 iostream 头文件中定义的类型。并且,他们还增加了一下成员来管理与流相关的 string。

也就是说,他们使得我们能够像控制IO流一样控制 string。

文章目录

std::ostringstream

常用方法:

  • << 操作符:用于将数据格式化并写入到 ostringstream 中
  • str() :返回当前流中的字符串
  • clear() :清楚流中的数据。
  • seekp():用于调整输出指针的位置,便于覆盖或插入内容,适用于一些高级场景

它有一个很典型的场景:

逐步构造输出,希望最后一起打印时,ostringstream 非常有用。

比如逐个验证电话号码并改变其格式等等。

使用场景一:序列化数据

这里就典型使用到了我们的逐步构造输出,希望最后一起打印。

cpp 复制代码
std::string serialize(TreeNode* root) {
	std::ostringstream out;
	if (!root) {
		out << "null ";
	} else {
		out << root->val << " ";
		out << serialize(root->left);
		out << serialize(root->right);
	}
	return out.str();
}

使用场景二:拼接字符串

这个也是,我们的逐步构造输出,希望最后一起打印。

cpp 复制代码
#include <iostream>
#include <sstream>

int main () {
	std::ostringstream out;
	int number = 42;
	std::string text = "The answer is";
	out << text << " " << number << ".";
	
	std::string result = out.str();
	std::cout << result << std::endl; // 输出:The answer is 42.
	return 0;
}

使用场景三:格式化输出

当需要对输出进行格式化(例如控制浮点数的小数位数、控制数字格式等),ostringstream 可以帮助我们简化这类操作。

cpp 复制代码
#include <sstream>
#include <iostream> 
#include <iomanip> // 控制浮点数京都

int main () {
	std::ostringstream out;
	double pi = 3.14159265358979323;
	// 设置京都为小数点后两位
	out << std::fixed << std::setprecision(2) << pi;
	std::out << "Formatted pi: " << out.str() << std::endl;
	return 0;
}

std::istringstream

  • >> 操作符:从字符串流中提取数据。可以从字符串中逐个提取数据并将其转换为相应的类型。
  • str() :设置或返回当前字符串流中的内容。
  • clear() :重置流的状态,使流可以重用。
  • seekg() :调整输入流指针的位置,通常用于重新读取数据或跳过某些数据。

使用场景一:解析输入

cpp 复制代码
int main () {
	std::string inpit = "42 3.14 Hello";
	std::istringstream iss(input);

	int number;
	double pi;
	std::string text;
	
	iss >> number >> pi >> text;
}

注意,我们的 >> 操作符更适合用于逐个提取空格分隔的值。

这里我们列举一个 getline 的用法:

cpp 复制代码
// getline 读取文件内容
int main () {
	std::ifstream file("input.txt");
	std::string line;
	if (file.is_open()) {
		while (std::getline(file, line)) {
			std::cout << line << std::endl; //输出每行内容,getline 会逐行读取,直到遇到文件结束或换行符
		}
		file.close();
	} else {
		std::cerr << "Unable to open file" << std::endl;
	}
	return 0;
}

// getline 自定义分隔符号
int main () {
	std::string input = "apple,banana,orange,grape";
	std::istringstream stream(input);
	std::string token;
	
	while (std::getline(stream, token, ',')) {
		std::cout << "Extracted token: " << token << std::endl; 
	}
}

使用场景二:反序列化数据

cpp 复制代码
TreeNode* deserialize(std::istringstream& iss) {
	std::string val;
	iss >> val;
	if (val == "null") {
		return nullptr;
	}
	TreeNode* node = new TreeNode(std::stoi(val));
	node->left = deserialize(iss);
	node->right = deserialize(iss);
	return node;
}
int main () {
	std::string data = "1 2 null null 3 null null";
	std::istringstream iss(data);
	TreeNode* root = deserialize(iss);
	std:: cout << "Deserialized tree root value: " << root->val << std::endl;
}
相关推荐
鱼跃鹰飞2 小时前
设计模式系列:工厂模式
java·设计模式·系统架构
a努力。2 小时前
国家电网Java面试被问:混沌工程在分布式系统中的应用
java·开发语言·数据库·git·mysql·面试·职场和发展
Yvonne爱编码2 小时前
Java 四大内部类全解析:从设计本质到实战应用
java·开发语言·python
J2虾虾2 小时前
SpringBoot和mybatis Plus不兼容报错的问题
java·spring boot·mybatis
毕设源码-郭学长3 小时前
【开题答辩全过程】以 基于springboot 的豪华婚车租赁系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
imX2G3 小时前
爆破小游戏2.0
c++
Cx330❀4 小时前
【优选算法必刷100题】第41-42题(模拟):Z 字形变换,外观数列
c++·算法
沃尔特。4 小时前
直流无刷电机FOC控制算法
c语言·stm32·嵌入式硬件·算法
Cx330❀4 小时前
【优选算法必刷100题】第038题(位运算):消失的两个数字
开发语言·c++·算法·leetcode·面试
燃于AC之乐4 小时前
我的算法修炼之路--5——专破“思维陷阱”,那些让你拍案叫绝的非常规秒解
c++·算法·贪心算法·bfs·二分答案·扩展域并查集·动态规划(最长上升子序列)