在平常的程式設計過程中,總免不了格式化字串。而作為c++程式設計師,是快樂的也是痛苦不的。快樂是因為我們有多種方式來達到目的,痛苦也是因為有多種方式而難以決策,總是在思索效率與優雅!c++逐步「淪落」的原因也正是因為她的高貴的氣質(難以駕馭),時尚的髮型(模板),狂野的性格(記憶體)。哎,迷戀它,她就是我的傳說!
先給出一張**,然後再來一一琢磨!
sprintf
snprintf
stringstream
strsteram
tr2::lexical_cast
boost::format
備註易用性yy
nnyn
無需額外記憶體yy
nynn
緩衝區安全ny
yyyy
型別安全nn
yyyy
是否可用於模板nn
yyyy
效率耗時取樣,以sprintf為基準
一、sprintf
先來看個成功案例
輸出: 10
sprintf的易用性是無需多言的,任何學過c語言的童鞋都能搞定,而且不需要額外的記憶體空間(除開我們制定的buffer區)。但是,也正是因為他來自c,所以就有一些不良嗜好:
1) 緩衝區溢位:
void formatstring(int i, char *pbuf)char buf[3] = ; // 這裡所指定的緩衝區不能滿足%4d的空間
formatstring(10, buf);
cout << buf << endl;
完了,記憶體遭到了破壞,在vs2008下測試,執行時會提示
「run-time check failure #2 - stack around the variable 'buf' was corrupted.」
2)型別安全
void formatstring(int i, char *pbuf)char buf[5] = ;
formatstring(10, buf);
cout << buf << endl; // 現在什麼也不輸出
由於printf家族都是使用的c可變引數列表,編譯期間不檢查引數列表(好像有個lint的工具可以檢查,沒用過。)
3)使用模板來解決型別安全
templatevoid formatstring(t value, char *pbuf); // 主模板進行宣告,不定義
template
<>
void formatstring(int value, char *pbuf) // 特化
template
<>
void formatstring(char value, char *pbuf) // 特化
template
<>
void formatstring(char *value, char *pbuf) // 特化
夠了,不想再寫了!來看其他的替代方案吧!
二、snprintf(m$用的是_snprintf)
void formatstring(int i, char *pbuf, int nbuflen)char buf[5] = ;
formatstring(10, buf, sizeof(buf) / sizeof(buf[0]));
cout << buf << endl;
正確輸出: 10
在c99中snprintf成為了標準的一部分,這樣,就能避免程式緩衝區溢位,除非故意把指定緩衝區長度搞錯。但是還是不能解決型別安全的為題
三、std::stringstream
看列子
特點很鮮明:易用性不如sprintf,使用了額外的緩衝區stringstream。但是現在沒有了緩衝區溢位和型別安全的擔心,而且我們可以做個更通用的版本
templatevoid formatstring(t value, string &str)
四、std::strstream
哎,這個要被拋棄了,成為標準的犧牲品!還是給他點信心吧
void formatstring(t value, char *pbuf, int nbuflen)
不錯的表現啊(相對stringstream講,無需額外的記憶體),但是要被標準拋棄~
五、str2::lexical_cast / boost::lexical_cast
很簡單,實現也是基於stringstream的,而其快進入c++標準了,不需多言。
六、boost::format
用法與srpintf類似,不過看上去n不像~不喜歡!
效率比試:
vs2008 release模式
<< dwlast << endl;
dwlast = 0;
}cout << "snprintf:"
<< dwlast << endl;
dwlast = 0;
string str;
}cout << "stringstream:"
<< dwlast << endl;
dwlast = 0;
}cout << "strstream:"
<< dwlast << endl;
dwlast = 0;
}cout << "boost::lexical_cast:"
<< dwlast << endl;
很出乎我得意料~boost這麼快啊~佩服佩服!不愧是大師的佳作!
總結:
預設情況下,效率不是關鍵
如果效率是瓶頸
如果只想做字元轉換
boost::lexical_cast
boost::lexical_cast/snprintf
簡單的格式化(unicode/ascii)
stringstream/strstream
snprintf
較為負載的格式化
stringstream/snprintf
snprintf
字串格式化
sprintf snprintf snprintf std stringstream std strstream boost lexical cast boost format cstring format 1 sprintf 使用 sprintf 不安全,輕則破壞資料的準確性,重則程式崩潰。請看下...
格式化字串
通常在使用字串的時候,會對字串進行格式化,然後輸出或呼叫 一般我們使用替換標記對字串進行格式化 string str1 string.format add is 1,2,3 而且在c 中的替換標記可以以任意順序和次數出現在格式化字串中,但替換值是按順序排的,而且替換標記不能超出索引範圍 string...
字串格式化
例如 string s hello map.put target world string res format s,map 有什麼用呢?比如在some.properties中配置模板字串,但是如果用 這種方式,在配置了spring讀取properties注入變數的時候,這個變數就找不到會報錯。這個...