天天看點

c++中istringstream及ostringstream超詳細說明

文章目錄

      • 1. stringbuf類介紹
        • 1.1 stringbuf類構造函數
        • 1.2 str函數
      • 2. istringstream類
        • 2.1 rdbuf函數
        • 2.2 swap函數
      • 3.ostringstream類和stringstream類

前文說過,istringstream是繼承于istream,ostringstream是繼承于ostream,而他們使用的緩沖區類是stringbuf。

關于這些類之間的關系,有興趣可以去檢視我之前的文章:

c++标準輸入輸出流關系梳理

stringbuf類緩沖區使用一個std::string類作為存儲媒體,然後根據構造時的讀寫模式來對string類進行讀寫。

小貼士:explicit用來防止由構造函數定義的隐式轉換。
//根據傳入的讀寫标示構造一個擁有空string的緩沖區,預設可讀可寫
explicit basic_stringbuf(ios_base::openmode __mode = ios_base::in | ios_base::out)
: __streambuf_type(), _M_mode(__mode), _M_string()
{ }

//複制一個已有的string作為緩沖區内容,且根據__mode來指定可讀、可寫或者讀寫,預設可讀可寫
explicit basic_stringbuf(const __string_type& __str,
      ios_base::openmode __mode = ios_base::in | ios_base::out)
: __streambuf_type(), _M_mode(), _M_string(__str.data(), __str.size())
{ _M_stringbuf_init(__mode); }
           

使用例子如下:

#include <sstream>
using namespace std;

int main()
{
	stringbuf *buf = new stringbuf(ios_base::in);//構造一個可寫的空stringbuf
	string str("my name is haha");
	stringbuf *bufStr = new stringbuf(str, ios_base::out);

	if ( buf != nullptr )
	{
		delete buf;
	}
	if ( bufStr != nullptr )
	{
		delete bufStr;
	}

	return 0;
}
           

str函數原型如下:

//擷取string内容     
__string_type
      str() const;

//參數__s中内容初始化為目前緩沖區string
      void
      str(const __string_type& __s);
           

使用案例如下:

#include <sstream>
#include <iostream>
using namespace std;

int main()
{
	stringbuf *buf = new stringbuf(ios_base::in);
	string str("my name is haha");
	stringbuf *bufStr = new stringbuf(str, ios_base::out);

	cout << bufStr->str() << endl;
	buf->str(string("my name is not haha"));
	cout << buf->str() << endl;

	if ( buf != nullptr )
	{
		delete buf;
	}
	if ( bufStr != nullptr )
	{
		delete bufStr;
	}

	return 0;
}
           

還有其他函數這裡就不多做介紹了,理論上來講,我們并不會直接使用stringbuf,因為它隻是一個工具人,是藏于暗中滴,大多數時候,我們都是直接使用istringstream和ostringstream。

前文說過,實際上istringstream全名應該是basic_istringstream,istringstream隻是basic_istringstream的一個char類型執行個體,下面還是直接使用istringstream來進行代指。

istringstream的構造函數與stringbuf的參數以及類型一模一樣,是以直接按照stringbuf的構造函數用法一樣使用即可,隻是流打開模式上而言,istringstream預設是ios_base::in。

截取構造函數原型如下:

explicit
      basic_istringstream(ios_base::openmode __mode = ios_base::in)
      : __istream_type(), _M_stringbuf(__mode | ios_base::in)
      { this->init(&_M_stringbuf); }
explicit
      basic_istringstream(const __string_type& __str,
			  ios_base::openmode __mode = ios_base::in)
      : __istream_type(), _M_stringbuf(__str, __mode | ios_base::in)
      { this->init(&_M_stringbuf); }
           

另外istringstream的str函數也是與stringbuf一樣,傳回了string對象,這裡不再多說。

rdbuf函數原型如下:

//傳回一個指向stringbuf對象的指針
__stringbuf_type*
      rdbuf() const
      { return const_cast<__stringbuf_type*>(&_M_stringbuf); }
           

rdbuf使用案例如下:

#include <sstream>
#include <iostream>
using namespace std;

int main()
{
	istringstream istr("istringstream", ios_base::in);
	cout << "string is " << istr.str() << endl;
	cout << "string's len is " << istr.rdbuf()->in_avail() << endl;

	return 0;
}
           

這裡也順便展示了一下str函數的用法,in_avail是streambuf類裡面的一個函數,用于傳回目前緩沖區長度。

編譯後執行結果如下:

[root@mylinux ~]# ./a.out 
string is istringstream
string's len is 13
[root@mylinux ~]#
           

swap函數原型如下:

//用于交換兩個istringstream内容
void swap(basic_istringstream& __rhs);
           

用法如下:

#include <sstream>
#include <iostream>
using namespace std;

int main()
{
	istringstream istr1("lilei");
	istringstream istr2("hanmeimei");
	istr1.swap(istr2);
	cout << "istr1 is " << istr1.str() << endl;
	cout << "istr2 is " << istr2.str() << endl;

	return 0;
}
           

編譯後輸出結果如下:

[root@mylinux ~]# ./a.out 
istr1 is hanmeimei
istr2 is lilei
[root@mylinux ~]#
           

可以看到istr1和istr2兩個對象的内容是完全交換了。

ostringstream用于往string寫入資料,除了構造的時候,預設的打開模式是ios_base::out,其他所有函數都與istringstream一樣,且用法也是一樣的,這裡不再多說。

截取其中一個構造函數原型如下:

//隻是構造函數預設參數不一樣,其他與istringstream是一樣的
explicit
      basic_ostringstream(ios_base::openmode __mode = ios_base::out)
      : __ostream_type(), _M_stringbuf(__mode | ios_base::out)
      { this->init(&_M_stringbuf); }
           

stringstream是繼承于iostream類,它除了構造函數預設模式不一樣,其他所有函數也與istringstream用法一樣

explicit
      basic_stringstream(ios_base::openmode __m = ios_base::out | ios_base::in)
      : __iostream_type(), _M_stringbuf(__m)
      { this->init(&_M_stringbuf); }