C++標準庫筆記:13.11 String Stream Classes

String Stream Classes

  • basic_istringstream,特化版本istringstream\wstringstream
  • basic_ostringstream,特化版本ostringstream\wostringstream
  • basic_stringstream,特化版本stringstream\wstringstream
  • basic_stringbuf,特化版本stringbuf\wstringbuf

注:這些classes定義在頭文件<sstream>

成員函數str()是string stream classes最主要的一個函數,用來管理緩衝區

  • str(),將緩衝區當做一個string對象返回
  • str(string),將string設爲緩衝區內容

output string stream 使用例子:

ostringstream os;
os << std::showbase << std::uppercase;
os << "dec: " << 15 << std::hex << " hex: " << 15 << endl;
cout << os.str() << endl;

bitset<16> b(10);
os << "float: " << 4.67 << " bitset: " << b << endl;
cout << os.str() << endl;

os.seekp( 0 );
os << "oct: " << oct << 15;
cout << os.str() << endl;

輸出:

dec: 15 hex: 0XF

dec: 15 hex: 0XF
float: 4.67 bitset: 0000000000001010

oct: 017hex: 0XF
float: 4.67 bitset: 0000000000001010

string stream也可以運用文件開啓模式作爲標誌以及某個字符串作爲初始值。若使用ios::app或ios::ate,寫入string stream的字符串便可以附加於既有字符串之後,其中str()返回的是原有字符串的副本,原有字符串本身並不變化。

string str("old string");
ostringstream os( str, ios::out | ios::app );
os.seekp( 0, ios::end );//在vs2005上試驗,ios::app不工作,可能是bug吧
os << 15 << std::hex << 15;

cout << os.str() << endl;
cout << str << endl;

input string stream主要用途是“按格式,從現有字符串中讀取數據”。如以下代碼,輸出: 10 13

int x = 0;
int y = 0;
std::string s = "10 13";
std::istringstream is( s );
is >> x >> y;
cout << x << " " << y << endl;

char* Stream Classes

char* Stream Classes只是爲了向下兼容被保留下來。它們的接口容易出錯,不易正確使用。這些類使用char*來表現字符串,而上文的string stream classes使用std::string來表現字符串。新編寫的程序最好不用這部分的類。

char* stream classes是特別爲字符型別char而定義的,包括:

  • istrstream
  • ostrstream
  • strstream
  • strstreambuf

所有類都在頭文件<strstream>中定義。

利用成員函數str(),字符序列可以和其調用者一起管理內存,除非被初始化爲定長緩衝區(即傳入一個外部分配的字符串數組,這樣stream就不用負責了), 否則就必須遵守以下原則:

  • 調用str(),內存可以被轉移給調用者,所以如果stream沒被初始化爲定長緩衝式,那麼字符序列將被釋放(注:這裏我想指的是string stream析構執行時,strstreambuf類型的成員對象會析構,strstreambuf析構時,會根據字符序列的分配模式及是否被凍結來判斷是否要釋放內存)。但外部擁有內存後,因爲無法確定內存是如何被分配的,如果直接使用delete來釋放是不安全的。安全的做是調用freeze(false),將內存回傳給stream,由其來釋放。
  • 調用了str(),stream便不能再修改字符序列了(但可以讀取)。因爲str()內部會調用freeze()來凍結字符串。
  • 成員函數str()不附加終止號(’\0’),我們可通過ends來加入終止號。

例子1:

ostrstream os;
os << "afdsf";
cout << os.str() << endl;

//此處改寫無效,因爲前面調用了str(),字符序列已被凍結
os << "11";
cout << os.str() << endl;

//此處是必要的,不然ostrstream內部的strstreambuf不會釋放
//字符序列內存,因爲調用了str(),內存擁有權被轉移了
os.freeze( false );

例子2:

//istrstream初始化爲定長字符序列
char buffer[] = "123 124 125";
std::istrstream input( buffer );

//此處輸出:first read form input: 123 124 125
int a = 0, b = 0, c = 0;
input >> a >> b >> c;
cout << "first read form input: " << a << " " << b << " " << c << endl;

//此處輸出:first read from str(): 123 124 125
input.seekg( 0 );
cout << "first read from str(): " << input.str() << endl;

//此處輸出:second read form buff: 123 124 125
input.clear();
a = b = c = 0;
input >> a >> b >> c;
cout << "second read form input: " << a << " " << b << " " << c << endl;

//此處輸出:second read from str(): 123 124 125
input.seekg( 0 );
cout << "second read from str(): " << input.str() << endl;

//內存不由stream管理,因爲是初始化爲定長字符序列

strstreambuf析構函數中調用的函數代碼(貼出來,輔助理解):

void __CLR_OR_THIS_CALL _Tidy() // free any allocated storage
{   // free any allocated storage
     if ((_Strmode & (_Allocated | _Frozen)) != _Allocated)
         ;  // no buffer to free
     else if (_Pfree != 0)
         (*_Pfree)(eback());    // free with function call
     else
         _DELETE_CRT_VEC(eback());  // free by deleting array

     _Seekhigh = 0;
     _Strmode &= ~(_Allocated | _Frozen);
}
發佈了164 篇原創文章 · 獲贊 106 · 訪問量 33萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章