我必须用sprintf格式化std::string,并将其发送到文件流。我该怎么做呢?
当前回答
我现在将为Visual Studio编写版本,希望有一天有人会让它变得可移植。(怀疑需要用vsnwprintf替换_vsnwprintf之类的东西。)
您需要使用项目配置中的define _CRT_SECURE_NO_WARNINGS来禁用已弃用的警告。
我使用_vsnwprintf与第一个参数作为nullptr能够估计缓冲区大小,保留wstring缓冲区,然后格式化字符串直接到缓冲区。
不确定为什么需要禁用已弃用警告,因为相同方法调用(_vsnwprintf_s)的安全版本不能使用nullptr作为输入。怀疑需要报告给微软c++团队。
这个版本应该同时使用- string类或wstring类。
如果你发现任何错误或不一致,请再问一次,我会尽力修复它。
stringHelpers.h:
#pragma once
#include <string>
//
// Formats string/wstring according to format, if formatting fails (e.g. invalid %s pointer - returns empty string)
//
template <typename T>
std::basic_string<T> sFormat(const T* format, ...)
{
va_list args;
va_start(args, format);
int size;
if constexpr (std::is_same_v<T, char>)
size = vsnprintf(nullptr, 0, format, args);
else
size = _vsnwprintf(nullptr, 0, format, args);
size++; // Zero termination
std::basic_string<T> s;
s.resize(size);
if constexpr (std::is_same_v<T, char>)
vsnprintf(&s[0], size, format, args);
else
_vsnwprintf(&s[0], size, format, args);
va_end(args);
return s;
}
以上是代码示例,可以复制。我将维护工作版本在我自己的仓库在github:
https://github.com/tapika/cppscriptcore/blob/master/SolutionProjectModel/helpers.h#L12
其他回答
你不能直接这样做,因为你没有对底层缓冲区的写访问权(直到c++ 11;见Dietrich Epp的评论)。你必须先在c-string中执行,然后将其复制到std::string中:
char buff[100];
snprintf(buff, sizeof(buff), "%s", "Hello");
std::string buffAsStdStr = buff;
但我不确定为什么不直接使用字符串流?我想你有特定的理由不这么做:
std::ostringstream stringStream;
stringStream << "Hello";
std::string copyOfStr = stringStream.str();
根据Erik Aronesty提供的答案:
std::string string_format(const std::string &fmt, ...) {
std::vector<char> str(100,'\0');
va_list ap;
while (1) {
va_start(ap, fmt);
auto n = vsnprintf(str.data(), str.size(), fmt.c_str(), ap);
va_end(ap);
if ((n > -1) && (size_t(n) < str.size())) {
return str.data();
}
if (n > -1)
str.resize( n + 1 );
else
str.resize( str.size() * 2);
}
return str.data();
}
这避免了需要从原始答案中的.c_str()结果中取消const。
这是可以尝试的。简单。虽然没有使用字符串类的细微差别。
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string>
#include <exception>
using namespace std;
//---------------------------------------------------------------------
class StringFormatter
{
public:
static string format(const char *format, ...);
};
string StringFormatter::format(const char *format, ...)
{
va_list argptr;
va_start(argptr, format);
char *ptr;
size_t size;
FILE *fp_mem = open_memstream(&ptr, &size);
assert(fp_mem);
vfprintf (fp_mem, format, argptr);
fclose (fp_mem);
va_end(argptr);
string ret = ptr;
free(ptr);
return ret;
}
//---------------------------------------------------------------------
int main(void)
{
string temp = StringFormatter::format("my age is %d", 100);
printf("%s\n", temp.c_str());
return 0;
}
我知道这个问题已经被回答过很多次了,但下面这个更简洁:
std::string format(const std::string fmt_str, ...)
{
va_list ap;
char *fp = NULL;
va_start(ap, fmt_str);
vasprintf(&fp, fmt_str.c_str(), ap);
va_end(ap);
std::unique_ptr<char[]> formatted(fp);
return std::string(formatted.get());
}
例子:
#include <iostream>
#include <random>
int main()
{
std::random_device r;
std::cout << format("Hello %d!\n", r());
}
参见http://rextester.com/NJB14150
我通常用这个:
std::string myformat(const char *const fmt, ...)
{
char *buffer = NULL;
va_list ap;
va_start(ap, fmt);
(void)vasprintf(&buffer, fmt, ap);
va_end(ap);
std::string result = buffer;
free(buffer);
return result;
}
缺点:并非所有系统都支持vasprint
推荐文章
- Python __str__与__unicode__
- 为什么STL如此严重地基于模板而不是继承?
- 查找当前可执行文件的路径,不包含/proc/self/exe
- bash:错误的替换
- 未定义对静态constexpr char的引用[]
- 在c#中检查字符串是否只包含数字的最快方法
- 在c++中,restrict关键字是什么意思?
- c++中类似于java的instanceof
- 我怎么能强迫一个长字符串没有任何空白被包装?
- include_directories和target_include_directories在CMake中的区别是什么?
- 转换JSON字符串到JSON对象c#
- std::make_pair与std::pair的构造函数的目的是什么?
- 将查询字符串解析为数组
- 如何追加一个字符到std::字符串?
- 删除字符串中的字符列表