C++ 字符串流化 stringstream

2024-06-21 07:52

本文主要是介绍C++ 字符串流化 stringstream,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

   

目录

原理

1. std::stringstream 概述

2. 内部机制

3. 工作原理

写入数据

读取数据

4. 主要操作

妙用

1. 将数据格式化为字符串

2. 从字符串解析数据

3. 字符串到数值转换、 数值到字符串转换

4. 合并字符串

5. 动态生成 SQL 查询

6. 日志系统

7. 基于模板生成代码

8. URL 解析

9. 生成 HTML

10. 动态命令行生成

总结

附:自定义 MyStringStream 类


     

        C++ 中的字符串流化(string stream)是通过标准库提供的 std::stringstream 实现的。std::stringstreamstd::iostream 的子类,它允许我们将字符串作为流进行读写操作。下面我将解释字符串流化的原理,包括其内部机制和工作方式。

原理

1. std::stringstream 概述

  std::stringstream 位于 <sstream> 头文件中,是 std::basic_stringstream<char> 的类型定义。它是一个模板类,继承自 std::iostream,可以同时进行输入和输出操作。

2. 内部机制

  std::stringstream 的核心是使用一个 std::stringbuf 对象,该对象是 std::basic_stringbuf<char> 的实例。std::stringbuf 提供了将字符串作为流缓冲区的能力。

  • std::stringbuf:该类继承自 std::basic_streambuf<char>,用于管理内部字符串缓冲区。它提供了读写字符串的接口。
  • std::stringstream:组合了 std::istreamstd::ostream 的功能,通过 std::stringbuf 实现对字符串的读写操作。

3. 工作原理

  std::stringstream 使用内部的 std::stringbuf 对象来存储和管理字符串数据。std::stringbuf 维护一个内部缓冲区(即 std::string 对象),可以通过流操作将数据写入或从中读取。

写入数据
  • 当我们向 std::stringstream 写入数据时,数据被插入到内部缓冲区中。
  • 流操作符(<<)重载实现了对各种数据类型的格式化写入。
std::stringstream ss;
ss << 123 << " " << 45.67;  // 将整数和浮点数写入字符串流
读取数据
  • 当我们从 std::stringstream 读取数据时,数据从内部缓冲区中提取。
  • 流操作符(>>)重载实现了对各种数据类型的解析读取。
std::stringstream ss("123 45.67");
int a;
double b;
ss >> a >> b;  // 从字符串流中读取整数和浮点数

4. 主要操作

  • 插入数据:使用 << 操作符将数据插入到字符串流中。
  • 提取数据:使用 >> 操作符从字符串流中提取数据。
  • 获取字符串:使用 str() 方法获取内部缓冲区的字符串表示。
  • 设置字符串:使用 str(const std::string& s) 方法设置内部缓冲区的内容。
  • 清空流:使用 str("")clear() 清空流内容和状态。
#include <iostream>
#include <sstream>
#include <string>int main() {// 创建一个字符串流对象std::stringstream ss;// 写入数据到字符串流int num = 42;double pi = 3.14159;ss << "Number: " << num << ", Pi: " << pi;// 获取字符串流的内容std::string str = ss.str();std::cout << "Stream content: " << str << std::endl;// 清空字符串流ss.str("");ss.clear();// 写入新的数据到字符串流std::string data = "123 45.67";ss.str(data);// 从字符串流读取数据int a;double b;ss >> a >> b;std::cout << "Extracted values: a = " << a << ", b = " << b << std::endl;return 0;
}

妙用

1. 将数据格式化为字符串

        使用 std::stringstream 可以将各种类型的数据格式化为字符串。

#include <iostream>
#include <sstream>
#include <string>int main() {std::stringstream ss;int n = 42;double pi = 3.14159;// 向字符串流中插入数据ss << "The value of n is " << n << " and the value of pi is " << pi;// 将字符串流转换为字符串std::string result = ss.str();std::cout << result << std::endl;return 0;
}

2. 从字符串解析数据

        使用 std::stringstream 可以从字符串中解析出不同类型的数据。

