C++ sprintf结果长度的估计

C++ sprintf结果长度的估计,c++,C++,我需要估计在sprintf操作中获得的字符串的长度。我怎样才能做到这一点。换句话说,我如何避免在下面的代码片段中对值50进行编码 double sum; char* resultString; .. resultString = new char[50]; //how can I avoid hardcoding 50 here? sprintf(resultString,"[%e]",sum); 使用snprintf(字符*缓冲区,整数大小,常量字符*格式,…)sprintf不安全 但是我

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

double sum;
char* resultString;
..

resultString = new char[50]; //how can I avoid hardcoding 50 here?
sprintf(resultString,"[%e]",sum);
使用
snprintf(字符*缓冲区,整数大小,常量字符*格式,…)<代码>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();
#包括
#包括
双和;
std::stringstream buf(std::stringstream::in | std::stringstream::out);
std::字符串结果字符串;
..

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

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

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

buffer
snprintf
返回如果缓冲区足够大,将写入的字符数。您可以调用它两次,一次是获取长度,另一次是实际格式化字符串。

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

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

printf(“%.2s”,“12345”)

本例仅打印前两个字符。通过这种方式,您可以估计/限制所需的最大尺寸


除此之外,还有许多其他人建议的好答案

通常,使用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;
}
static void append_格式(std::string&s,const char*格式,va_list vl)
{
自动电流长度=s.长度();
自动sz=vsnprintf(NULL,0,格式,vl);
s、 调整大小(cur_长度+sz);
自动sz2=vsnprintf(&s[cur_length],sz+1,格式,vl);
断言(sz2==sz);
}
静态void示例_用法()
{
std::字符串s;
附加_格式,“%s%dD world”,“hello”,3);//s==“hello 3D world”
附加_格式(s,,,PI=~%f,,,3.14);//s==“你好,3D世界,PI=~3.14”

STD::为什么你使用C字符串而不是C++ <代码>字符串 [某些初始化变量]中发送变量
。我收到一个错误
错误:嵌套名称说明符中使用了不完整的类型“std::stringstream”
我正在执行以下操作,但为cresult获取了一个空值。sprintf版本正在工作。
stringstream buf(stringstream::in);string resultString;buf已修复。显然,您需要
std::stringstream::out
用于
::str();
。您不需要
in | out
。它们是默认值。我更喜欢stringstream随时打印f,但有时在与旧代码交互时无法避免。有关该场景,请参阅下面的答案。