C/C++-Entwicklung, unvermeidliche IO-Eingabe/Ausgabe (Teil 3) String-Stream (Speicherstrom) IO-Verarbeitung

Inhaltsverzeichnis

1. String-Stream

        1.1 String-Stream-Vererbungssystem

        1.2 Die Essenz von Stringstream – Klassenvorlage std::basic_stringstream

        1.3 String-Stream-Puffer - std::stringbuf

        1.4 Stringbuf und Sequenzpuffer

        1.5 Eröffnungsmodus des Stringstreams

Zweitens die Verwendung von String-Stream

        2.1 Formatkonvertierung ist seine Stärke

        2.2 String-Stream bietet nur eine mobile Zuordnung

        2.3 std::basic_stringstream ist nicht nur String-Unterstützung

        2.4 String Stream ist auch einzigartig beim Spleißen von Informationen

 3. Demo-Quellcode-Ergänzung


1. String-Stream

        1.1 String-Stream-Vererbungssystem

        Der E/A-Stream der Geräteabstraktionsschicht von C++ (iostream/ostream/istream) leitet zwei Systeme ab, eines ist ein Dateistream (fstream/ofstream/ifstream) und das andere ein Stringstream (dh Speicherstream, stringstream/ostringstream/istringstream, Zeichenfolge in der Ausgabe, Saite raus, Saite rein). Außerdem hat jede Klasse von String-Streams eine entsprechende Wide-Character-Set-Version. Im Allgemeinen reicht es aus, stringstream zu verwenden, da Strings häufig an der Ein- und Ausgabe beteiligt sind.

        Daher werden die Fähigkeiten des E/A-Streams der Geräteabstraktionsschicht, die weiter oben in diesem Artikel beschrieben wurden, wie z stream Es ist auch verfügbar, und im Anwendungsprozess stellt sich heraus, dass sich ein großer Teil der Funktionen der abstrakten Schicht IO-Stream und File-Stream überschneiden, also warum brauchen wir einen String-Stream und warum die String-Klasse (String) Funktion ist für seine Anwendung nicht geeignet.

        Da die Stringstream-Klasse Stringstream heißt, ist ihre größte Funktion die „Stream“-Funktion, und Entwickler können Daten wie „fließendes Wasser“ an das Stringstream-Objekt übertragen.

#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 Die Essenz von Stringstream – Klassenvorlage std::basic_stringstream

        Ähnlich wie bei Textstreams stammt die wesentliche Implementierung der Klasse stringstream aus der Spezialisierung des Klassen-Templates std::basic_stringstream, nämlich

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 ist eine Klassenvorlage, die Eingabe- und Ausgabeoperationen auf Zeichenfolgen-basierten Streams implementiert. Ersetzen Sie das vorherige Beispiel durch ein std::basic_stringstream<char>-Objekt und testen Sie es:

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-Puffer - std::stringbuf

        std::basic_stringstream Es speichert äquivalent eine Instanz von std::basic_string (basic_stringstream<char>) und führt Eingabe- und Ausgabeoperationen darauf durch. Diese Klasse umschließt tatsächlich das native String-Gerät von std::basic_stringbuf auf einer niedrigen Ebene mit der High-Level-Schnittstelle von std::basic_iostream. Stellen Sie dem eindeutigen std::basic_stringbuf-Member eine vollständige Schnittstelle bereit, d. h. der Puffer des String-Streams und zugehörige Verarbeitungsfunktionen werden von der std::stringbuf(std::basic_stringbuf<char>)-Klasse vervollständigt.