#include <iostream>
#include <sstream>
#include <string>int main() {std::string data = "42 3.14159";std::stringstream ss(data);int n;double pi;// 从字符串流中提取数据ss >> n >> pi;std::cout << "The value of n is " << n << " and the value of pi is " << pi << std::endl;return 0;
}

3. 字符串到数值转换、 数值到字符串转换

#include <iostream>
#include <sstream>
#include <string>int main() {std::string numberStr = "12345";int number;std::stringstream ss(numberStr);ss >> number;if (ss.fail()) {std::cout << "Conversion failed!" << std::endl;} else {std::cout << "Converted number: " << number << std::endl;}return 0;
}
#include <iostream>
#include <sstream>
#include <string>int main() {int number = 12345;std::stringstream ss;ss << number;std::string numberStr = ss.str();std::cout << "Converted string: " << numberStr << std::endl;return 0;
}

4. 合并字符串

  std::stringstream 可以用于高效地拼接多个字符串。

#include <iostream>
#include <sstream>
#include <string>int main() {std::string firstName = "John";std::string lastName = "Doe";int age = 30;std::stringstream ss;ss << "Name: " << firstName << " " << lastName << ", Age: " << age;std::string result = ss.str();std::cout << result << std::endl;return 0;
}

5. 动态生成 SQL 查询

  std::stringstream 可以用于动态生成复杂的 SQL 查询语句。

#include <iostream>
#include <sstream>
#include <string>std::string generateSQLQuery(const std::string& tableName, const std::string& column, int value) {std::stringstream ss;ss << "SELECT * FROM " << tableName << " WHERE " << column << " = " << value;return ss.str();
}int main() {std::string query = generateSQLQuery("users", "age", 25);std::cout << "Generated SQL Query: " << query << std::endl;return 0;
}

6. 日志系统

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>class Logger {
public:void log(const std::string& message) {std::stringstream ss;ss << "[INFO] " << message;writeLog(ss.str());}void logError(const std::string& message) {std::stringstream ss;ss << "[ERROR] " << message;writeLog(ss.str());}private:void writeLog(const std::string& logEntry) {std::ofstream logFile("log.txt", std::ios_base::app);logFile << logEntry << std::endl;}
};int main() {Logger logger;logger.log("This is an information message.");logger.logError("This is an error message.");return 0;
}

7. 基于模板生成代码

  std::stringstream 可以用于代码生成工具,通过模板生成不同的代码片段。

#include <iostream>
#include <sstream>
#include <string>std::string generateFunction(const std::string& returnType, const std::string& functionName, const std::string& params) {std::stringstream ss;ss << returnType << " " << functionName << "(" << params << ") {\n";ss << "    // function body\n";ss << "}\n";return ss.str();
}int main() {std::string code = generateFunction("int", "add", "int a, int b");std::cout << "Generated Function Code:\n" << code << std::endl;return 0;
}

8. URL 解析

#include <iostream>
#include <sstream>
#include <string>
#include <map>std::map<std::string, std::string> parseURLParameters(const std::string& url) {std::map<std::string, std::string> params;std::string::size_type pos = url.find('?');if (pos == std::string::npos) {return params;}std::string query = url.substr(pos + 1);std::stringstream ss(query);std::string param;while (std::getline(ss, param, '&')) {std::string::size_type eqPos = param.find('=');if (eqPos != std::string::npos) {std::string key = param.substr(0, eqPos);std::string value = param.substr(eqPos + 1);params[key] = value;}}return params;
}int main() {std::string url = "http://example.com/page?param1=value1&param2=value2&param3=value3";std::map<std::string, std::string> params = parseURLParameters(url);std::cout << "Parsed URL Parameters:" << std::endl;for (const auto& param : params) {std::cout << param.first << ": " << param.second << std::endl;}return 0;
}

9. 生成 HTML

#include <iostream>
#include <sstream>
#include <string>
#include <vector>std::string generateHTML(const std::vector<std::string>& items) {std::stringstream ss;ss << "<ul>\n";for (const auto& item : items) {ss << "  <li>" << item << "</li>\n";}ss << "</ul>";return ss.str();
}int main() {std::vector<std::string> items = {"Item 1", "Item 2", "Item 3"};std::string html = generateHTML(items);std::cout << "Generated HTML:\n" << html << std::endl;return 0;
}

