2011-03-25 130 views
2

我需要估計在sprintf操作中獲得的字符串的長度。我怎樣才能做到這一點。換句話說,我如何避免在下面的代碼段中對50的值進行編碼。估計sprintf的結果長度

double sum; 
char* resultString; 
.. 

resultString = new char[50]; //how can I avoid hardcoding 50 here? 
sprintf(resultString,"[%e]",sum); 
+6

爲什麼使用C字符串而不是C++'字符串? – 2011-03-25 09:24:57

+0

僅供參考,您也可以在索引'[someInitializedIntVariable]'中發送變量。 – Mahesh 2011-03-25 09:25:32

回答

3

使用snprintf(char *buffer, int buf_size, const char *format, ...);sprintf是不安全的。

但是我看到你正在使用C++,所以我會用一個字符串流是這樣的:

#include <iostream> 
#include <sstream> 

double sum; 
std::stringstream buf(std::stringstream::in | std::stringstream::out); 
std::string resultString; 
.. 

buf << "[" << std::scientific << sum << "]"; 
resultString = buf.str(); 
+0

不能使用C++ 0x – Emie 2011-03-25 09:28:42

+1

這個C++ 0x如何? – orlp 2011-03-25 09:31:56

+0

我得到一個錯誤'錯誤:不完整類型'std :: stringstream'在嵌套名稱說明符中使用' – Emie 2011-03-25 09:43:28

1

正確的方法是不使用的sprintf。有很多可擴展的,安全的方式來格式化您的輸出在C++(包括但不限於標準iostreams設施)。如果你用C編碼,使用snprintf。

3

最好的辦法避免這一切都將是使用std::stringstream代替:

std::stringstream buffer; 
buffer << std::scientific << sum; 
std::string resultString = buffer.str(); 
8

snprintf返回如果緩衝區足夠大已被寫入字符數。你可以調用它兩次,一次獲得長度並再次實際格式化字符串。

2

一個很好的快速方法是使用固定大小的緩衝區snprintf,它返回緩衝區足夠大時它將打印的字符數。如果返回值指示緩衝區不夠大,則使用malloc()或使用現有大小的新值。一個更慢更簡單的方法是尋找總是從堆中分配的asprintf()。您可以在幾行內實現您自己的asprintf()頂端snprintf()

0

使用printf like函數時,您可以選擇爲每個數字提供長度。

printf(「%。2s」,「12345」);

本例僅打印前兩個字符。這樣你可以估計/限制最大需求大小。

否則有被別人

0

通常提出了許多很好的答案,使用std :: stringstream的是正確的答案。有時,在連接C代碼時,使用printf(fmt,...)是必要的,所以std :: stringstream是不可能的。在這些情況下 仍然可以格式化一個可變長度的字符串,像這樣:

static void append_format(std::string& s, const char* format, va_list vl) 
{ 
    auto cur_length = s.length(); 
    auto sz = vsnprintf(NULL, 0, format, vl); 
    s.resize(cur_length + sz); 
    auto sz2 = vsnprintf(&s[cur_length], sz + 1, format, vl); 
    assert(sz2 == sz); 
} 

static void example_usage() 
{ 
    std::string s; 
    append_format(s, "%s %dD world", "hello", 3); // s == "hello 3D world" 
    append_format(s, ", PI= ~%f", 3.14); // s == "hello 3D world, PI= ~3.14" 
    std::cout << s; 
} 

注意到,因爲printf和它的克隆不是類型安全的這種方法不是類型安全的。但不會導致有效調用的緩衝區溢出,無論結果字符串結果多長時間爲止