我必须用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
其他回答
Boost::format()提供了你想要的功能:
Boost格式库简介如下:
format对象由format-string构造,然后通过反复调用运算符%来给出参数。 然后,每个参数都被转换为字符串,这些字符串又根据format-string组合成一个字符串。
#include <boost/format.hpp>
cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50;
// prints "writing toto, x=40.230 : 50-th try"
可以使用iomanip头文件格式化cout中的c++输出。 在使用类似的任何helper函数之前,请确保包含iomanip头文件 Setprecision, setfill等等。
下面是我过去用来在向量中打印平均等待时间的代码片段,这是我“累积”的。
#include<iomanip>
#include<iostream>
#include<vector>
#include<numeric>
...
cout<< "Average waiting times for tasks is " << setprecision(4) << accumulate(all(waitingTimes), 0)/double(waitingTimes.size()) ;
cout << " and " << Q.size() << " tasks remaining" << endl;
下面是如何格式化c++流的简要描述。 http://www.cprogramming.com/tutorial/iomanip.html
template<typename... Args>
std::string string_format(const char* fmt, Args... args)
{
size_t size = snprintf(nullptr, 0, fmt, args...);
std::string buf;
buf.reserve(size + 1);
buf.resize(size);
snprintf(&buf[0], size + 1, fmt, args...);
return buf;
}
使用C99 snprintf和c++ 11
我通常用这个:
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
对于Visual C:
std::wstring stringFormat(const wchar_t* fmt, ...)
{
if (!fmt) {
return L"";
}
std::vector<wchar_t> buff;
size_t size = wcslen(fmt) * 2;
buff.resize(size);
va_list ap;
va_start(ap, fmt);
while (true) {
int ret = _vsnwprintf_s(buff.data(), size, _TRUNCATE, fmt, ap);
if (ret != -1)
break;
else {
size *= 2;
buff.resize(size);
}
}
va_end(ap);
return std::wstring(buff.data());
}
推荐文章
- decltype(auto)的一些用途是什么?
- Shared_ptr转换为数组:应该使用它吗?
- Printf与std::字符串?
- 禁用复制构造函数
- 不区分大小写的“in”
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 只接受特定类型的c++模板
- 如何在PHP中截断字符串最接近于一定数量的字符?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- Ruby数组到字符串的转换
- c++ 11中的递归lambda函数
- 在c++中指针使用NULL或0(零)吗?
- 为什么在Java和。net中不能修改字符串?
- 在c++中,如何将int值附加到字符串中?
- 如何创建一个日期对象从字符串在javascript