C/C++ development, inevitable IO input/output (Part 3). String stream (memory stream) IO processing

Table of contents

1. String stream

        1.1 String stream inheritance system

        1.2 The essence of string stream - class template std::basic_stringstream

        1.3 String stream buffer - std::stringbuf

        1.4 stringbuf and sequence buffer

        1.5 Opening mode of string stream

Second, the use of string stream

        2.1 Format conversion is its forte

        2.2 String stream only provides mobile assignment

        2.3 std::basic_stringstream is not just string support

        2.4 String stream is also unique in information splicing

 3. Demo source code supplement


1. String stream

        1.1 String stream inheritance system

        C++'s device abstraction layer IO stream (iostream/ostream/istream) derives two systems, one is file stream (fstream/ofstream/ifstream), and the other is string stream (ie memory stream, stringstream/ostringstream/istringstream, string in output, string out, string in). In addition, each class of string stream has a corresponding wide character set version. In general, it is enough to use stringstream, because strings are frequently involved in input and output.

        Therefore, the capabilities of the device abstraction layer IO stream described earlier in this column, such as open flags, stream state management, buffer management, location finding, formatting, callback, etc. (these will not be expanded in this article), string stream It is also available, and in the application process, it is found that a large part of the functions of the abstract layer IO stream and file stream overlap, so why do we need a string stream, and why the string class (string) function is not suitable for its application.

        Since the stringstream class is named stringstream, its biggest feature is the "stream" feature, and developers can transfer data to the stringstream object like "flowing water".

#include <iostream>
#include <sstream>

void stringstream_first_test(void)
{
    std::stringstream ss;
    ss << "hello ";
    ss << "world!";
    ss << std::endl;
    ss << "I'm c++ developer!";

    std::cout << ss.str() << std::endl;
}
//out log
D:\workForMy\workspace\io_c++_test3>test.exe
hello world!
I'm c++ developer!

        1.2 The essence of string stream - class template std::basic_stringstream

        Similar to text streams, the essential implementation of the stringstream class comes from the specialization of the class template std::basic_stringstream, namely

namespace std {
  template<class CharT, class Traits = char_traits<CharT>,
           class Allocator = allocator<CharT>>
    class basic_stringbuf;
 
  using stringbuf  = basic_stringbuf<char>;
  using wstringbuf = basic_stringbuf<wchar_t>;

  template<class CharT, class Traits = char_traits<CharT>,
           class Allocator = allocator<CharT>>
    class basic_istringstream;
 
  using istringstream  = basic_istringstream<char>;
  using wistringstream = basic_istringstream<wchar_t>;
 
  template<class CharT, class Traits = char_traits<CharT>,
           class Allocator = allocator<CharT>>
    class basic_ostringstream;
  using ostringstream  = basic_ostringstream<char>;
  using wostringstream = basic_ostringstream<wchar_t>;
 
  template<class CharT, class Traits = char_traits<CharT>,
           class Allocator = allocator<CharT>>
    class basic_stringstream;
  using stringstream  = basic_stringstream<char>;
  using wstringstream = basic_stringstream<wchar_t>;
};

        std::basic_stringstream is a class template that implements input and output operations on string-based streams. Replace the previous example with a std::basic_stringstream<char> object and test it out:

void basic_stringstream_test(void)
{
    std::basic_stringstream<char> ss;
    ss << "hello ";
    ss << "world!";
    ss << std::endl;
    ss << "I'm c++ developer!";

    std::cout << ss.str() << std::endl;
}
//main.cpp
    stringstream_first_test();
    basic_stringstream_test();
//out log 是一致的
D:\workForMy\workspace\io_c++_test3>test.exe
hello world!
I'm c++ developer!
hello world!
I'm c++ developer!

        1.3 String stream buffer - std::stringbuf

        std::basic_stringstream It equivalently stores an instance of std::basic_string (basic_stringstream<char>) and performs input and output operations on it. This class actually wraps the native string device of std::basic_stringbuf at a low level to the high-level interface of std::basic_iostream. Provide a complete interface to the unique std::basic_stringbuf member, that is, the buffer of the string stream and related processing functions are completed by the std::stringbuf(std::basic_stringbuf<char>) class.

//定义于头文件 <sstream>
template< 
     class CharT,
     class Traits = std::char_traits<CharT>,
     class Allocator = std::allocator<CharT>
> class basic_stringstream; 

