1. 程式人生 > >c++中stringstream 類的用法及字串與數字之間轉化

c++中stringstream 類的用法及字串與數字之間轉化

iostream標準庫支援對於記憶體的輸入輸出,只要將流與儲存在程式記憶體中的string物件捆綁在一起,就可以使用通用的輸入輸出操作符來讀寫string物件!標準庫中定義了三種類型的字串流:
istringstream,由istream派生出來的,用於讀一個string的物件;
ostringstream,由ostream派生出來的,用於寫一個string的物件;
stringstream,由iostream派生出來,同時提供了對於stringstream物件的功能!!
要是用上述的三個類,必須包含sstream標頭檔案!!

stringstream物件的一個重要的功能是讓我們更方便的操作string物件!

1.stringstream::str(); returns a string object with a copy of the current contents of the stream.

 2.stringstream::str (const string& s); sets s as the contents of the stream, discarding any previous contents.

  3.stringstream清空,stringstream s; s.str("");

  4.實現任意型別的轉換

template<typename out_type, typename in_value>
    out_type convert(const in_value & t){
    stringstream stream;
    stream<<t;//向流中傳值
    out_type result;//這裡儲存轉換結果
    stream>>result;//向result中寫入值
   return result;


例子:可以在定義這個物件的時候進行初始化操作:
#include<sstream>
#include<string>
#include<iostream>
using namespace std;
int main()
{
            string str;
            int i = 12345;
            stringstream ss;
            ss << i;
            str = ss.str();
            return 0;
}

其中ss.str()返回的是一個流中儲存的string物件的副本,這樣就實現了通過流物件對一個string物件的賦值操作從而增加string物件操作的靈活性!

2、另外一個很重要的方面就是可以通過stringstream來實現資料型別的轉換將一個string物件中儲存的字串
還原成原來的資料結構!
#include<sstream>
#include<string>
#include<iostream>
using namespace std;
int main()
{
            string str = “12345true”;
            stringstream ss;
            int i;
            bool j;
            ss.str(str);
            ss >> i;
            ss >> j;
            cout << i <<endl;
            cout << j <<endl;
            return 0;
}
3、另外一個非常重要是將其作為一個socket通訊中一個重要的載體來接收和儲存recv和send處理的資料!
這樣就可以直接作為boost序列化和反序列化的操作物件,來實現序列化和反序列化的操作!
while(true)
{
          if((x = recv(int socket,char *buf, int len,0)) < 0)
           {
                        sys_err("recv() error!!");
                        exit(-1);
            }
           else if(x > 0)//說明此處的資料尚未接收完畢,繼續往流物件中新增!!
           {
                      ss << buf;

         }
            else
            {
                          break;
             }
}
boost::archive::text_iarchive ia(ss);
ia >> BOOST_SERIALIZATION_NVP(des);//這樣就可以直接將接受的資料物件進行反序列化操作,在
記憶體中進行,提高了速度!!這裡對於des目標類的序列化操作具體課參加這篇文中的內容!http://www.linuxidc.com/Linux/2012-08/69192.htm
send(int socket,char *buf,int len,0);
對於傳送的操作同樣可以直接利用我們這裡stringstream物件:
boost::archive::text_oarchive oa(ss);
oa << BOOST_SERIALIZATION_NVP(des);通過這樣的方式將我們需要傳送的資料結構寫入流物件!
send(socket,ss.str(),ss.str().size(),0);將流中儲存的序列化之後的字串,直接傳送出去,加快了速度!

4、在型別轉換中使用模板

你可以輕鬆地定義函式模板來將一個任意的型別轉換到特定的目標型別。例如,需要將各種數字值,如int、long、double等等轉換成字串,要使用以一個string型別和一個任意值t為引數的to_string()函式。to_string()函式將t轉換為字串並寫入result中。使用str()成員函式來獲取流內部緩衝的一份拷貝:

template<class T>

void to_string(string & result,const T& t)

{

 ostringstream oss;//建立一個流

oss<<t;//把值傳遞如流中

result=oss.str();//獲取轉換後的字元轉並將其寫入result
}

這樣,你就可以輕鬆地將多種數值轉換成字串了:

to_string(s1,10.5);//double到string

to_string(s2,123);//int到string

to_string(s3,true);//bool到string

可以更進一步定義一個通用的轉換模板,用於任意型別之間的轉換。函式模板convert()含有兩個模板引數out_type和in_value,功能是將in_value值轉換成out_type型別:

template<class out_type,class in_value>

out_type convert(const in_value & t)

{

stringstream stream;

stream<<t;//向流中傳值

out_type result;//這裡儲存轉換結果

stream>>result;//向result中寫入值

return result;

}

這樣使用convert():

double d;

string salary;

string s=”12.56”;

d=convert<double>(s);//d等於12.56

salary=convert<string>(9000.0);//salary等於”9000”

數字轉字串:
用C++的streanstream:

#include <sstream>
#Include 
<string>
string num2str(double i)
{
        stringstream ss;
        ss
<<i;
        
return ss.str();
}

字串轉數字:

int str2num(string s)
 
{   
        
int num;
        stringstream ss(s);
        ss
>>num;
        
return num;
}
對比之前的sprintf和scanf函式:

sprintf函式原型為 int sprintf(char *str, const char *format, ...)。作用是格式化字串,具體功能如下所示:

  (1)將數字變數轉換為字串。

  (2)得到整型變數的16進位制和8進位制字串。

  (3)連線多個字串。

int main(){
    char str[256] = { 0 };
    int data = 1024;
    //將data轉換為字串
    sprintf(str,"%d",data);
    //獲取data的十六進位制
    sprintf(str,"0x%X",data);
    //獲取data的八進位制
    sprintf(str,"0%o",data);
    const char *s1 = "Hello";
    const char *s2 = "World";
    //連線字串s1和s2
    sprintf(str,"%s %s",s1,s2);
    cout<<str<<endl; 
    return 0;
} 

 sscanf函式原型為int sscanf(const char *str, const char *format, ...)。將引數str的字串根據引數format字串來轉換並格式化資料,轉換後的結果存於對應的引數內。具體功能如下:

  (1)根據格式從字串中提取資料。如從字串中取出整數、浮點數和字串等。

  (2)取指定長度的字串

  (3)取到指定字元為止的字串

  (4)取僅包含指定字符集的字串

  (5)取到指定字符集為止的字串

  當然,sscanf可以支援格式串"%[]"形式的,有興趣的可以研究一下。

int main(){
    char s[15] = "123.432,432";
    int n;
    double f1;
    int f2;
    sscanf(s, "%lf,%d%n", &f1, &f2, &n);
    cout<<f1<<" "<<f2<<" "<<n;
    return 0;
} 輸出:1 1 23 23 # 0 4 4
常見的格式串:
%% 印出百分比符號,不轉換。
  %c 整數轉成對應的 ASCII 字元。
  %d 整數轉成十進位。
  %f 倍精確度數字轉成浮點數。
  %o 整數轉成八進位。
  %s 整數轉成字串。
  %x 整數轉成小寫十六進位。
  %X 整數轉成大寫十六進位。
  %n sscanf(str, "%d%n", &dig, &n),%n表示一共轉換了多少位的字元