我必须用sprintf格式化std::string,并将其发送到文件流。我该怎么做呢?
当前回答
我喜欢的一个解决方案是,在使缓冲区足够大之后,用sprintf直接在std::string缓冲区中执行此操作:
#include <string>
#include <iostream>
using namespace std;
string l_output;
l_output.resize(100);
for (int i = 0; i < 1000; ++i)
{
memset (&l_output[0], 0, 100);
sprintf (&l_output[0], "\r%i\0", i);
cout << l_output;
cout.flush();
}
因此,创建std::string,调整它的大小,直接访问它的缓冲区…
其他回答
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"
这是谷歌的做法: facebook也以类似的方式:StringPrintf (Apache许可证) 两者都提供了一个方便的StringAppendF。
c++ 17解决方案(这将工作于std::string和std::wstring):
分配一个缓冲区,格式化它,然后复制到另一个字符串是不高效的。可以创建格式化字符串大小的std::string,并直接格式化到字符串缓冲区中:
#include <string>
#include <stdexcept>
#include <cwchar>
#include <cstdio>
#include <type_traits>
template<typename T, typename ... Args>
std::basic_string<T> string_format(T const* const format, Args ... args)
{
int size_signed{ 0 };
// 1) Determine size with error handling:
if constexpr (std::is_same_v<T, char>) { // C++17
size_signed = std::snprintf(nullptr, 0, format, args ...);
}
else {
size_signed = std::swprintf(nullptr, 0, format, args ...);
}
if (size_signed <= 0) {
throw std::runtime_error("error during formatting.");
}
const auto size = static_cast<size_t>(size_signed);
// 2) Prepare formatted string:
std::basic_string<T> formatted(size, T{});
if constexpr (std::is_same_v<T, char>) { // C++17
std::snprintf(formatted.data(), size + 1, format, args ...); // +1 for the '\0' (it will not be part of formatted).
}
else {
std::swprintf(formatted.data(), size + 1, format, args ...); // +1 for the '\0' (it will not be part of formatted).
}
return formatted; // Named Return Value Optimization (NRVO), avoids an unnecessary copy.
}
此外:通常,format参数是char[] / wchar_t[] &创建std::string对象效率不高。传递char*或wchar_t* &如果你已经有一个std::string对象,你仍然可以使用它作为your_string.c_str()。例子:
int main()
{
int i{ 0 };
// The format parameter is a char[] / wchar_t[]:
const std::string title1 = string_format("story[%d].", ++i); // => "story[1]"
const std::wstring title2 = string_format(L"story[%d].", ++i); // => L"story[2]"
// If you already have a std::string object:
const std::string format1{ "story[%d]." };
const std::string title3 = string_format(format1.c_str(), ++i); // => "story[3]"
const std::wstring format2{ L"story[%d]." };
const std::wstring title4 = string_format(format2.c_str(), ++i); // => L"story[4]"
}
你不能直接这样做,因为你没有对底层缓冲区的写访问权(直到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();
你可以试试这个:
string str;
str.resize( _MAX_PATH );
sprintf( &str[0], "%s %s", "hello", "world" );
// optionals
// sprintf_s( &str[0], str.length(), "%s %s", "hello", "world" ); // Microsoft
// #include <stdio.h>
// snprintf( &str[0], str.length(), "%s %s", "hello", "world" ); // c++11
str.resize( strlen( str.data() ) + 1 );
推荐文章
- 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