在 C 中,有不止一种方法可以做到这一点,具体取决于您希望如何分配内存 [*]。对于从堆中分配它的直接选项:
len = snprintf(0, 0, "%d bottles, %d shelves, room %d\n", one, two, three);
char *result = malloc(len+1);
if (result == 0) { /* handle error */ }
snprintf(result, len+1, "%d bottles, %d shelves, room %d\n", one, two, three);
/* some time later */
free(result);
注意snprintf 的非标准实现,当超出缓冲区时不会返回长度。检查您的文档。
在 C++ 中,snprintf 不在标准中,即使它可用,上面的代码也需要转换 malloc[**] 的结果。 C++ 增加了使用字符串流的选项:
std::stringsteam r;
r << one << " bottles, " << two << " shelves, room " << three << "\n";
std::string result = r.str();
// if you absolutely need a char*, use result.c_str(), but don't forget that
// the pointer becomes invalid when the string, "result" ceases to exist.
这避免了缓冲区长度的混乱,使资源管理更容易,并避免printf 和朋友可能为格式说明符传递错误类型的参数的风险。它通常是首选。
然而在某些情况下它不太灵活:格式被硬连接到代码中,而不是包含在格式字符串中,因此更难使文本可配置。它也可能有点难以阅读,例如在任何此类代码行的第一个版本中省略空格字符并不少见。但是,如果您想在 C++ 中使用 snprintf 方法,并且在您的实现中可以使用 snprintf,那么您可以利用 C++ 更简单的内存管理,如下所示:
len = std::snprintf(0, 0, "%d bottles, %d shelves, room %d\n", one, two, three);
std::vector<char> r(len+1);
std::snprintf(&r[0], r.size(), "%d bottles, %d shelves, room %d\n", one, two, three);
char *result = &r[0];
// again, "result" is only valid as long as "r" is in scope
[*] 请注意,您不能在char* 中“存储”字符串,因为char* 只是一个指针。您可以在char* 中存储指向字符串的指针,但字符串本身是完全独立的。
[**] 因为 C 和 C++ 是不同的语言!