类型             定义 
stringstream     basic_stringstream<char> 
wstringstream    basic_stringstream<wchar_t> 

成员类型                 定义 
char_type               CharT 
traits_type             Traits ;若 Traits::char_type 不是 CharT 则程序非良构。 
int_type                Traits::int_type 
pos_type                Traits::pos_type 
off_type                Traits::off_type 
allocator_type          Allocator 

成员函数
(构造函数)          构造字符串流(公开成员函数) 
operator=          (C++11)移动字符串流(公开成员函数) 
swap               (C++11)交换两个字符串流(公开成员函数) 
rdbuf              返回底层未处理的字符串设备对象(公开成员函数) 

字符串操作
str                获取或设置底层字符串设备对象的内容(公开成员函数) 
view               (C++20)获得底层字符串设备的内容上的视图(公开成员函数) 

非成员函数
std::swap(std::basic_istringstream)     (C++11)特化 std::swap 算法(函数模板) 

//相关父类的成员和设备抽象层IO流、文件流是一致的这里就不详细给出,可以参看前面博文
【1】***继承自 std::basic_istream省略
【2】***继承自 std::basic_ostream省略
【3】***继承自 std::basic_ios省略
【4】***继承自 std::ios_base省略

        std::basic_stringbuf is a std::basic_streambuf whose associated character sequence is any memory-resident sequence of characters. It can be initialized from an instance of std::basic_string, or made an instance of that class.

//定义于头文件 <sstream>
template< 
     class CharT,
     class Traits = std::char_traits<CharT>,
     class Allocator = std::allocator<CharT>
