小屋創作

日誌2018-09-01 02:01

stringstream用法整理

作者:驥哥

今天來分享stringstream的用法,剛好一邊打心得文邊學,感覺比較好記XD

stringstream是一個C++底下的類別,專門拿來讀取字串並且處理,很多時候拿來做字串的切割,或者是int跟string類別之間的轉換。
●標頭檔

#include <sstream>
若是要用到stringstream類別必須引入此標頭檔

●把int型態的數字轉成string
此時的stringstream就像個橋樑,可以負責當中間轉換的部分。
stringstream提供了>><<運算子來讀取或寫入:
>>代表寫入stringstream中,<<代表從stringstream拿出。

#include <sstream>
using namespace std;
int main()
{
    stringstream s1;
    int number =1234;
    string output;//要把number轉成字串型態的容器
    
    cout<<"number="<<number<<endl;//顯示number=1234;
    
    s1<<number; //將以int宣告的number放入我們的stringstream中
    s1>>output;
    
    cout<<"output="<<output<<endl;//顯示output=1234;
}
值得注意的是我們兩行顯示都是1234但是他的資料型態卻已經不一樣了,第一個是int的型態,第二行則是string的型態。

●相反的stringstream也可以將string轉成int

#include <sstream>
using namespace std;
int main()
{
    stringstream string_to_int;
    string s1="12345";
    int n1;

    string_to_int<<s1;
    //也可以使用string_to_int.str(s1);
    //或者 s1=string_to_int.str();
    
    string_to_int>>n1;

    cout<<"s1="<<s1<<endl;//s1=12345
    cout<<"n1="<<n1<<endl;//n1=12345
    
}

●分割字串的範例:
這邊我們來一個在網路上看到的簡單例題來說明怎麼分割字串。
題目內容:輸入第一行數字N代表接下來有N行資料,接著每行有不定個數的整數(最多20個,每行最大200個字元),請把每行的總和印出來。
輸入:輸出:
4
1 1 2 3 5 8 13
1 1 5
11 557 996 333
2 4 6
輸出
33
7
1897
12
程式碼部分:

#include <sstream>
#include <iostream>
using namespace std;
int main()
{
    stringstream s1;
    int N;//代表有幾行
    int i1;//用來存放string轉成int的資料
    while(cin>>N)
    {
      cin.ignore();
      string line;//讀入每行的資料
      for(int i=0;i<N;i++)
      {
         getline(cin,line);//讀入每行的資料
         int sum=0;//計算總和
         s1.clear();//清除緩存
         s1<<line;
         //也可以使用s1.str(line);
         //還可以寫成line=s1.str();
         while(true)
         {
           s1>>i1;
           if(s1.fail()) break;//確認stringstream有正常流出,沒有代表空了
           sum+=i1;//把每個轉換成int的數字都丟入sum累加
         }
         cout<<sum<<endl;
      }
    }
}

●針對stringstream類別的初始化
這邊要提到一點就是要重複使用一個stringstream的情況,因為宣告stringstream類別的時候其實蠻消耗CPU的時間,在解題目以及應用的時候不太建議重複宣告,而是使用完之後就初始化再次利用。
基本就是要以下這兩行:

#include <sstream>
#include <iostream>
using namespace std;
int main()
{
    ////////基本的初始化stringstream
    stringstream s1;
    s1.str("");
    s1.clear();
}
這邊有個重點就是s1.str("");    s1.clear();
這兩行基本上缺一不可,缺少了任一行就會導致某些情況下的錯誤。
1.僅只用s1.str("");   未使用s1.clear();

#include <sstream>
#include <iostream>
using namespace std;
int main()
{
    stringstream ss;
    int i1=77777;
    string s1;
    ss<<i1;
    ss>>s1;
    
    cout<<"i1 = "<<i1<<endl;
    cout<<"s1 = "<<s1<<endl;

    //僅用ss.str("");初始化
    ss.str("");
    //////////////////////
    string s2="888888";
    int i2=0;
    ss<<s2;
    ss>>i2;
    
    cout<<"str type = "<<ss.str()<<endl;//這邊理論上會藉由ss<<s2寫入stringstream
    cout<<"int type = "<<i2<<endl;//理論上會藉由ss>>i2;寫到i2內部



}
結果:
有發現了嗎?我們初始化並沒有成功,s2並沒有成功的放入ss,而且ss也沒有成功的傳到i2內。
原因是出在當執行到ss>>s1這行時,我們的stringstream已經讀到EOF了。
stringstream的情況大概是這樣的
執行完ss>>s1時的情況:"77777"EOF
當我們使用ss.str("")時:""EOF
對,他並不會把EOF的地方清空,會繼續保留,再次使用的時候就會發生錯誤了。

2.僅只用ss.clear();     

#include <sstream>
#include <iostream>
using namespace std;
int main()
{
    stringstream ss;
    int i1=87;
    string s1;
    
    ss<<i1;
    ss>>s1;
    
    cout<<"i1="<<i1<<endl;
    cout<<"s1="<<s1<<endl;
    
    ss.clear();
    
    string s2="877";
    int i2;
    
    ss<<s2;
    ss>>i2;

    cout<<"stringstream內部="<<ss.str()<<endl;
    cout<<"s2="<<s2<<endl;
    cout<<"i2="<<i2<<endl;

}
結果:
這邊發現stringstream的內部有點奇怪呢,他還保存著之前的結果,並不算完全的初始化。
來分析一下stringstream內部在程式內運行的結果:
執行完ss>>s1時的內部狀況:87EOF

此時有了EOF之後已經不能再操作了,接著使用ss.clear();
此時stringstream內部的情況:87(沒有EOF了可以繼續操作)

執行完ss<<s2時的內部狀況:87877EOF

大概就這樣把基本的stringstream的操作介紹完了,自己也記的更熟了一點謝謝大家。

74

19

LINE 分享

相關創作

《劍與魔法與自爆裝置 》讀後

(開箱)抽不到就用買的!!!少女與戰車-戰車道大作戰手遊全角色畫冊~

【生活日記】2022/07/12拜二、(7/11)上山&短暫的消愁

留言

開啟 APP

face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】