开发者

Estimating length of result of sprintf

I need to estimate the length of the string obtained on sprintf operation. How can I do this. In other 开发者_高级运维words, how can I avoid harcoding the value 50 in the below snippet.

double sum;
char* resultString;
..

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


snprintf returns the number of chars that would have been written if the buffer was large enough. You can call it twice, once to get the length and again to actually format your string.


Use snprintf(char *buffer, int buf_size, const char *format, ...);. sprintf is unsafe.

However I read you are using C++, so I would use a stringstream like this:

#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();


The best way to avoid all this would be to use a std::stringstream instead:

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


A nice fast way is to use a fixed-sized buffer with snprintf, which returns the number of characters that it would have printed if the buffer were large enough. If that return value indicates the buffer wasn't big enough, then use malloc() or new with the now-known size. A slower but simpler alternative is to look for asprintf(), which always allocated from the heap. You could implement your own asprintf() atop snprintf() in a few lines.


The proper way is not using sprintf. There are many extensible, safe ways to format your output in C++ (including, but not limited to, the standard iostreams facility). If you code in C, use snprintf.


while using printf like function you have options to provide length for each number.

printf("%.2s", "12345");

this example prints only first two characters. This way you can estimate/limit maximum required size.

otherwise there are many good answers suggested by others


usually, using std::stringstream is the right answer. yet sometimes, when interfacing C code, using printf(fmt, ...) is necessary, so std::stringstream isn't possible. in these cases one can still format a variable length string like so:

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;
}

note, that this method is not type safe because printf and its clones are not type safe. but it will not cause buffer overruns for valid invocations, no matter how long the result string turns out to be

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