來自:http://blog.csdn.net/zaishaoyi/article/details/46682033
stringstream
stringstream 是 C++ 提供的另一個字串型的串流(stream)物件,和之前學過的 iostream、fstream 有類似的操作方式。要使用 stringstream, 必須先加入這一行:
#include <sstream>
stringstream 主要是用在將一個字串分割,可以先用 clear( )以及 str( ) 將指定字串設定成一開始的內容,再用 >> 把個別的資料輸出,例如:
string s;stringstream ss;int a, b, c;getline(cin, s);ss.clear();ss.str(s);ss >> a >> b >> c;
下面我們看到一個使用 stringstream 的例子:
題目:輸入的第一行有一個數字 N 代表接下來有 N 行資料,每一行資料裡有不固定個數的整數(最多 20 個,每行最大 200 個字元),請你寫一個程式將每行的總和印出來。
輸入:
3
1 2 3
20 17 23 54 77 60
111 222 333 444 555 666 777 888 999
輸出:
6
251
4995
程式如下:
string s;stringstream ss;int n, i, sum, a;cin >> n;getline(cin, s); // 讀取換行for (i=0; i<n; i++){ getline(cin, s); ss.clear(); ss.str(s); sum=0; while (1) { ss >> a; if ( ss.fail() ) break; sum+=a; } cout << sum << endl;}
string類型是c語言中char *類型的一種更便利的實現。使用這個類型,不用再去刻意考慮記憶體的事兒。在做快速開發的時候,string對象提供的便利,還是相當出色的。然而,在這兒提醒一下:string類型很有可能成為一個工程效率問題的根源,產品層級的應用當中,應該盡量避免在深層迴圈嵌套中使用string類型。
除size()外,另外兩個string常用的方法是find和substr。在下面的代碼當中:
string str = "aaaaddddssdfsasdf"; size_t pos = str.find("ssdf", 3); //用if(pos == string::npos) 用來判斷是否找到子串。 string str2 = str.substr(pos, 5);
find函數從str的第3個位置查起,找到ssdf這個子串後,返回子串的位置。而substr函數從pos位置開始,截取5個字元,賦值給str2。也就是說,str2之後的內容將是ssdfs。stringstream是字串流,經常被我用來作資料切分或者類型轉化。一個經常被我用到的函數如下:
string i2s(int i, int len = 0){ stringstream ss; ss << setw(len) << setfill('0') << i; return ss.str():}
以i2s(7, 3)形式調用這個函數,返回的結果是字串007。我通常在迴圈裡,這樣產生或者遍曆一些檔案。
使用stringstream對象簡化類型轉換
C++標準庫中的<sstream>提供了比ANSI C的<stdio.h>更進階的一些功能,即單純性、型別安全和可擴充性。在本文中,我將展示怎樣使用這些庫來實現安全和自動的類型轉換。
為什麼要學習
如果你已習慣了<stdio.h>風格的轉換,也許你首先會問:為什麼要花額外的精力來學習基於<sstream>的類型轉換呢。也許對下面一個簡單的例子的回顧能夠說服你。假設你想用sprintf()函數將一個變數從int類型轉換到字串類型。為了正確地完成這個任務,你必須確保證目標緩衝區有足夠大空間以容納轉換完的字串。此外,還必須使用正確的格式化符。如果使用了不正確的格式化符,會導致非預知的後果。下面是一個例子:
int n=10000;chars[10];sprintf(s,”%d”,n);// s中的內容為“10000”
到目前為止看起來還不錯。但是,對上面代碼的一個微小的改變就會使程式崩潰:
int n=10000;char s[10];sprintf(s,”%f”,n);// 看。錯誤的格式化符
在這種情況下,程式員錯誤地使用了%f格式化符來替代了%d。因此,s在調用完sprintf()後包含了一個不確定的字串。要是能自動推匯出正確的類型,那不是更好嗎。
進入stringstream
由於n和s的類型在編譯期就確定了,所以編譯器擁有足夠的資訊來判斷需要哪些轉換。庫中聲明的標準類就利用了這一點,自動選擇所必需的轉換。而且,轉換結果儲存在stringstream對象的內部緩衝中。你不必擔心緩衝區溢位,因為這些對象會根據需要自動分配儲存空
你的編譯器支援嗎。
庫是最近才被列入C++標準的。(不要把與標準發布前被刪掉的弄混了。)因此,老一點的編譯器,如GCC2.95,並不支援它。如果你恰好正在使用這樣的編譯器而又想使用的話,就要先對它進行升級更新。
庫定義了三種類:istringstream、ostringstream和stringstream,分別用來進行流的輸入、輸出和輸入輸出操作。另外,每個類都有一個對應的寬字元集版本。簡單起見,我主要以stringstream為中心,因為每個轉換都要涉及到輸入和輸出操作。
注意,使用string對象來代替字元數組。這樣可以避免緩衝區溢位的危險。而且,傳入參數和目標對象的類型被自動推匯出來,即使使用了不正確的格式化符也沒有危險。
string到int的轉換
string result=”10000”;int n=0;stream<<result;stream>>n;//n等於10000
重複利用stringstream對象
如果你打算在多次轉換中使用同一個stringstream對象,記住再每次轉換前要使用clear()方法;
在多次轉換中重複使用同一個stringstream(而不是每次都建立一個新的對象)對象最大的好處在於效率。stringstream對象的構造和解構函式通常是非常耗費CPU時間的。
一些執行個體:
stringstream通常是用來做資料轉換的。
相比c庫的轉換,它更加安全,自動和直接。
例子一:基礎資料型別 (Elementary Data Type)轉換例子 int轉string
#include <string>#include <sstream>#include <iostream> int main(){ std::stringstream stream; std::string result; int i = 1000; stream << i; //將int輸入資料流 stream >> result; //從stream中抽取前面插入的int值 std::cout << result << std::endl; // print the string "1000"}
例子二:除了基本類型的轉換,也支援char *的轉換。
#include <sstream>#include <iostream> int main(){ std::stringstream stream; char result[8] ; stream << 8888; //向stream中插入8888 stream >> result; //抽取stream中的值到result std::cout << result << std::endl; // 螢幕顯示 "8888"}
例子三:再進行多次轉換的時候,必須調用stringstream的成員函數clear().
#include <sstream>#include <iostream>int main(){ std::stringstream stream; int first, second; stream<< "456"; //插入字串 stream >> first; //轉換成int std::cout << first << std::endl; stream.clear(); //在進行多次轉換前,必須清除stream stream << true; //插入bool值 stream >> second; //提取出int std::cout << second << std::endl;}