10. 动态命令行生成

#include <iostream>
#include <sstream>
#include <string>std::string generateCommand(const std::string& command, const std::vector<std::string>& args) {std::stringstream ss;ss << command;for (const auto& arg : args) {ss << " " << arg;}return ss.str();
}int main() {std::vector<std::string> args = {"-o", "output.txt", "-i", "input.txt", "--verbose"};std::string command = generateCommand("my_program", args);std::cout << "Generated Command: " << command << std::endl;return 0;
}

总结

        可以看到 std::stringstream 在各种实际编程任务中都有广泛的应用。不论是格式化输出、数据解析、生成动态内容,还是处理多行文本、生成命令行字符串等,std::stringstream 都提供了灵活且强大的解决方案。这些示例展示了 std::stringstream 的多种妙用,希望能帮助你更好地理解和应用这一强大的工具。

附:自定义 MyStringStream

#include <iostream>
#include <string>
#include <sstream>class MyStringStream {
public:MyStringStream() {}// 写入数据到流template<typename T>MyStringStream& operator<<(const T& value) {buffer << value;return *this;}// 从流中读取数据template<typename T>MyStringStream& operator>>(T& value) {buffer >> value;return *this;}// 获取流的内容std::string str() const {return buffer.str();}// 设置流的内容void str(const std::string& s) {buffer.str(s);}// 清空流void clear() {buffer.str("");buffer.clear();}private:std::stringstream buffer;
};int main() {MyStringStream myStream;// 写入数据myStream << "Hello, " << "world! " << 123 << " " << 45.67;// 获取流内容std::string content = myStream.str();std::cout << "Stream content: " << content << std::endl;// 清空流myStream.clear();myStream << "New content: " << 789;content = myStream.str();std::cout << "Stream content after clear: " << content << std::endl;// 设置流内容myStream.str("100 200");int a, b;myStream >> a >> b;std::cout << "Extracted values: a = " << a << ", b = " << b << std::endl;return 0;
}

这篇关于C++ 字符串流化 stringstream的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1080638

相关文章

Java中String字符串使用避坑指南

《Java中String字符串使用避坑指南》Java中的String字符串是我们日常编程中用得最多的类之一,看似简单的String使用,却隐藏着不少“坑”,如果不注意,可能会导致性能问题、意外的错误容... 目录8个避坑点如下:1. 字符串的不可变性:每次修改都创建新对象2. 使用 == 比较字符串,陷阱满

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

IDEA编译报错“java: 常量字符串过长”的原因及解决方法

《IDEA编译报错“java:常量字符串过长”的原因及解决方法》今天在开发过程中,由于尝试将一个文件的Base64字符串设置为常量,结果导致IDEA编译的时候出现了如下报错java:常量字符串过长,... 目录一、问题描述二、问题原因2.1 理论角度2.2 源码角度三、解决方案解决方案①:StringBui

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没

c++中std::placeholders的使用方法

《c++中std::placeholders的使用方法》std::placeholders是C++标准库中的一个工具,用于在函数对象绑定时创建占位符,本文就来详细的介绍一下,具有一定的参考价值,感兴... 目录1. 基本概念2. 使用场景3. 示例示例 1:部分参数绑定示例 2:参数重排序4. 注意事项5.

使用C++将处理后的信号保存为PNG和TIFF格式

《使用C++将处理后的信号保存为PNG和TIFF格式》在信号处理领域,我们常常需要将处理结果以图像的形式保存下来,方便后续分析和展示,C++提供了多种库来处理图像数据,本文将介绍如何使用stb_ima... 目录1. PNG格式保存使用stb_imagephp_write库1.1 安装和包含库1.2 代码解

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

C#从XmlDocument提取完整字符串的方法

《C#从XmlDocument提取完整字符串的方法》文章介绍了两种生成格式化XML字符串的方法,方法一使用`XmlDocument`的`OuterXml`属性,但输出的XML字符串不带格式,可读性差,... 方法1:通过XMLDocument的OuterXml属性,见XmlDocument类该方法获得的xm