boost lexical_cast format

來源:互聯網
上載者:User

Boost中包括五個字串與文本處理領域的程式庫:
 【1】兩個與c標準庫函數功能類似的lexical_cast和format,它們關注與字串的表示,可以將數值轉化為字串,對輸出做精確的格式化。
 【2】string_algo庫提供了大量常用的字串處理函數
 【3】tokenizer和xpressive,前者是一個分詞器,後者則是一個靈活的Regex分析器,同時也是一個文法分析器.

lexical_cast:
 lexical_cast庫進行"字面量"的轉換,類似c中的atio函數,可以進行字串,整數/浮點數之間的字面轉換。
#include<boost/lexical_cast.hpp>
using namespace boost;
用法:

 lexcial_cast使用類似c++98標準轉型操作符(xxx_cast)的形式給出了通用,一致,可理解的文法。
 使用lexcical_cast可以很容易地在數值與字串之間轉換,只需要在模板參數中指定轉換的目標類型即可,樣本:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
int main()
{
 int x = lexical_cast<int>("100");
 long y = lexical_cast<long>("2000");
 float pai = lexical_cast<float>("3.14159e5");
 double e = lexical_cast<double>("2.71828");
 cout<<x<<","<<y<<","<<pai<<","<<e<<endl;
 string str = lexical_cast<string>(456);
 cout<<str<<endl;
 cout<<lexical_cast<string>(0.618)<<endl;
 cout<<lexical_cast<string>(0x10)<<endl;
 system("pause");
 return 0;
}
 注意:要轉換成數位字串中只能有數字和小數點,不能出現字母(表示指數的e/E除外)或其他非數字字元,也就是說,lexcical_cast不能轉換如"123L","0x100"這樣的c++文法許可的數字字面量字串,而且lexcical_cast不支援進階的格式控制,不能把數字轉換成指定格式的字串,如果要更進階的格式控制,可使用std::stringstream或者boost::format;
 除了轉換數值與字串,lexcical_cast也可以轉換bool類型,但功能很有限,不能使用true/false字面量,只能使用1或0;
cout<<lexical_cast<bool>("1")<<endl;

異常bad_lexical_cast
 當lexcical_cast無法執行轉換操作時會拋出異常bad_lexical_cast,它是std::bad_cast的衍生類別,為了使程式更加健壯,使用try/catch塊來保護轉碼;
樣本:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
int main()
{
 try
 {
  cout<<lexical_cast<int>("0x100")<<endl;
  cout<<lexical_cast<double>("HelloWorld")<<endl;
  cout<<lexical_cast<long>("100L")<<endl;
  cout<<lexical_cast<bool>("false")<<endl;
 }
 catch (bad_lexical_cast& e)
 {
  cout<<"error: "<<e.what()<<endl;
 }
 system("pause");
 return 0;
}
 也可以利用bad_lexical_cast來驗證數字字串的合法性,實現一個模板函數num_valid()代碼如下:
template<typename T>
bool num_valid(const char *str)
{
 try
 {
  lexical_cast<T>(str);
  return true;
 }
 catch(bad_lexical_cast&)
 {
  return false;
 }
}
int main()
{
 assert(num_valid<double>("3.14"));
 assert(!num_valid<int>("3.14"));
 assert(num_valid<int>("65535"));
 system("pause");
 return 0;
}

轉換對象的要求:
 lexical_cast實際是一個模板函數,內部使用了標準庫的流操作,因此,對於它的轉換對象有如下要求:
 【1】轉換起點對象是可流輸出的,即定義了operator<<;
 【2】轉換終點對象是可流輸入的,即定義了operator>>;
 【3】轉換終點對象必須是可預設構造和可拷貝構造的;
 c++語言中的內建類型(int,double等)和std::string都滿足以上的三個條件;

應用於自己的類:
 如果要將lexcical_cast應用於自訂的類,把類轉換為可理解的字串描述,只需要滿足lexcical_cast的要求即可,準確地說,需要實現流輸出操作符operator<<;
示範:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
class demo_class
{
 friend std::ostream& operator<<(std::ostream& os, const demo_class& x)
 {
  os<<"demo_class's Name";
  return os;
 }
};
int main()
{
 cout<<lexical_cast<string>(demo_class())<<endl;
 system("pause");
 return 0;
}
 這段代碼值得提取一個模板類,可以仿造boost.operator庫,定義一個模板類outable,以簡化流輸出操作符<<重載,注意這裡沒有使用基類鏈技術,不能用operator的基類串聯;
樣本:
#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace boost;
using namespace std;
template<typename T>
struct outable
{
 friend std::ostream& operator<<(std::ostream& os, const T &x)
 {
  os<<typeid(T).name();
  return os;
 }

};
class demo_class: outable<demo_class>
{};
int main()
{
 cout<<lexical_cast<string>(demo_class())<<endl;
 system("pause");
 return 0;
}
 這樣任何繼承outable的類,都會自動獲得流輸出操作符<<或者lexcical_cast的支援
 依據同樣的原理,也可以實現流輸入操作符>>的重載.