//定义于头文件 <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 ist ein std::basic_streambuf, dessen zugeordnete Zeichenfolge eine beliebige speicherresidente Zeichenfolge ist. Es kann von einer Instanz von std::basic_string initialisiert oder zu einer Instanz dieser Klasse gemacht werden.

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

        Eine typische Implementierung von std::basic_stringbuf enthält ein Objekt des Typs std::basic_string oder einen äquivalenten skalierbaren Sequenzcontainer als Datenmember und verwendet beides als eine Sequenz von kontrollierten Zeichen (auf die die sechs Zeiger von std::basic_streambuf zeigen). Array) und zugehörige Zeichenfolgen (Zeichenquellen für alle Eingabeoperationen und Ziele für Ausgabeoperationen). Darüber hinaus verwalten typische Implementierungen ein Datenelement vom Typ std::ios_base::openmode, um den Status des Streams anzugeben (schreibgeschützt, schreibgeschützt, schreibgeschützt, Schreibende usw.). Wenn overflow() eine Zuordnungsstrategie verwendet, kann ein zusätzlicher High-Water-Mark-Zeiger gespeichert werden, um das zuletzt initialisierte Zeichen zu verfolgen. (seit 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 und Sequenzpuffer

        Die Operationen von stringbuf auf den Eingabe- und Ausgabesequenzen stellen größtenteils geschützte virtuelle Funktionen dar. Entwickler können die Klasse stringbuf erben und diese Funktionen dann in der abgeleiteten Klasse überladen, um zusätzliche Funktionen zu erhalten, die für die Projektentwicklung geeignet sind. Wenn das Stringstream-Objekt diese implementierten virtuellen Implementierungen, wie z. B. setbuf, direkt aufrufen möchte, muss vor dem Aufruf der Stringbuf-Objektzeiger über die Funktion rdbuf abgerufen werden.

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!

        Der obige Code legt ein Zeichenarray als Puffersequenz von stringstream fest, und die Eingabe- und Ausgabedaten des stringstream-Objekts werden durch dieses Zeichenarray zur Speicherung und Verwaltung ersetzt.Sie ​​können sehen, dass der Speicherinhalt von stringstream über die str-Funktion ausgegeben wird (das Rückgabewertobjekt ist stringbuf) und es ist konsistent, den Inhalt des Zeichenarrays direkt auszugeben.

        Dasselbe Zeichenarray kann nacheinander mit verschiedenen Stringströmen (str_in oder str_out) verknüpft werden, um jeweils auf einem Zeichenarray zu arbeiten und sogar Zeichenarrays kreuzweise zu lesen und zu schreiben.

        1.5 Eröffnungsmodus des Stringstreams

        Obwohl stringstream keine Dateien wie Dateistreams öffnen muss und keine Funktionen wie open bereitstellt, kann stringstream Pufferspeicherblöcke als Dateien behandeln und hat auch Einstellungen für den offenen Modus, die sich hauptsächlich in seinem Konstruktor widerspiegeln (istringstream/ ostringstream ähnlich ):

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

        Das Open-Flag kann explizit zur Konstruktionszeit angegeben werden, und diese Werte sind eine Kombination der folgenden Konstanten ('|'):

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

        Die String-Stream-Klasse hat keine offene Elementfunktion, und das String-Stream-Objekt wird durch Aufrufen des Konstruktors erstellt. Unterstützen Sie die Übergabe eines Zeigers auf das erste Element eines Zeichenarrays, verwenden Sie ihn zum Initialisieren des Stream-Objekts, Sie können openmode festlegen, was eine Kombination der oben genannten Konstanten ist, und den Betriebsmodus explizit angeben.

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

Zweitens die Verwendung von String-Stream

       2.1 Formatkonvertierung ist seine Stärke

        stringstream unterstützt formatierte Eingabe und Ausgabe (operator<</operator>>), stringstream wird normalerweise für die Datenkonvertierung verwendet, für die Konvertierung zwischen Zeichenfolgen und anderen Variablentypen ist es sicher, automatisch und direkt. Das Lesen von Daten aus einem Zeichenarray oder einer Zeichenkette über einen Zeichenkettenstream stellt das gleiche wie das Lesen von Daten von einer Tastatur dar. Sie können Zeichendaten aus einem Zeichenarray lesen, und Sie können auch Ganzzahlen, Gleitkommazahlen oder andere Datentypen lesen.

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

        Im eigentlichen Entwicklungsprozess ist es für diese nicht aufgelösten gemischten Feldinformationen eine gute Wahl, die Stringstream-Serie zum Speichern zu verwenden und dann die genaue Typunterstützung hinzuzufügen, wenn die spezifische Datenverarbeitung realisiert ist.

        2.2 String-Stream bietet nur eine mobile Zuordnung

        Die Typen der Stringstream-Serie unterstützen die Move-Zuweisung, aber keine Copy-Zuweisung, dies ist durch stringbuf bekannt:

//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-Zuweisung des Stringstream-Objekts, äquivalente Move-Zuweisung std::basic_iostream Basisklasse und zugehöriger std::basic_stringbuf, Basisklassen-Move-Zuweisung tauscht alle Stream-Zustandsvariablen (außer rdbuf) zwischen *this und other, Inhalte von other werden gelöscht, der Flow-Status wird zurückgesetzt.

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"

        Wenn Sie ihren Inhalt und Stream-Status mit dem String-Stream anderer austauschen möchten, verwenden Sie die Austauschfunktion swap.

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

        Der Austausch von Stringstream-Objekten erfolgt im Wesentlichen durch den Aufruf von basic_iostream<CharT, Traits>::swap(other) und 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 ist nicht nur String-Unterstützung

        Was nicht vergessen werden muss, ist, dass std::basic_stringstream ein Klassen-Template ist und stringstream nur seine spezialisierte Klasse.Die Verwendung von std::basic_stringstream zur Unterstützung anderer Typen kann auch ähnliche Stream-Effekte erzielen:

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 ist auch einzigartig beim Spleißen von Informationen

        Verglichen mit der Verwendung von Stringstream zum Teilen von Feldinformationen, um Informationen unterschiedlicher Datentypen zu erhalten, kann Stringstream auch zum Mischen und Verbinden verschiedener Arten von Dateninformationen verwendet werden, um die erforderlichen Feldinformationen zu erhalten, was in der Vokabularorganisation und -verarbeitung einzigartig ist.

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"

        Dies ist das Ende der Einführung in den Hauptinhalt von Stringstream IO!

        Vielen Dank an die Leser, dass Sie geduldig bis zum Ende gelesen haben. Meine Artikel sind sehr lang und die Wissenspunkte sind sehr detailliert. Es kann Auslassungen und Fehler geben. Wenn es irgendwelche Unzulänglichkeiten gibt, weisen Sie bitte darauf hin. Wenn dich der Inhalt berührt, like und folge ihm bitte, um nicht verloren zu gehen.

 3. Demo-Quellcode-Ergänzung

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

Ich denke du magst

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