1、lexical_cast
一些常見的數值,字符互轉函數:
整型int:
itoa()、_itoa_s
atoi()、_ttoi
無符號整型unsigned int:
_ultoa_s()、_ultot_s
strtoul()、_tcstoul
長整型long long:
_i64toa_s()、_i64tot_s
_atoi64()、_ttoi64,strtoll(C99/C++11)
無符號長整型unsigned long long:
_ui64toa_s()、_ui64tot_s
_strtoui64()、_tcstoui64,strtoull(C99/C++11)
浮點型double:
atof()、_ttof,strtod
char buf[10] = {0};
_gcvt_s(buf, 10, 12.345, 5);//最后一個參數為要轉換的位數
boost的lexical_cast提供數字、字符串之間的相互轉換,可以用來替代上面的atoi、itoa、strtol等,使用需要包含boost\lexical_cast.hpp:
int x = lexical_cast<int>("100"); double d = lexical_cast<double>("3.14"); string str = lexical_cast<string>(100); string str2 = lexical_cast<string>(3.14);
需要注意的是當浮點數float、double轉化為字符串的時候會將不精確的數字也轉換,如上面的3.14轉換成了"3.1400000000000001",如果需要指定小數位數的轉換的話可以使用下面的format。
當lexical_cast無法執行轉換操作時會拋出bad_lexical_cast異常,它是std::bad_cast的派生類,我們可以實現一個模板函數來判斷用戶輸入的是否是有效的數值:
template<typename T>
bool num_valid(const char* pStr) { try { lexical_cast<T>(pStr); return true; } catch (bad_lexical_cast) { return false; } } bool bRet; char* pInputStr = "123"; bRet = num_valid<int>(pInputStr); //輸入有效
pInputStr = "123test"; bRet = num_valid<int>(pInputStr); //輸入無效
lexcical_cast對於轉換對象有三個要求:轉換起點對象是可流輸出的,即定義了operator<<;轉換終點對象是可流輸入的,即定義了operator>>;轉換終點對象必須是可缺省構造和拷貝構造的。C++中的內建類型int、double等以及std::string都滿足前面的可轉換條件,而STL中的容器則不可轉換,對於用戶自定義類型需要滿足前面三個條件可以進行轉換。
2、format
format可以把參數格式化到一個字符串中,而且是類型安全的,使用format需要包含頭文件"boost\format.hpp",使用示例:
string str = "value"; int num = 100; cout << format("%s: %d \n") % str % num; //format支持流輸出,可以直接向輸出流cout輸出內部保存的字符串,輸出value: 100
format fmt("%s: %d, %s: %d \n"); fmt % str % num; fmt % str % num; //可以多次輸入參數
string strFmt = fmt.str(); //strFmt為 value: 100, value: 100
fmt.clear(); fmt % "test" % 99 % "test2" %100; cout << fmt; format fot("%1%: %2%, %1%: %2% \n"); // %n%用來指定使用的參數
fot % str % num; cout << fot; //輸出 value: 100, value: 100
fot.parse("%f \n"); fot % 3.14; cout << fot; //輸出 3.140000
format對象的一些成員函數:
str():返回內部已經格式化好的字符串
size():相當於str().size()
clear():清空內部緩存,執行后立即調用str()或size()會拋出異常
parse():清空內部緩存並使用一個新的格式化字符串,執行后立即調用str()或size()會拋出異常
參數及其數量必須匹配格式化字符串中要求的參數及數量,否則使用<<輸出format對象、調用成員函數str()、size()等會拋出異常,所以使用format的時候最好加上異常處理。
format基本繼承了printf的格式化語法,如:
%05d:輸出寬度為5的整數,不足位用0填充
%-8.3f:輸出左對齊,寬度為8,小數位3位的浮點數
% 10s:輸出寬度為10的字符串,不足位用空格填充
%5X:輸出寬度為5的大寫十六進制整數
format要比printf速度慢幾倍,可以先建立const format對象,然后拷貝這個對象進行格式化操作,這樣比直接使用format對象能夠提高一些速度:
const format fmt("%d, %d"); string str = (format(fmt) % 50 % 100).str();
3、string_algo
string_algo是一個非常全面的字符串算法庫,使用它需要包含頭文件"boost\algorithm\string.hpp",算法庫的命名規范符合標准庫的慣例:前綴i表示是大小寫不敏感的,后綴_copy即為不改變原輸入的copy版本,后綴_if表示使用一個謂詞函數對象,很多算法都有包含這三個版本的函數,使用示例:
#include "boost\algorithm\string.hpp"
int main() { string str("readme.txt"); boost::to_upper(str); string strUpper = boost::to_lower_copy(str); bool bRet = boost::starts_with(str, "read"); bRet = boost::iends_with(strUpper, "txt"); bRet = boost::contains(str, "me"); boost::all(str, boost::is_lower()); //判斷每個字符是否都是小寫
boost::all(str, boost::is_alpha()); //判斷每個字符是否都是字母
boost::all(str, boost::is_digit()); //判斷每個字符是否都是十進制數字
boost::all(str, boost::is_alnum()); //判斷每個字符是否都是字母或數字
boost::all(str, boost::is_any_of("*+-")); //判斷每個字符是否都是*或+或-
boost::trim(str); boost::trim_if(str, boost::is_lower() || boost::is_digit());//清除兩端小寫的字符或數字
boost::trim_left(str); str = "readme.txt"; boost::iterator_range<string::iterator> rge; //boost::iterator_range相當於容器(string)的子區間類型,它有begin()、end()、size()、empty()等成員函數。
rge = boost::find_first(str, "me"); //查找首次出現的位置
if (rge/*!rge.empty()*/) //rge可以隱式轉換為bool,所以有兩種方法判斷查找的結果
{ int iFoundPos = rge.begin() - str.begin(); //iFoundPos為4
string strFind(rge.begin(), rge.end()); //strFind為"me"
string strFull(rge.begin(), str.end()); //strFull為me.txt
int a = 0; } boost::find_last(str, "txt"); //查找最后一次出現的位置
boost::find_nth(str, "dm", 1); //查找"dm第二次出現的位置"
str = "abc, TestD, test"; vector<string> vs; boost::ifind_all(vs, str, "test"); //查找所有出現的位置
for (auto obj : vs) { string s = obj; cout << s << ","; //輸出為Test, test
} vector<boost::iterator_range<string::iterator>> vr; boost::ifind_all(vr, str, "test"); for (auto obj : vr) { string strSub(obj.begin(), obj.end()); cout << strSub << ","; //輸出為Test, test
string strTemp(obj.begin(), str.end()); cout << strTemp << ";"; //輸出為TestD, test; test
int iFoundPos = obj.begin() - str.begin(); cout << iFoundPos << ","; //輸出為5, 12
} replace / erase_all(); //替換/刪除所有出現的字符串
replace / erase_first(); //替換/刪除第一次出現的字符串
replace / erase_last(); //替換/刪除所有出現的字符串
replace / erase_nth(); //替換/刪除第n + 1次出現的字符串
replace / erase_head(); //替換/刪除開頭的n個字符串
replace / erase_tail(); //替換/刪除結尾的n個字符串 //split()以指定單個字符分割字符串到一個容器中,其參數列表的最后是一個帶默認參數,取值可為token_compress_on、token_compress_off //token_compress_on表示連續兩個分割字符出現時視為一個,token_compress_off為正常操作(會分割出一個空字符串來)。
str = "c++ java c#"; list<string> l; boost::split(l, str, boost::is_space()); //以空格分割
auto it = l.begin(); for (; it != l.end(); ++it) { string str = *it; cout << str << ","; //輸出為c++, java, c#
}
std::vector<std::string> vc;
boost::split(vc, str, boost::is_any_of(" ")); //以空格分割
for (auto& item : vc)
{
cout << item << ","; //輸出為c++, java, c#,
}
struct SIs_space { bool operator()(const char& ch)const { return ch == ' '; } }; list<boost::iterator_range<string::iterator>> lr; boost::split(lr, str, SIs_space()); auto iter = lr.begin(); for (; iter != lr.end(); ++iter) { string strSub(iter->begin(), iter->end()); cout << strSub << ","; //輸出為c++, java, c#
string strTemp(iter->begin(), str.end()); cout << strTemp << ";"; //輸出為c++ java c#; java c#; c#
int iFoundPos = iter->begin() - str.begin(); cout << iFoundPos << ","; //輸出為0, 4, 9
} //使用分割迭代器來分割字符串,可以以多個字符來分割
str = "Samus || samus || mario |||| Link"; typedef boost::split_iterator<string::iterator> string_split_iterator; string_split_iterator p, endp; for (p = boost::make_split_iterator(str, boost::first_finder("||", boost::is_equal())); p != endp; ++p) { string strSub = string(p->begin(), p->end()); //cout << strSub << ","; //輸出為Samus , samus , mario ,, Link
string strFull = string(p->begin(), str.end()); cout << strFull << ","; //輸出為 Samus || samus || mario |||| Link, samus || mario |||| Link, mario |||| Link, || Link, Link
int iPos = p->begin() - str.begin(); cout << iPos << ","; //輸出為0, 8, 17, 26, 28
} return 0; }
4、tokenizer
使用tokenizer庫可以很容易的執行分詞操作,但它只支持使用單個字符進行分詞,而且它對wstring(unicode)缺乏完善的考慮。通常建議使用string_algo或正則表達式來替換它的工作。
5、xpressive
xpressive是一個功能強大的正則表達式庫,它比原正則表達式庫boost.regex速度更快,而且不用編譯。xpressive不僅是一個類似boost.regex的正則表達式解析器,還是一個類似於boost.spirit的語法分析器,並且將這兩種不相交的文本處理方式融合在了一起。
c++11中已經有了正則表達式類regex。