C/C++開発、IO入出力不可避(その3) 文字列ストリーム(メモリストリーム)のIO処理

目次

1.文字列ストリーム

        1.1 文字列ストリーム継承システム

        1.2 文字列ストリームの本質 - クラステンプレート std::basic_stringstream

        1.3 文字列ストリームバッファ - std::stringbuf

        1.4 stringbuf とシーケンスバッファ

        1.5 文字列ストリームのオープンモード

第二に、文字列ストリームの使用

        2.1 フォーマット変換が得意

        2.2 文字列ストリームはモバイル割り当てのみを提供します

        2.3 std::basic_stringstream は単なる文字列サポートではありません

        2.4 情報のつなぎ合わせも文字列ストリームならでは

 3. デモソースコード補足


1.文字列ストリーム

        1.1 文字列ストリーム継承システム

        C++ のデバイス抽象化レイヤー IO ストリーム (iostream/ostream/istream) は 2 つのシステムを派生させます。1 つはファイル ストリーム (fstream/ofstream/ifstream) で、もう 1 つは文字列ストリーム (つまり、メモリ ストリーム、stringstream/ostringstream/istringstream、出力の文字列、ストリングアウト、ストリングイン)。さらに、文字列ストリームの各クラスには、対応するワイド文字セット バージョンがあります。通常、文字列は入出力に頻繁に使用されるため、stringstream を使用するだけで十分です。

        したがって、このコラムで前述したデバイス アブストラクション レイヤー IO ストリームの機能 (オープン フラグ、ストリーム状態管理、バッファー管理、位置検索、フォーマット、コールバックなど) (これらについては、この記事では説明しません)、文字列ストリームも利用可能で、アプリケーション プロセスでは、アブストラクト レイヤの IO ストリームとファイル ストリームの機能の大部分が重複していることがわかり、なぜ文字列ストリームが必要なのか、なぜ文字列クラス (string)機能はその用途には適していません。

        stringstream クラスは stringstream という名前になっているため、その最大の特徴は「ストリーム」機能であり、開発者は「流れる水」のように stringstream オブジェクトにデータを転送できます。

#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 文字列ストリームの本質 - クラステンプレート std::basic_stringstream

        テキスト ストリームと同様に、stringstream クラスの本質的な実装は、クラス テンプレート std::basic_stringstream の特殊化、つまり

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 は、文字列ベースのストリームに対する入出力操作を実装するクラス テンプレートです。前の例を std::basic_stringstream<char> オブジェクトに置き換えてテストします。

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 文字列ストリームバッファ - std::stringbuf

        std::basic_stringstream std::basic_string (basic_stringstream<char>) のインスタンスを同等に格納し、それに対して入出力操作を実行します。このクラスは実際には std::basic_stringbuf のネイティブ文字列デバイスを低レベルで std::basic_iostream の高レベル インターフェイスにラップします。一意の std::basic_stringbuf メンバーへの完全なインターフェイスを提供します。つまり、文字列ストリームのバッファーと関連する処理関数は std::stringbuf(std::basic_stringbuf<char>) クラスによって完成されます。

//定义于头文件 <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 は、関連する文字シーケンスが任意のメモリ常駐文字シーケンスである std::basic_streambuf です。std::basic_string のインスタンスから初期化するか、そのクラスのインスタンスにすることができます。

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

        std::basic_stringbuf の典型的な実装は、std::basic_string 型のオブジェクト、または同等のスケーラブルなシーケンス コンテナーをデータ メンバーとして保持し、それを制御文字のシーケンスとして使用します (std::basic_streambuf の 6 つのポインターによってポイントされます)。配列) および関連する文字シーケンス (すべての入力操作の文字ソースと出力操作のターゲット)。さらに、典型的な実装では、ストリームの状態 (読み取り専用、書き込み専用、読み取り-書き込み、終了-書き込みなど) を示すために、型 std::ios_base::openmode のデータ メンバーを維持します。overflow() が割り当て戦略を使用する場合、最後に初期化された文字を追跡するために、追加の最高水準点ポインターが格納される場合があります。(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 とシーケンスバッファ

        入力シーケンスと出力シーケンスでの stringbuf の操作は、ほとんどが保護された仮想関数です. 開発者は stringbuf クラスを継承し、派生クラスでこれらの関数をオーバーロードして、プロジェクト開発に適した追加関数を実現できます. stringstream オブジェクトが setbuf などの実装済みのこれらの仮想実装を直接呼び出したい場合は、呼び出す前に rdbuf 関数を介して stringbuf オブジェクト ポインターを取得する必要があります。

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!

        上記のコードは文字配列を stringstream のバッファ シーケンスとして設定し、stringstream オブジェクトの入出力データをこの文字配列に置き換えて格納および管理します. str 関数を通じて stringstream の格納内容が出力されることがわかります. (戻り値オブジェクトは stringbuf です) and 文字配列の内容をそのまま出力するのは一貫しています。

        同じ文字配列を異なる文字列ストリーム (str_in または str_out) に連続して関連付けて、それぞれ文字配列を操作したり、文字配列を横方向に読み書きしたりすることもできます。

        1.5 文字列ストリームのオープンモード

        stringstream はファイル ストリームのようにファイルを開く必要がなく、open などの機能を提供しませんが、stringstream はバッファ メモリ ブロックをファイルとして扱うことができ、また、主にそのコンストラクタ (istringstream/ ostringstream と同様) に反映されるオープン モード設定もあります。 ):

