[原创](Modern C++)现代C++的输入流与“>>“的微妙关系 (包含字符流拆分技巧)

常用网名:猪头三

出生日期: 1981.XX.XX

QQ联系: 643439947

个人网站: 80x86汇编小站

编程生涯: 2001年~至今[共23年]

职业生涯: 21年

开发语言: C/C++、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python

开发工具: Visual Studio、Delphi、XCode、Eclipse、C++ Builder

技能种类: 逆向 驱动 磁盘 文件

研发领域: Windows应用软件安全/Windows系统内核安全/Windows系统磁盘数据安全/macOS应用软件安全

项目经历: 磁盘性能优化/文件系统数据恢复/文件信息采集/敏感文件监测跟踪/网络安全检测

[序言]

C++中, 输入流(如std::istringstream, std::wistringstream等)是用于从字符串或其他数据源提取数据的对象. ">>"操作符被称为提取运算符, 它可以与输入流一起使用, 从输入流中读取特定类型的值并存储到变量中.

[代码演示]

下面是一个示例代码片段, 展示了如何使用std::wistringstream从输入字符串提取多个字段.

cpp 复制代码
int main()
{
    // 需要按照空格符进行拆分字符串(有4个字段)
    std::wstring wstr_Demo = L"1 hello world 5.1";
    std::wistringstream class_wss(wstr_Demo);

    int     int_Value1;                    // 字段1
    std::wstring wstr_Value2, wstr_Value3; // 字段2 字段3
    double  double_Value4;                 // 字段4
    wchar_t whar_Delimiter;                // 分隔符

    // 提取字段1
    class_wss >> int_Value1;

    // ">>"操作符会忽略开头的空白符,直到遇到第一个非空白符为止。
    // 因此,在提取字段2和字段3时,">>"运算符会跳过中间的多个空格,只保留一个空格作为分隔符。
    class_wss >> wstr_Value2;
    class_wss >> wstr_Value3;

    // 提取字段4
    class_wss >> double_Value4;
}

通过多次使用">>"运算符, 可以依次提取所有的字段. 因为使用">>"运算符从输入流中提取数据时, 它会跳过开头的空白符(如空格、制表符、回车等)并读取下一个非空白符之后的数据, 读取完成之后, 如果遇到新的空白符, 就会停止读取. 此时输入流会自动移动到当前新的白符处. 如果要继续读取下一个字段数据, 那么只需要再次调用">>"运算符即可.

[利用流的工作原理优化代码写法]

使用">>"运算符可以方便地从输入流中连续不断地提取不同类型的值并将其存储到变量中, 因此,可以进一步简化代码:

cpp 复制代码
class_wss >> int_Value1 >> wstr_Value2 >> wstr_Value3 >> double_Value4;

这种写法被称为链式提取(chain extraction), 它利用了">>"运算符的返回值是输入流对象本身这一特性, 通过连续使用">>"运算符, 可以一次性地提取所有字段.

[处理无空白符的字符串]

如果字符串中没有空白符(例如"1:hello:world:5.1"), 此时使用">>"运算符将会失效, 在这种情况下, 可以使用std::getline()函数进行处理提取字段.

cpp 复制代码
int main()
{
    // 需要按照":"进行拆分字符串(有4个字段)
    std::wstring wstr_Demo = L"1:hello:world:5.1";
    std::wistringstream class_wss(wstr_Demo);

    // 通过std::getline来进行拆分
    std::wstring wstr_Value;
    std::vector<std::wstring> vector_Token;
    while (std::getline(class_wss, wstr_Value, L':'))
    {
        // 保存字段到vector容器
        vector_Token.push_back(wstr_Value);
    }
}

[高级方法: 使用std::setw()来控制流提取的宽度]

std::setw(n)是一个用来设置输出/输入流宽度的函数. 当表达式 out << std::setw(n) 或者 in >> std::setw(n)时, 它会将流out或者in的宽度参数精确地设置为n. 比如有一个字符串"1:10:ABCD:5.1", 为了提取"ABCD"这个字段, 可以用std::setw(4)来处理. (注意: 有些操作可能会重置宽度为零(例如,>>提取操作), 因此在进行多个操作时, 可能需要反复调用std::setw()来设置宽度) .

如下代码演示:

cpp 复制代码
int main()
{
    // 需要按照空格符进行拆分字符串(有4个字段)
    std::wstring wstr_Demo = L"1:10:ABCD:5.1";
    std::wistringstream class_wss(wstr_Demo);

    int     int_Value1, int_Value2; // 字段1 字段2
    std::wstring wstr_Value3;       // 字段3
    double  double_Value4;          // 字段4
    wchar_t whar_Delimiter;         // 分隔符

    // 提取字段1, 字段2, 字段3, 字段4 (注意在提取字段3之前, 用std::setw()函数设置了提取流的宽度.)
    class_wss >> int_Value1 >> whar_Delimiter >> int_Value2 >> whar_Delimiter >> std::setw(4) >> wstr_Value3 >> whar_Delimiter >> double_Value4;
 }

[总结]

通过上面的3个代码演示, 可以清楚的看到2种情况: 存在空白符 与 不存在空白符, 对输入流的操作是截然不同的. 希望这篇文章对大家有所帮助.

相关推荐
Ljw...19 分钟前
DeepSeek+Kimi生成高质量PPT
数据库·c++·powerpoint·ppt·deepseek
敲上瘾20 分钟前
基础dp——动态规划
java·数据结构·c++·python·算法·线性回归·动态规划
禁默1 小时前
C++之旅-C++11的深度剖析(1)
开发语言·c++
张有志_1 小时前
STL容器终极解剖:C++ vector源码级实现指南 | 从内存分配到异常安全的全流程避坑
c语言·c++·算法·开源·visual studio
挨代码1 小时前
UE_C++ —— Delegates
c++·ue
web_155342746563 小时前
性能巅峰对决:Rust vs C++ —— 速度、安全与权衡的艺术
c++·算法·rust
9毫米的幻想3 小时前
【Linux系统】—— 冯诺依曼体系结构与操作系统初理解
linux·运维·服务器·c语言·c++
Mr.Wang8093 小时前
条款23:宁以non-member、non-friend替换member函数
开发语言·c++
以卿a4 小时前
C++ 模板初阶
开发语言·c++
黑不溜秋的10 小时前
C++ 设计模式 - 策略模式
c++·设计模式·策略模式