istringstream、ostringstream、stringstream 類介紹 和 stringstream類 clear函數的真正用途
來源: http://blog.csdn.net/TQH_Candy/article/details/52494570
0、C++的輸入輸出分為三種:
(1)基於控制台的I/O
(2)基於文件的I/O
(3)基於字符串的I/O
1、頭文件
- #include <sstream>
2、作用
istringstream類用於執行C++風格的字符串流的輸入操作。
ostringstream類用於執行C++風格的字符串流的輸出操作。
strstream類同時可以支持C++風格的串流的輸入輸出操作。
3、具體分析
istringstream類
描述:從流中提取數據,支持 >> 操作
這里字符串可以包括多個單詞,單詞之間使用空格分開
- istringstream的構造函數原形:
- istringstream::istringstream(string str);
初始化:使用字符串進行初始化
- istringstream istr("1 56.7");
- istr.str("1 56.7");//把字符串"1 56.7"存入字符串流中
使用:我們可以使用分解點獲取不同的數據,完成 字符串 到 其他類型 的轉換
常用成員函數:
- str():使istringstream對象返回一個string字符串
舉例:把字符串類型的數據轉換為其他類型
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main()
- {
- istringstream istr("1 56.7");
- cout<<istr.str()<<endl;//直接輸出字符串的數據 "1 56.7"
- string str = istr.str();//函數str()返回一個字符串
- cout<<str<<endl;
- int n;
- double d;
- //以空格為界,把istringstream中數據取出,應進行類型轉換
- istr>>n;//第一個數為整型數據,輸出1
- istr>>d;//第二個數位浮點數,輸出56.7
- //假設換下存儲類型
- istr>>d;//istringstream第一個數要自動變成浮點型,輸出仍為1
- istr>>n;//istringstream第二個數要自動變成整型,有數字的階段,輸出為56
- //測試輸出
- cout<<d<<endl;
- cout<<n<<endl;
- system("pause");
- return 1;
- }
舉例2:把一行字符串放入流中,單詞以空格隔開。之后把一個個單詞從流中依次讀取到字符串
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main()
- {
- istringstream istr;
- string line,str;
- while (getline(cin,line))//從終端接收一行字符串,並放入字符串line中
- {
- istr.str(line);//把line中的字符串存入字符串流中
- while(istr >> str)//每次讀取一個單詞(以空格為界),存入str中
- {
- cout<<str<<endl;
- }
- }
- system("pause");
- return 1;
- }
輸入:123 34 45
輸出:
123 換行 34 換行 45
ostringstream類
描述:把其他類型的數據寫入流(往流中寫入數據),支持<<操作
- ostringstream的構造函數原形:
- ostringstream::ostringstream(string str);
初始化:使用字符串進行初始化
- ostringstream ostr("1234");
- ostr.str("1234");//把字符串"1234"存入字符串流中
舉例:
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main()
- {
- //初始化輸出字符串流ostr
- ostringstream ostr("1234");
- cout<<ostr.str()<<endl;//輸出1234
- ostr.put('5');//字符4頂替了1的位置
- cout<<ostr.str()<<endl;//輸出5234
- ostr<<"67";//字符串67替代了23的位置,輸出5674
- string str = ostr.str();
- cout<<str<<endl;
- system("pause");
- return 1;
- }
stringstream類
描述:是對istringstream和ostringstream類的綜合,支持<<, >>操作符,可以進行字符串到其它類型的快速轉換
- stringstream的構造函數原形如下:
- stringstream::stringstream(string str);
初始化:使用字符串進行初始化
- stringstream str("1234");
- str.str("1234");//把字符串"1234"存入字符串流中
作用:
1、stringstream通常是用來做數據轉換的
2、將文件的所有數據一次性讀入內存
舉例1:基本數據類型變字符串
- /*基本數據類型變字符串*/
- #include <fstream>
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main()
- {
- /*整型變字符串*/
- int n = 10;
- string str;
- stringstream stream;
- stream << n;
- stream >> str;
- cout<<str<<endl;
- stream.clear();//多次使用stringstream,要先清空下,不能使用stream.str("");否則下面輸出10
- /*char* 變 string*/
- char cStr[10] = "china";
- stream << cStr;
- stream >> str;
- cout<<str<<endl;
- system("pause");
- return 1;
- }
舉例2:字符串變基本數據類型
- /*字符串變基本數據類型*/
- #include <fstream>
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main()
- {
- /*字符串 變 double*/
- double n;
- string str = "12.5";
- stringstream stream;
- stream << str;
- stream >> n;
- cout<<n<<endl;
- stream.clear();//多次使用stringstream,要先清空下,不能使用stream.str("");
- /*string 變 char* */
- string str1 = "china";
- char cStr[10];
- stream << str1;
- stream >> cStr;
- cout<<cStr<<endl;//輸出china
- system("pause");
- return 1;
- }
- 注意:
- #include <iostream>
- #include <sstream>
- using namespace std;
- int main(int argc,char *argv[])
- {
- std::stringstream stream;
- string str;
- while(1)
- {
- //clear(),這個名字讓很多人想當然地認為它會清除流的內容。
- //實際上,它並不清空任何內容,它只是重置了流的狀態標志而已!
- stream.clear();
- // 去掉下面這行注釋,清空stringstream的緩沖,每次循環內存消耗將不再增加!
- //stream.str("");
- stream<<"sdfsdfdsfsadfsdafsdfsdgsdgsdgsadgdsgsdagasdgsdagsadgsdgsgdsagsadgs";
- stream>>str;
- //測試輸出每次循環,你的內存消耗增加了多少!
- cout<<"Size of stream = "<<stream.str().length()<<endl;
- system("PAUSE");
- }
- system("PAUSE");
- return EXIT_SUCCESS;
- }
由於stringstream構造函數會特別消耗內存,似乎不打算主動釋放內存(或許是為了提高效率),但如果你要在程序中用同一個流,反復讀寫大量的數據,將會造成大量的內存消耗,因些這時候,需要適時地清除一下緩沖 (用 stream.str("") )。
另外不要企圖用 stream.str().resize(0),或 stream.str().clear() 來清除緩沖,使用它們似乎可以讓stringstream的內存消耗不要增長得那么快,但仍然不能達到清除stringstream緩沖的效果,內存的消耗還在緩慢的增長!,至於stream.flush(),則根本就起不到任何作用。
//=============================================
究竟什么情況下需要用到clear
先來看一個stack overflow上的問題(http://stackoverflow.com/questions/35080342/using-two-string-streams-but-not-getting-same-result)
我將其簡化為以下代碼:
- int main() {
- string line = "1 2 3 4 5";
- stringstream s1(line);
- string temp;
- int toAdd;
- stringstream s2;
- while (s1 >> temp) {
- cout << "temp:" << temp << endl;
- s2 << temp;
- cout << "s2.str: " << s2.str() << endl;
- s2 >> toAdd;
- cout << "toAdd:" << toAdd << endl;
- s2.str("");
- }
- return 0;
- }
這個代碼的原意是要把line中的字符串形式的1 2 3 4 5一個一個地轉成int並輸出,所以我們期望的toAdd的輸出應該是1 2 3 4 5,但結果卻是 1 1 1 1 1, 如下圖
可以從s2.str:這句輸出中看到, 只有第一次是正常地把temp輸入進s2,后面的都失敗了。
原因在於, s2在第一次調用完operator<<和operator>>后,來到了end-of-file的位置,此時stringstream會為其設置一個eofbit的標記位,標記其為已經到達eof。查文檔得知, 當stringstream設置了eofbit,任何讀取eof的操作都會失敗,同時,會設置failbit的標記位,標記為失敗狀態。所以后面的操作都失敗了,toAdd的值一直都是1。
Operations that attempt to read at the End-of-File fail, and thus both the eofbit and the failbit end up set. This function can be used to check whether the failure is due to reaching the End-of-File or to some other reason.
clear函數:
原型: void clear (iostate state = goodbit);
標志位一共有4種, goodbit, eofbit, failbit, badbit
clear可以清除掉所有的error state
- int main() {
- string line = "1 2 3 4 5";
- stringstream s1(line);
- string temp;
- int toAdd;
- stringstream s2;
- while (s1 >> temp) {
- cout << "temp:" << temp << endl;
- s2 << temp;
- cout << "s2.str: " << s2.str() << endl;
- s2 >> toAdd;
- cout << "toAdd:" << toAdd << endl;
- s2.str("");
- if (s2.eof()) {
- s2.clear();
- cout << "s2.eof true" << endl;
- }
- }
- return 0;
- }
使用clear后, s2就可以正常地工作了,結果如下:
參考網站:http://www.cplusplus.com/reference/sstream/stringstream/
http://www.cplusplus.com/reference/ios/ios/clear/