創作內容

31 GP

stringstream用法整理

作者:驥哥│2018-09-01 02:01:08│贊助:1,256│人氣:16776
今天來分享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的操作介紹完了,自己也記的更熟了一點謝謝大家。
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=4114818
All rights reserved. 版權所有,保留一切權利

相關創作

留言共 8 篇留言

jenny
程式很強(嘻嘻~

09-01 09:19

驥哥
沒啦XD 邊整理自己也在學習
09-01 13:52
烤飯糰大師
原來小屋也有放 再跪一次<(_ _)>

09-02 00:16

驥哥
勿 真的版上窩還是小嫩嫩 最爛ㄉ那種
09-02 00:19
麻塔巴巴
學了這ㄍ之後要對數字操作都會懶得想算法 直接拿stringstream下去硬幹= =

尼會ㄅ會這樣R

09-03 01:15

驥哥
能用數字解就用數字解 字串4第二道防線
09-03 15:32
小浣熊ʕ•ᴥ•ʔ
謝謝 受益良多

10-14 00:11

修加
哥,有講istringstream的部分嗎? 我有些分不出差別,目前你教的最詳細。

01-15 23:12

明石改修工廠早見表
講的好詳細~ 謝謝你

04-02 21:09

端正自己的品性
你好
請問文中的 >>代表寫入stringstream中,<<代表從stringstream拿出
是不是反了 還是我有理解錯誤呢
因為我是看程式碼覺得寫入好像是<< 拿出好像是>> 感謝您~

05-29 19:35

驥哥
ㄜ對 那部份好像是我筆誤 謝謝你提出來XD06-06 20:40
Absinthe
google排名超前面 首推精華文章

06-06 19:40

驥哥
真假 沒注意過耶ㄏㄏ06-06 20:44
我要留言提醒:您尚未登入,請先登入再留言

31喜歡★leichitw 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:vector簡單用法整理... 後一篇:2018/9/29 日誌...

追蹤私訊

作品資料夾

pig156769為什麼故事不感人?
請進小屋文章解析看更多我要大聲說昨天16:04


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

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