streamstring类介绍

std::stringstream 是 C++ 标准库中提供的一个类,定义在头文件 <sstream> 中。它是基于字符串的流(stream),允许像操作输入流(std::cin)或输出流(std::cout)那样,操作字符串内容。

std::stringstream 是 std::iostream 的派生类,支持同时进行字符串解析(输入)和字符串构造(输出)。

核心概念

std::stringstream 用字符串作为存储介质,模拟流的行为。

主要用于:

  • 从字符串中提取数据(类似 std::cin)。

  • 将数据写入字符串(类似 std::cout)。

常见成员函数

  • 输入与输出

    <<:将数据写入流中(字符串拼接)。

    >>:从流中提取数据(字符串解析)。

  • 绑定与清空

    • str():获取或设置流内的字符串。

    • clear():清除流状态(但不清除内容)。

举几个例子

1. 字符串构造

将多个数据拼接成字符串:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::stringstream ss;
    ss << "Name: " << "Alice" << ", Age: " << 25; // 写入字符串流

    std::string result = ss.str(); // 获取流中的字符串
    std::cout << result << std::endl; // 输出: Name: Alice, Age: 25

    return 0;
}

输出如下:

img

2. 字符串解析

从字符串中提取数据:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string data = "123 456 789"; // 要解析的字符串
    std::stringstream ss(data);

    int a, b, c;
    ss >> a >> b >> c; // 逐个提取整数

    std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl; // 输出: a: 123, b: 456, c: 789

    return 0;
}

输出如下:

img

3. 字符串重用

修改或清空流中的字符串:

#include <iostream>
#include <sstream>

int main() {
    std::stringstream ss;

    // 第一次使用
    ss << "Hello, World!";
    std::cout << ss.str() << std::endl; // 输出: Hello, World!

    // 重用流
    ss.str("");            // 清空内容
    ss.clear();            // 清除状态标志
    ss << "New String!";
    std::cout << ss.str() << std::endl; // 输出: New String!

    return 0;
}

img

插句题外话

如果写成这样:

#include <iostream>
#include <sstream>

int main() {
    std::stringstream ss;

    // 第一次使用
    ss << "Hello, World!";
    std::cout << ss.str() << std::endl; // 输出: Hello, World!

    ss << "New String!";
    std::cout << ss.str() << std::endl; // 输出: New String!

    return 0;
}

输出如下:

img

应用场景

1. 替代 itoa 或 sprintf

std::stringstream 可以将整数或浮点数格式化为字符串:

#include <iostream>
#include <sstream>

int main() {
    int num = 42;
    std::stringstream ss;
    ss << "Number: " << num;

    std::string result = ss.str();
    std::cout << result << std::endl; // 输出: Number: 42

    return 0;
}

输出如下:

img

可以看看这篇博客 将数值转换为字符串的函数,涉及到了itoasprintf

2. 解析复杂字符串

从复杂字符串中提取数据,比如读取配置或处理输入:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string input = "Name=John;Age=30;Country=USA";
    std::stringstream ss(input);

    std::string item;
    while (std::getline(ss, item, ';')) { // 按分号分割字符串
        std::cout << item << std::endl;
    }

    return 0;
}

输出如下:

img

3. 文件数据处理

用于处理从文件读取的字符串内容:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

int main() {
    std::ifstream file("data.txt");
    std::stringstream buffer;

    buffer << file.rdbuf(); // 将文件内容读取到字符串流
    std::string content = buffer.str();

    std::cout << "File Content:\n" << content << std::endl;

    return 0;
}

输出如下:

img

其中data.txt内容如下:

img

streamstring类遇到空格或者换行会怎么做

在 C++ 的 std::stringstream 中,空格和换行符的处理取决于使用的输入方式(比如 >> 操作符或 getline 函数):

1. 使用 >> 操作符读取

>> 操作符会将空格和换行符视为分隔符,跳过它们。它会自动提取下一个有效的非空白内容。

比如:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string input = "Hello World\n42";
    std::stringstream ss(input);

    std::string word;
    int number;

    ss >> word; // 读取第一个单词
    std::cout << "Word: " << word << std::endl; // 输出: Hello

    ss >> word; // 读取第二个单词
    std::cout << "Word: " << word << std::endl; // 输出: World

    ss >> number; // 读取数字
    std::cout << "Number: " << number << std::endl; // 输出: 42

    return 0;
}

输出如下:

img

解释:

  • >> 会跳过所有空白字符(包括空格和换行符)。

  • 每次调用 >> 都会从上次解析停止的位置继续提取。

2. 使用 getline 函数读取

  • std::getline 会按行读取内容,直到遇到换行符 \n

  • 换行符会被作为分隔符,不包含在返回的字符串中。

  • 空格会被视为普通字符,不会跳过。

比如:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string input = "Hello World\n42";
    std::stringstream ss(input);

    std::string line;
    while (std::getline(ss, line)) { // 按行读取
        std::cout << "Line: " << line << std::endl;
    }

    return 0;
}

输出如下:

img

解释:

  • getline 会读取整行内容直到遇到换行符,换行符本身被丢弃。

  • 每次调用 getline 会从流的当前位置继续读取下一行。

3. 混合读取方式

可以根据需要,使用 >>getline 结合解析内容:

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string input = "Name: John Doe\nAge: 30";
    std::stringstream ss(input);

    std::string label, name;
    int age;

    // 使用 >> 提取部分数据
    ss >> label >> name; // 提取 "Name:" 和 "John"
    std::cout << label << " " << name << std::endl;

    // 使用 getline 处理整行
    std::getline(ss, name); // 提取 " Doe"
    std::cout << "Name (continued):" << name << std::endl;

    // 提取下一行
    ss >> label >> age; // 提取 "Age:" 和 "30"
    std::cout << label << " " << age << std::endl;

    return 0;
}

输出如下:

img

4. 空格与换行的处理差异总结

img

注意事项

  • 效率问题:std::stringstream 适合轻量级字符串处理,但对于频繁的字符串拼接操作,性能可能不如 std::string 直接操作高。

  • 状态清理:在重用 std::stringstream 时,记得使用 str("") 清空内容,并用 clear() 重置流状态。

posted @ 2024-11-16 15:52  hisun9  阅读(4)  评论(0编辑  收藏  举报