我必须用sprintf格式化std::string,并将其发送到文件流。我该怎么做呢?


当前回答

你可以试试这个:

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 );

其他回答

Windows和Visual Studio有一个非常有吸引力的解决方案:CString。

CString str;
str.Format("Hello %s\n", "World");
str = "ABC";
str += "DEF";

你不能直接这样做,因为你没有对底层缓冲区的写访问权(直到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();

可以使用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

这是可以尝试的。简单。虽然没有使用字符串类的细微差别。

#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;
}

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]"  
}