2014-02-18 99 views
2

我正在考慮編寫一個函數來估計至少一個來自sprintf(),snprintf()函數的格式化字符串的全長。估計格式化的snprintf()字符串的大小?

我的方法是解析格式字符串以查找各種%s,%d,%f,%p args,創建strlen()s,itoa()s和strlen(format_string)的運行總和得到足夠大的內容來爲snprintf()分配適當的緩衝區。

我知道下面的作品,但它需要10X長,因爲所有的printf()函數是非常靈活的,而是因爲如果它很慢。

char c; 
    int required_buffer_size = snprintf(&c, 1, "format string", args...); 

這已經完成了嗎? - 通過建議的方法或其他合理有效的方法 - IE:比sprintf()變種快5-50倍?

+6

採取「10倍長」作爲究竟是什麼?你所描述的函數必須再次實現snprintf纔是正確的,除非你願意將它限制爲格式說明符的一個子集......這是你想出更快選擇的唯一方法。 – vanza

+1

可能的複製http://stackoverflow.com/questions/16647278/minimal-fast-implementation-of-sprintf-for-embedded –

+0

@vanza,你能證明你的要求?我可以做很少的工作,比如對於int32_t使用12的長度,對於int64_t使用24的長度,對於%f使用80的長度等。對於僅處理字符串,我已經具有5-10X。我會RX基準snprintf()。所有的printf()變體都非常慢。有時候他們是唯一正確的解決方案,但這不是其中之一。 – user2548100

回答

2

如果snprintf的第一個參數是NULL,則返回值是應寫入的字符數。

+0

太慢了。如..所示。 :( – user2548100

5

分配足夠大的緩衝第一,並檢查它是否足夠長。如果它不是重新分配和第二次通話。

int len = 200; /* Any number well chosen for the application to cover most cases */ 
int need; 
char *buff = NULL; 
do { 
    need = len+1; 
    buff = realloc(buff, need); /* I don't care for return value NULL */ 
    len = snprintf(buff, need, "...", ....); 
    /* Error check for ret < 0 */ 
} while(len > need); 
/* buff = realloc(buff, len+1); shrink memory block */ 

通過選擇您的初始值正確,你將不得不在大多數情況下,只有一個呼叫snprintf()和過度分配的有點不應該是至關重要的。如果你處於一個非常緊張的環境中,這種分配至關重要,那麼在昂貴的分配和格式化方面你已經遇到了其他問題。 在任何情況下,您仍然可以調用realloc()以將分配的緩衝區縮小到確切的大小。

+0

我現在使用的方法非常多,除了我對realloc()具有明確的步長以外,體面,但我認爲在我的上下文中快速和骯髒的估計是更好的一個好的調整是保持max_size,因爲在我的上下文中,這是循環運行的,唯一需要注意的就是最大大小應該有一些限制,以防止由於缺少終止符或惡意的字符串注入而導致的大量分配 – user2548100

+0

在這種情況下,在基於解析格式字符串並調用'strlen()'的估計中存在相同的問題,無論如何,當構建時間關鍵循環中的字符串時,我更願意避免完全使用通用格式函數,而只能使用O 1)字符串連接,即沒有'strcat()'和'strlen()'。 –

+0

我不確定你的意思是「只用O(1)字符串連接」。你可以擴展嗎?你正在談論Kamailio風格_str {char * p; int len;}「字符串」?我喜歡這種方式,但是試圖避免這種搖搖欲墜的舊系統在我的膝蓋上傾倒的情況。 – user2548100