我需要估计在sprintf
操作中获得的字符串的长度。我怎样才能做到这一点。换句话说,如何避免在下面的代码段中隐藏值50
。
double sum;
char* resultString;
..
resultString = new char[50]; //how can I avoid hardcoding 50 here?
sprintf(resultString,"[%e]",sum);
答案 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及其克隆不是类型安全的。但无论结果字符串结果有多长,它都不会导致有效调用的缓冲区溢出