> class basic_stringbuf : public std::basic_streambuf<CharT, Traits> 

        A typical implementation of std::basic_stringbuf holds an object of type std::basic_string, or an equivalent scalable sequence container, as a data member, and uses it both as a sequence of controlled characters (pointed to by std::basic_streambuf's six pointers array) and associated character sequences (character sources for all input operations and targets for output operations). In addition, typical implementations maintain a data member of type std::ios_base::openmode to indicate the state of the stream (read-only, write-only, read-write, end-write, etc.). If overflow() uses an allocation strategy, an additional high-water mark pointer may be stored to keep track of the last initialized character. (since C++11).

公开成员函数
(构造函数)         构造一个 basic_stringbuf 对象(公开成员函数) 
operator=         (C++11)赋值 basic_stringbuf 对象(公开成员函数) 
swap              (C++11)交换二个 basic_stringbuf 对象(公开成员函数) 
(析构函数)         [虚](隐式声明)析构 basic_stringbuf 对象和其所保有的 string(虚公开成员函数) 
str               替换或获得关联字符串的副本(公开成员函数) 
get_allocator     (C++20)获得与内部 basic_string 关联的分配器的副本(公开成员函数) 
view (C++20)      获得底层字符序列上的视图(公开成员函数) 

受保护成员函数
underflow [虚]    返回输入序列中可用的下一字符(虚受保护成员函数) 
pbackfail [虚]    回放字符到输出序列中(虚受保护成员函数) 
overflow [虚]     后附字符到输出序列(虚受保护成员函数)
setbuf [虚]       试图以数组替换受控字符序列(虚受保护成员函数) 
seekoff [虚]      用相对寻址,重定位输入序列、输出序列或两者中的下一位置指针(虚受保护成员函数) 
seekpos [虚]      用绝对寻址,重定位输入序列、输出序列或两者中的下一位置指针(虚受保护成员函数) 

非成员函数
std::swap(std::basic_stringbuf)     (C++11)特化std::swap算法(函数模板) 

//父类streambuf这里就不详细给出,可以参看前面博文
【1】***继承自 std::basic_streambuf

        1.4 stringbuf and sequence buffer

        The operations of stringbuf on the input and output sequences are mostly protected virtual functions. Developers can inherit the stringbuf class, and then overload these functions in the derived class to achieve additional functions suitable for project development. If the stringstream object wants to directly call these virtual implementations that have been implemented, such as setbuf, it is necessary to obtain the stringbuf object pointer through the rdbuf function before calling.

void basic_stringstream_test1(void)
{
    std::basic_stringstream<char> ss;
    char c[256] = {0};
    ss.rdbuf()->pubsetbuf(c, 256);
    ss << "hello ";
    ss << "world!";
    ss << std::endl;
    ss << "I'm c++ developer!";
    std::cout << "--------1--------\n";
    std::cout << ss.str() << std::endl;
    std::cout << "--------2--------\n";
    std::cout << c << std::endl;
}
//out log
--------1--------
hello world!
I'm c++ developer!                                                                                                                                                                                                                              
--------2--------
hello world!
I'm c++ developer!

        The above code sets a character array as the buffer sequence of stringstream, and the input and output data of the stringstream object are replaced with this character array for storage and management. You can see that the storage content of stringstream is output through the str function (the return value object is stringbuf) and It is consistent to directly output the contents of the character array.

        The same character array can be associated with different string streams (str_in or str_out) successively, to operate on a character array respectively, and even to read and write character arrays crosswise.

        1.5 Opening mode of string stream

        Although stringstream does not need to open files like file streams, and does not provide functions such as open, stringstream can treat buffer memory blocks as files, and it also has open mode settings, which are mainly reflected in its constructor (istringstream/ ostringstream similar):

/*以默认打开模式构造新的底层字符串设备*/
basic_stringstream()
     : basic_stringstream(std::ios_base::in | std::ios_base::out) { }//(C++11 起) 

/*构造新的底层字符串设备。
*以 basic_stringbuf<Char,Traits,Allocator>(mode) 构造底层 basic_stringbuf 对象*/
explicit basic_stringstream( std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out );//  (C++11 前) 
explicit basic_stringstream( std::ios_base::openmode mode );//(C++11 起) 

/*以 str 的副本为底层字符串设备的初始内容。
*以 basic_stringbuf<Char,Traits,Allocator>(str, mode) 构造底层 basic_stringbuf 对象。*/
explicit basic_stringstream( const std::basic_string<CharT,Traits,Allocator>& str,
    std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out );

/*移动构造函数。用移动语义,构造拥有 other 的状态的字符串流。*/
basic_stringstream( basic_stringstream&& other );// (C++11 起) 

/*构造新的底层字符串设备。
*以 basic_stringbuf<Char,Traits,Allocator>(mode, a) 构造底层 basic_stringbuf 对象。*/
basic_stringstream( std::ios_base::openmode mode, const Allocator& a );//(C++20 起) 

/*用 str 移动构造底层字符串设备的内容。
*以basic_stringbuf<Char,Traits,Allocator>(std::move(str), mode)构造basic_stringbuf对象*/
explicit basic_stringstream( std::basic_string<CharT,Traits,Allocator>&& str,
    std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out );//(C++20 起) 

/*构造新的底层字符串设备。
*以basic_stringbuf<Char,Traits,Allocator>(str, std::ios_base::in | std::ios_base::out, a) 
*构造底层 basic_stringbuf 对象。*/
template<class SAlloc>
basic_stringstream( const std::basic_string<CharT,Traits,SAlloc>& str,
    const Allocator& a )
    : basic_stringstream(str, std::ios_base::in | std::ios_base::out, a) { } //(C++20 起) 

/*构造新的底层字符串设备。
*以 basic_stringbuf<Char,Traits,Allocator>(str, mode, a) 构造底层 basic_stringbuf 对象。*/
template<class SAlloc> 
basic_stringstream( const std::basic_string<CharT,Traits,SAlloc>& str,
                    std::ios_base::openmode mode, const Allocator& a ); // (C++20 起) 
/*构造新的底层字符串设备。
*以 basic_stringbuf<Char,Traits,Allocator>(str, mode) 构造底层 basic_stringbuf 对象。
*此重载仅若 SAlloc 与 Allocator 不是同一类型才参与重载决议。*/
template<class SAlloc> 
explicit basic_stringstream( const std::basic_string<CharT,Traits,SAlloc>& str,
    std::ios_base::openmode mode = std::ios_base::in 
    | std::ios_base::out ); // (C++20 起) 

        The open flag can be specified explicitly at construction time, and these values ​​are a combination of the following constants ('|'):

app     每次写入前寻位到流结尾 
binary  以二进制模式打开 
in      为读打开 
out     为写打开 
trunc   在打开时舍弃流的内容 
ate     打开后立即寻位到流结尾 

        The string stream class has no open member function, and the string stream object is created by calling the constructor. Support passing in a pointer to the first element of a character array, use it to initialize the stream object, you can set openmode, which is a combination of the above constants, and explicitly indicate the operation mode.

void basic_stringstream_test2(void)
{
    char c;
    std::istringstream in; 
    //std::stringstream in(std::ios_base::in);   //实际
    in.str("a b");
    in >> c;
    std::cout << "c = " << c << ", str() = \"" << in.str() << "\"\n";
    // in << 'c'; //error,无效,不存在该功能
 
    std::ostringstream out("a b");
    //std::ostringstream out("a b",std::ios_base::out);//实际
    out << 'c';
    std::cout << "str() = \"" << out.str() << "\"\n";
    // out >> c;    //error,无效,不存在该功能
    std::stringstream ate1("a b ", std::ios_base::ate);
    ate1 << 'c';    //编译正确,但无效。std::ios_base::out没开启
    std::cout << "ate1.str() = \"" << ate1.str() << "\"\n";

    std::stringstream ate2("a b ", std::ios_base::out | std::ios_base::ate);
    ate2 << 'c';
    std::cout << "ate2.str() = \"" << ate2.str() << "\"\n";
}

Second, the use of string stream

       2.1 Format conversion is its forte

        stringstream supports formatted input and output (operator<</operator>>), stringstream is usually used for data conversion, for conversion between strings and other variable types, it is safe, automatic and direct. Reading data from a character array or string through a string stream is the same as reading data from a keyboard. You can read character data from a character array, and you can also read integers, floating-point numbers, or other types of data.

//类似的可以写出其他类型的转换,或采用模板函数实现各种类型转换
int strToInt(const char* str)
{
    int ret = 0;
    std::stringstream strBufer(str);
    if(!(strBufer>>ret))
        std::cout << "strToInt error"<< std::endl;
    return ret;
}

void stringstream_user_test1(void)
{
    std::string str1("hello 1234 0 4.368");
    std::stringstream ss(str1);//构造函数初始化
    std::cout<<ss.str()<<std::endl;
    std::string str2;
    if(ss>>str2)
    {
        std::cout << "str2 = " << str2 << std::endl;
    }
	int a;
	if(ss>>a)
    {
        std::cout << "a = " << a << std::endl;
    }
	bool b;
    // ss>>std::boolalpha;
    if(ss>>b)
    {
        std::cout << "b = " << b << std::endl;
    }
	float c;
    if(ss>>c)
    {
        std::cout << "c = " << c << std::endl;
    }
	ss.clear();
	ss.str(" I am learning c++ stringstream!");//重新赋值
	while(ss>>str2)//不断读取
	{ 
   
		std::cout<<str2<<" ";
	}		
    std::cout << std::endl;
    const char *pi = "1314";
    std::cout << "strToInt(pi) = " << strToInt(pi) << std::endl;
}
//out log
hello 1234 0 4.368
str2 = hello
a = 1234
b = 0
c = 4.368
I am learning c++ stringstream!
strToInt(pi) = 1314

        In the actual development process, for those unresolved mixed field information, it is a good choice to use the stringstream series to store, and then add the exact type support when the specific data processing is realized.

        2.2 String stream only provides mobile assignment

        The stringstream series types support move assignment, but do not support copy assignment, it is familiar through stringbuf:

//std::basic_stringbuf<CharT,Traits,Allocator>::operator=
/*
*移动赋值运算符:移动 rhs 的内容到 *this 中。
*移动后 *this 拥有 rhs 之前保有的关联 string 、打开模式、本地环境和所有其他状态。
*保证 *this 中 std::basic_streambuf 的六个指针有别于被移动的 rhs 的对应指针,除非它们为空。
*/
std::basic_stringbuf& operator=( std::basic_stringbuf&& rhs );// (C++11 起) 

/*复制赋值运算符被删除;basic_stringbuf 不可复制赋值 (CopyAssignable) 。*/
std::basic_stringbuf& operator=( const std::basic_stringbuf& rhs ) = delete;

//std::basic_stringstream::operator=
/*
*移动赋值字符串流 other 给 *this 。
*/
basic_stringstream& operator=( basic_stringstream&& other );//(C++11 起) 

        Move assignment of stringstream object, equivalent move assignment std::basic_iostream base class and associated std::basic_stringbuf, base class move assignment swaps all stream state variables (except rdbuf) between *this and other, contents of other are cleared , the flow state is reset.

void stringstream_user_test2(void)
{
    std::stringstream in("in");
    std::stringstream out("out");
 
    std::cout << "Before move, int = \"" << in.str() << '"'
              << " out = \"" << out.str() << "\"\n";
 
    *in.rdbuf() = std::move(*out.rdbuf());
 
    std::cout << "After move, in = \"" << in.str() << '"'
              << " out = \"" << out.str() << "\"\n";
    std::stringstream ss;
    ss = std::move(in);
    std::cout << "After move again, in = \"" << in.str() << '"'
              << " ss = \"" << ss.str() << "\"\n";
}
//out log
Before move, int = "in" out = "out"
After move, in = "out" out = ""
After move again, in = "" ss = "out"

        If you want to exchange their content and stream status with other's string stream, use the exchange function swap.

//std::basic_stringstream::swap
//交换流与 other 的状态。
void swap( basic_stringstream& other );//(C++11 起) 

        The exchange of stringstream objects is essentially performed by calling basic_iostream<CharT, Traits>::swap(other) and rdbuf()->swap(*other.rdbuf()).

void stringstream_user_test3(void)
{
    std::stringstream in("in");
    std::stringstream out("out");
    std::cout << "Before swap, int = \"" << in.str() << '"'
        << " out = \"" << out.str() << "\"\n";
    in.swap(out);
    //out.swap(in);
    std::cout << "After swap, in = \"" << in.str() << '"'
        << " out = \"" << out.str() << "\"\n";
}
//out log
Before swap, int = "in" out = "out"
After swap, in = "out" out = "in"

        2.3 std::basic_stringstream is not just string support

        What needs to be remembered is that std::basic_stringstream is a class template, and stringstream is just its specialized class. Using std::basic_stringstream to support other types can also achieve similar stream effects:

void stringstream_user_test4(void)
{
    int a[10] = {1,2,3,4,5,6};
    std::basic_stringstream<int> ss(a);
    // std::basic_stringstream<int> ss;    
    // ss.rdbuf()->pubsetbuf(a, 10);
    int n = 0;
    int index = 0;
    while(index<6 && ss.read(&n,1))
    {
        std::cout << " a["<<index<<"] = " << n << "\n";
        ++index;
    }
}
//out log
 a[0] = 1
 a[1] = 2
 a[2] = 3
 a[3] = 4
 a[4] = 5
 a[5] = 6

        2.4 String stream is also unique in information splicing

        Compared with using stringstream to split field information to obtain information of different data types, stringstream can also be used to mix and splice different types of data information to obtain the required field information, which is unique in vocabulary organization and processing.

void stringstream_user_test5(void)
{
    std::stringstream ss;
    int a = 34;
    int b = 27;
    ss << "now we count " << a <<" multiply " << b <<" the val is " << a*b;
    std::cout << "ss = \"" << ss.str() << "\"\n";
}
//out log
ss = "now we count 34 multiply 27 the val is 918"

        This is the end of the introduction to the main content of string stream IO!

        Thank you readers for patiently reading to the end. My articles are very long and the knowledge points are very detailed. There may be omissions and mistakes. If there are any inadequacies, please point them out. If the content touches you, please like and follow it to avoid getting lost.

 3. Demo source code supplement

        Compilation instruction: g++ main.cpp test*.cpp -o test.exe -std=c++11

        main.cpp

#include "test1.h"

int main(int argc, char* argv[])
{
    stringstream_first_test();
    basic_stringstream_test();
    basic_stringstream_test1();
    basic_stringstream_test2();
    stringstream_user_test1();
    stringstream_user_test2();
    stringstream_user_test3();
    stringstream_user_test4();
    stringstream_user_test5();
    return 0;
}

        test1.h

#ifndef _TEST_1_H_
#define _TEST_1_H_

void stringstream_first_test(void);
void basic_stringstream_test(void);
void basic_stringstream_test1(void);
void basic_stringstream_test2(void);
void stringstream_user_test1(void);
void stringstream_user_test2(void);
void stringstream_user_test3(void);
void stringstream_user_test4(void);
void stringstream_user_test5(void);
#endif //_TEST_1_H_

        test1.cpp

#include "test1.h"

#include <iostream>
#include <sstream>

void stringstream_first_test(void)
{
    std::stringstream ss;
    ss << "hello ";
    ss << "world!";
    ss << std::endl;
    ss << "I'm c++ developer!";

    std::cout << ss.str() << std::endl;
}

void basic_stringstream_test(void)
{
    std::basic_stringstream<char> ss;
    ss << "hello ";
    ss << "world!";
    ss << std::endl;
    ss << "I'm c++ developer!";

    std::cout << ss.str() << std::endl;
}

void basic_stringstream_test1(void)
{
    std::basic_stringstream<char> ss;
    char c[256] = {0};
    ss.rdbuf()->pubsetbuf(c, 256);
    ss << "hello ";
    ss << "world!";
    ss << std::endl;
    ss << "I'm c++ developer!";
    std::cout << "--------1--------\n";
    std::cout << ss.str() << std::endl;
    std::cout << "--------2--------\n";
    std::cout << c << std::endl;
}

void basic_stringstream_test2(void)
{
    char c;
    std::istringstream in; 
    //std::stringstream in(std::ios_base::in);   //实际
    in.str("a b");
    in >> c;
    std::cout << "c = " << c << ", str() = \"" << in.str() << "\"\n";
    // in << 'c'; //error,无效,不存在该功能
 
    std::ostringstream out("a b");
    //std::ostringstream out("a b",std::ios_base::out);//实际
    out << 'c';
    std::cout << "str() = \"" << out.str() << "\"\n";
    // out >> c;    //error,无效,不存在该功能
    std::stringstream ate1("a b ", std::ios_base::ate);
    ate1 << 'c';    //编译正确,但无效。std::ios_base::out没开启
    std::cout << "ate1.str() = \"" << ate1.str() << "\"\n";

    std::stringstream ate2("a b ", std::ios_base::out | std::ios_base::ate);
    ate2 << 'c';
    std::cout << "ate2.str() = \"" << ate2.str() << "\"\n";
}
//类似的可以写出其他类型的转换,或采用模板函数实现各种类型转换
int strToInt(const char* str)
{
    int ret = 0;
    std::stringstream strBufer(str);
    if(!(strBufer>>ret))
        std::cout << "strToInt error"<< std::endl;

    return ret;
}

void stringstream_user_test1(void)
{
    std::string str1("hello 1234 0 4.368");
    std::stringstream ss(str1);//构造函数初始化
    std::cout<<ss.str()<<std::endl;
    std::string str2;
    if(ss>>str2)
    {
        std::cout << "str2 = " << str2 << std::endl;
    }
	int a;
	if(ss>>a)
    {
        std::cout << "a = " << a << std::endl;
    }
	bool b;
    // ss>>std::boolalpha;
    if(ss>>b)
    {
        std::cout << "b = " << b << std::endl;
    }
	float c;
    if(ss>>c)
    {
        std::cout << "c = " << c << std::endl;
    }
	ss.clear();
	ss.str(" I am learning c++ stringstream!");//重新赋值
	while(ss>>str2)//不断读取
	{ 
   
		std::cout<<str2<<" ";
	}		
    std::cout << std::endl;
    const char *pi = "1314";
    std::cout << "strToInt(pi) = " << strToInt(pi) << std::endl;
}

void stringstream_user_test2(void)
{
    std::stringstream in("in");
    std::stringstream out("out");
 
    std::cout << "Before move, int = \"" << in.str() << '"'
              << " out = \"" << out.str() << "\"\n";
 
    *in.rdbuf() = std::move(*out.rdbuf());
 
    std::cout << "After move, in = \"" << in.str() << '"'
              << " out = \"" << out.str() << "\"\n";
    std::stringstream ss;
    ss = std::move(in);
    std::cout << "After move again, in = \"" << in.str() << '"'
              << " ss = \"" << ss.str() << "\"\n";
}

void stringstream_user_test3(void)
{
    std::stringstream in("in");
    std::stringstream out("out");
    std::cout << "Before swap, int = \"" << in.str() << '"'
        << " out = \"" << out.str() << "\"\n";
    in.swap(out);
    //out.swap(in);
    std::cout << "After swap, in = \"" << in.str() << '"'
        << " out = \"" << out.str() << "\"\n";
}

void stringstream_user_test4(void)
{
    int a[10] = {1,2,3,4,5,6};
    std::basic_stringstream<int> ss(a);
    // std::basic_stringstream<int> ss;    
    // ss.rdbuf()->pubsetbuf(a, 10);
    int n = 0;
    int index = 0;
    while(index<6 && ss.read(&n,1))
    {
        std::cout << " a["<<index<<"] = " << n << "\n";
        ++index;
    }
}

void stringstream_user_test5(void)
{
    std::stringstream ss;
    int a = 34;
    int b = 27;
    ss << "now we count " << a <<" multiply " << b <<" the val is " << a*b;
    std::cout << "ss = \"" << ss.str() << "\"\n";
}

Guess you like

Origin blog.csdn.net/py8105/article/details/129830327