字串格式化大比拼

2021-05-13 08:42:44 字數 3231 閱讀 4783

在平常的程式設計過程中,總免不了格式化字串。而作為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)使用模板來解決型別安全

template

void 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。但是現在沒有了緩衝區溢位和型別安全的擔心,而且我們可以做個更通用的版本

template

void 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注入變數的時候,這個變數就找不到會報錯。這個...