format:
 boost.format可以把參數格式化到一個字串,而且是完全型別安全的。
#include<boost/format.hpp>
using namespace boost;
簡單例子:
#include <assert.h>
#include <iostream>
#include <boost/format.hpp>
using namespace boost;
using namespace std;
int main()
{
 cout<<format("%s:%d+%d=%d\n")%"sum"%1%2%(1+2);
 format fmt("(%1% + %2%) * %2% = %3%\n");
 fmt %2%5;
 fmt %((2+5)*5);
 cout<<fmt.str();
 system("pause");
 return 0;
}

輸入操作符%:
為什麼使用重載操作符:
 基於型別安全的考慮,format不能使用省略符號來實現可變參數,如果使用函數的調用形式,那麼就需要定義不同參數數量的模板函數,如:
template<class T1, class T2, .., class TN>
string format(string s, const T1 &x1, ..., const T1& xN);
 在c++沒有實現可變數量模板參數之前,無論定義多少個這樣的重載形式,都無法滿足格式化“無限”個參數的需求,因此,必須使用操作符的方式來接受參數,而且IO流的operator<<已經應用了許多年,證明這種方式的確有效,

二元操作符operator%()聲明如下:
format& operator%(T& x);
 它接受format對象和任意值作為參數,然後返回format對象的引用,因此可以再對返回的format對象實施%操作符,所以:
format("...")%x%y
被編譯器解釋為:
 operator%(format("..."), x) %y  =>
 operator%(operator%format("..."), x), y)
依次類推,從而能夠接受無限個待格式化的參數。

類摘要:
 format並不是一個真正的類,而是一個typedef,真正的實現是basic_format
格式化文法:
 format基本繼承了printf的格式化文法,僅對printf文法有少量的不相容;
 
 每個printf格式化選項以%開始,後面是格式規則,規定了輸出的對齊,寬度,字元類型:
 【1】%05d;輸出寬度為5的整數,不足位用0填充
 【2】%-8.3f;輸出靠左對齊,總寬度為8,小數位3位的浮點數
 【3】%10s;輸出10位的字串,不足位用空格填充
 【4】%05X;輸出寬度為5的大寫16進位整數,不足位用0填充。
在經典的printf式格式化外,format還增加了新的格式:
 【5】%|spec|:與printf格式選項功能相同,但兩邊增加了豎線分隔,可以更好地區分格式化選項與一般字元;
 【6】%N%;標記第N個參數,相當於預留位置,不帶任何其他的格式化選項。

進階用法:
 format提供了類似printf的功能,但它並不等同於printf函數,這就是物件導向的好處,在通常的格式化字串之外,format類還擁有幾個進階功能,可以再運行時修改格式化選項,綁定輸入參數。
這些進階功能用到的函數如下:
 【1】basic_format&bind_arg(int argN, const T& val)
  把格式化字串第argN位置的輸入參數固定為val,即使調用clear()也保持不變,除非調用clear_bind()或clear_binds().
 【2】basic_format& clear_bind(int argN)
  取消格式化字串第argN位置的參數綁定.
 【3】basic_format& clear_binds()
  取消格式化字串所有位置的參數綁定,並調用clear().
 【4】basic_format& modify_item(int itemN, T manipulator)
  設定格式化字串第itemN位置的格式化選項,manipulator是一個boost::io::group()返回的對象。
 【5】boost::io::group(T1 al, ..., Var const &var)
  它是一個模板函數,最大支援10個參數(10個重載形式),可以設定IO流操縱以指定格式或輸入參數值,IO流操縱器位於標頭檔<iomanip>.
 
樣本:
#include <iostream>
#include <boost/format.hpp>
#include <iomanip>
using namespace boost;
using boost::io::group;
using namespace std;
int main()
{
 //聲明format對象,有三個輸入參數,五個格式化選項
 format fmt("%1% %2% %3% %2% %1% \n");
 cout<<fmt %1 % 2 % 3;
 fmt.bind_arg(2, 20); //將第二個輸入參數固定為數字20
 cout<<fmt %1 %3;  //輸入其餘兩個參數
 fmt.clear();   //清空緩衝,但綁定的參數不變
 //在操作符中使用group(),指定IO流操縱符第一個參數顯示為八進位
 cout<<fmt % group(showbase, oct, 111) % 333;
 fmt.clear_binds();  //清除所有綁定參數
 //設定第一個格式化項,十六進位,寬度為8,靠右對齊,不足位用*填充
 fmt.modify_item(1, group(hex, right, showbase, setw(8), setfill('*')));
 cout<<fmt % 49 % 20 %100;
 system("pause");
 return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.