vsnprintf()
может вычислить необходимый размер буфера без фактического вывода в буфер, так что вам обычно вообще не нужен отдельный char[]
, вы можете просто рассчитать размер, выделить std::string
к этому размеру, а затем использовать собственный внутренний буфер std::string
для вывода, например:
std::string vstring (const char * format, ...)
{
std::string result;
va_list args, args_copy;
va_start(args, format);
va_copy(args_copy, args);
int len = vsnprintf(nullptr, 0, format, args);
if (len < 0) {
va_end(args_copy);
va_end(args);
throw std::runtime_error("vsnprintf error");
}
if (len > 0) {
result.resize(len);
// note: &result[0] is *guaranteed* only in C++11 and later
// to point to a buffer of contiguous memory with room for a
// null-terminator, but this "works" in earlier versions
// in *most* common implementations as well...
vsnprintf(&result[0], len+1, format, args_copy); // or result.data() in C++17 and later...
}
va_end(args_copy);
va_end(args);
return result;
}
Хотя до C ++ 11 использование отдельного буфера было бы более«правильный» (т. е. портативный) и более безопасный выбор, например:
std::string vstring (const char * format, ...)
{
std::string result;
va_list args, args_copy;
va_start(args, format);
va_copy(args_copy, args);
int len = vsnprintf(nullptr, 0, format, args);
if (len < 0) {
va_end(args_copy);
va_end(args);
throw std::runtime_error("vsnprintf error");
}
if (len > 0) {
std::vector<char> buffer(len+1);
vsnprintf(&buffer[0], buffer.size(), format, args_copy);
result = std::string(&buffer[0], len);
}
va_end(args_copy);
va_end(args);
return result;
}