估计sprintf的结果长度

时间:2011-03-25 09:22:57

标签: c++

我需要估计在sprintf操作中获得的字符串的长度。我怎样才能做到这一点。换句话说,如何避免在下面的代码段中隐藏值50

double sum;
char* resultString;
..

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

7 个答案:

答案 0 :(得分:8)

如果缓冲区足够大,

snprintf将返回已写入的字符数。你可以调用它两次,一次得到长度,然后再次实际格式化你的字符串。

答案 1 :(得分: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();

答案 2 :(得分:3)

避免这一切的最佳方法是使用std::stringstream代替:

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

答案 3 :(得分:2)

一个很好的快速方法是使用带有snprintf的固定大小的缓冲区,如果缓冲区足够大,它将返回它将打印的字符数。如果该返回值表明缓冲区不够大,则使用现在已知大小的malloc()或new。一个更慢但更简单的替代方法是查找始终从堆分配的asprintf()。您可以在几行中实现自己的asprintf() atop snprintf()

答案 4 :(得分:1)

正确的方法是不使用sprintf。有许多可扩展,安全的方法来格式化您的C ++输出(包括但不限于标准的iostreams工具)。如果您使用C编码,请使用snprintf。

答案 5 :(得分:0)

在使用类似printf的函数时,您可以选择为每个数字提供长度。

printf(“%。2s”,“12345”);

此示例仅打印前两个字符。这样您就可以估算/限制所需的最大尺寸。

否则其他人会提出许多好的答案

答案 6 :(得分: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及其克隆不是类型安全的。但无论结果字符串结果有多长,它都不会导致有效调用的缓冲区溢出