如何處理字串(C++11)

C++對於字串的處理已經很方便、很高階了(跟C相比)
只是要用對方法
字串處理起來的舒暢程度我認為不輸Java
而我所用的方法其實說穿了就是C++的標準函式庫(STL)

以下是我們在處理字串時會用到三個東西,分別是兩個Class和一個function
第一個是std::string,這裡是std::string相關的C++ Reference頁面
第二個是std::stringstream,這裡是std::stringstream相關的C++ Reference頁面
最後是std::getline,這裡是std::getline相關的C++ Reference頁面

[目錄]
    概論:該如何安全地處理字串
    字串相關的宣告與初值化:std::string、std::stringstream
    字串的讀取、切割字串
    字串的常用操作:拼接、尋找、刪除、插入、加長、相等比較、取代
    字串的型態轉換


[概論:該如何安全地處理字串]
    1.所有變數皆用std::string,不用任何char*或char[]
    2.任何型態的變數都先丟進std::stringstream,再丟出來變成切好的std::string來做
       所有我們想做的字串處理(尋找,拼接,相等比較等等)
       很多時候其實我們只需要切字串,所以std::stringstream丟出來之後就搞定了
    3.做完處理的字串,除了幾個方便簡短的轉換函數可以記一下以外
       若要做型態轉換的話,就都再丟一次std::stringstream
       它出來可以指派給任何資料型態的變數
    4.用std::vector儲存需要存的std::string

    要注意的是,用我所說的方法
    可以確保程式是安全的、簡潔的,而且寫起來是順暢的
    但速度並沒有用C或是其他較低階的函數操作來得快


[字串相關的宣告與初值化:std::string、std::stringstream]
先看std::stringstream的宣告
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        std::stringstream ss1("hello");          //often used
        std::stringstream ss2, ss3, ss4, ss5;
        ss2.str("haha");
        std::string str_hey = "hey";
        ss3.str(str_hey);
        ss4 << "cool";
        ss5 << str_hey;

        std::cout << "ss1: " <<  ss1 << std::endl;
                  << "ss1.str(): " << ss1.str() << std::endl
                  << "ss2.str(): " << ss2.str() << std::endl
                  << "ss3.str(): " << ss3.str() << std::endl
                  << "ss4.str(): " << ss4.str() << std::endl
                  << "ss5.str(): " << ss5.str() << std::endl;
}
result : 
    這裡比較值得一提的是如果是 ss4 << "so" << "cool" << std::endl;的話
    他的效果會等同於先做 ss4 << "so",接著ss4 << "cool",最後ss4 << std::endl;
    就像我們習以為常的std::cout << 一樣


接著看std::string的宣告,這太基本了我快速帶過
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        std::string str1 = "hello";
        std::string str2("hi");
        std::string str3 = "";     //often used
        str3 = "hey";
        std::cout << "str1: " <<  str1 << std::endl
                  << "str2: " <<  str2 << std::endl
                  << "str3: " <<  str3 << std::endl;
        /*result:
          str1: hello
          str2: hi
          str3: hey         
         */
}


[字串的讀取、切割字串]
    這裡的讀取是指從std::strinstream中取出std::string
    切割字串主要有兩種方式
    1. 直接從std::stringstream取出std::string。此方法用任意空白做切割
    2. 用std::getline()把std::stringstrem用特別的std::string做斷句取出。
        此種方法可以指定特定的字串做切割,但若沒指定則不會切割空白
  
先展示如何從std::stringstream讀取std::string
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        std::stringstream ss("a      long. string!!");
        std::string str1, str2, str3, str4;
        ss >> str1; //a
        ss >> str2; //long.
        ss >> str3; //string!!
        ss >> str4; //ss is empty
        std::cout << "ss.str(): " << ss.str() << std::endl
                  << "str1: " << str1 << std::endl
                  << "str2: " << str2 << std::endl
                  << "str3: " << str3 << std::endl
                  << "str4: " << str4 << std::endl
                  << "ss >> str4: " << (ss >> str4) << std::endl;
}
result:
    這裡有兩個事情需要注意
    1. 當std::stringstream已經讀完(讀取的位置已經到最後了),再讀都只能得到空白
        而且這個讀取的動作會返回一個0的值,可用於迴圈對於讀取完畢的判斷
    2. 是如果已經讀完,又讀了空白的話(非空格),此時讀取位置會設成-1
        此時無法用ss.seekg(0)來設定讀取位置,只能用ss.clear()清除資料後重新來過
        否則此std::stringstream將再也讀不出資料來

    接著來看切割字串,一共兩招
    第一招就只是剛才的程式碼加上迴圈而已
1. 直接從std::stringstream取出std::string。此方法用任意空白做切割
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        std::stringstream ss("a      long. string!!");
        std::string str = "";
        while(ss >> str){
                std::cout << str << std::endl;
        }
}
result:



2. 用std::getline()把std::stringstrem用特別的std::string做斷句取出。
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        std::stringstream ss("a      long. string!!");
        std::string str = "";
        while(std::getline(ss,str,'n')){
                std::cout << str << std::endl;
        }
}
result:
    這裡要注意的是
    第三個argument只能放char,不能放std::string



[字串的常用操作:拼接、尋找、刪除、插入、加長、相等比較、取代]
這太基本了我快速帶過
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        
        std::string str = "Hello world";

        //mix
        std::string str1 = "I'm Burwei!!";
        str1 = str + ". " + str1;
        std::cout << str1 << std::endl; //result: Hello world. I'm Burwei!!

        //find      
        std::cout << str.find("l") << std::endl; //result: 2 
        std::cout << str.find("l",0) << std::endl; //result: 2 

        //erase
        std::string str2 = str; //Hello world
        std::cout << str2.erase(2,2) << std::endl; //result: Heo world

        //insert
        std::string str3 = str; //Hello world
        std::cout << str3.insert(3,"HAHA") << std::endl;//result: HelHAHAlo world

        //append
        std::string str4 = str; //Hello world
        std::cout << str4.append("HAHA") << std::endl; //result: Hello worldHAHA

        //replace
        std::string str5 = str; //Hello world
        std::string token_old = "l";
        std::string token_new = "LLL";
        int pos = 0;
        while((pos = str5.find(token_old,pos)) != std::string::npos) {
                str5.replace(pos, token_old.length(),token_new);
        }
        std::cout << str5 << std::endl; //result: HeLLLLLLo worLLLd

        //compare
        if(str==str1)
                std::cout << "str==str1" << std::endl;
        else
                std::cout << "str!=str1" << std::endl; //result: str!=str1
}


[字串的型態轉換]
最後,展示一下用std::stringstream做型態轉換
//stringstream_test.cpp
#include <iostream>
#include <string>
#include <sstream>

int main(){
        
        std::stringstream ss1, ss2;
        ss1 << "1234" << 1.234 << "cool";
        ss2 << "1234" << " "  << 1.234 << " " << " cool";
        float a, b, c, d;
        char ch1[100] = {0};
        char ch2[100] = {0};
        ss1 >> a >> b >> ch1;
        ss2 >> c >> d >> ch2;
        std::cout << std::setprecision(8)
                  << "a+b: " << a+b << std::endl
                  << "a: " << a << " / b: " << b << std::endl
                  << "ch1: " << ch1 << std::endl
                  << "c+d: " << c+d << std::endl
                  << "c: " << c << " / d: " << d << std::endl
                  << "ch2: " << ch2 << std::endl;
}
result:


好了,今天的筆記到此結束

留言

這個網誌中的熱門文章