/*以默认打开模式构造新的底层字符串设备*/
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 起) 

        open フラグは構築時に明示的に指定でき、これらの値は次の定数 ('|') の組み合わせです。

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

        文字列ストリーム クラスには open メンバ関数がなく、コンストラクタを呼び出すことによって文字列ストリーム オブジェクトが作成されます。文字配列の最初の要素へのポインターの受け渡しをサポートし、それを使用してストリーム オブジェクトを初期化します。上記の定数の組み合わせである openmode を設定し、動作モードを明示的に示すことができます。

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";
}

第二に、文字列ストリームの使用

       2.1 フォーマット変換が得意

        stringstream は書式設定された入力と出力 (operator<</operator>>) をサポートします。stringstream は通常、データ変換に使用されます。文字列と他の変数型の間の変換には、安全で自動かつ直接的です。文字列ストリームを介して文字配列または文字列からデータを読み取ることは, キーボードからデータを読み取ることと同じです. 文字配列から文字データを読み取ることができます. また, 整数, 浮動小数点数, または他の型のデータを読み取ることもできます.

//类似的可以写出其他类型的转换,或采用模板函数实现各种类型转换
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

        実際の開発プロセスでは、これらの未解決の混合フィールド情報については、stringstream シリーズを使用して保存し、特定のデータ処理が実現されたときに正確な型のサポートを追加することをお勧めします。

        2.2 文字列ストリームはモバイル割り当てのみを提供します

        stringstream シリーズの型は移動代入をサポートしていますが、コピー代入はサポートしていません。

//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 起) 

        stringstream オブジェクトの移動代入、同等の移動代入 std::basic_iostream 基本クラスおよび関連付けられた std::basic_stringbuf、基本クラスの移動代入は *this と other の間ですべてのストリーム状態変数 (rdbuf を除く) をスワップし、other の内容は clear 、フロー状態リセットされます。

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"

        コンテンツとストリーム ステータスを他の文字列ストリームと交換する場合は、交換関数 swap を使用します。

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

        基本的に、stringstream オブジェクトの交換は、basic_iostream<CharT, Traits>::swap(other) および 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 は単なる文字列サポートではありません

        覚えておく必要があるのは、std::basic_stringstream はクラス テンプレートであり、stringstream は単にその特殊化されたクラスであるということです. std::basic_stringstream を使用して他の型をサポートすることも、同様のストリーム効果を実現できます:

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 情報のつなぎ合わせも文字列ストリームならでは

        stringstream を使用してフィールド情報を分割し、さまざまなデータ型の情報を取得するのと比較して、stringstream を使用して、さまざまな種類のデータ情報を混合および接合して、必要なフィールド情報を取得することもできます。これは語彙の構成と処理において独特です。

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"

        以上で文字列ストリーム IO のメインコンテンツの紹介を終わります!

        読者の皆様、最後まで辛抱強くお読みいただきありがとうございました. 私の記事は非常に長く、知識ポイントは非常に詳細です. 抜けや間違いがあるかもしれません. 不備があればご指摘ください. 内容に触れたら、迷子にならないようにいいねとフォローをお願いします。

 3. デモソースコード補足

        コンパイル手順: 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";
}

おすすめ

転載: blog.csdn.net/py8105/article/details/129830327