std::string formatting like sprintf

前端 未结 30 2552
野趣味
野趣味 2020-11-22 04:42

I have to format std::string with sprintf and send it into file stream. How can I do this?

相关标签:
30条回答
  • 2020-11-22 05:27

    This is the code I use to do this in my program... It's nothing fancy, but it does the trick... Note, you will have to adjust your size as applicable. MAX_BUFFER for me is 1024.

    std::string Format ( const char *fmt, ... )
    {
        char textString[MAX_BUFFER*5] = {'\0'};
    
        // -- Empty the buffer properly to ensure no leaks.
        memset(textString, '\0', sizeof(textString));
    
        va_list args;
        va_start ( args, fmt );
        vsnprintf ( textString, MAX_BUFFER*5, fmt, args );
        va_end ( args );
        std::string retStr = textString;
        return retStr;
    }
    
    0 讨论(0)
  • 2020-11-22 05:27

    I usually use this:

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

    Disadvantage: not all systems support vasprint

    0 讨论(0)
  • 2020-11-22 05:29

    In order to format std::string in a 'sprintf' manner, call snprintf (arguments nullptr and 0) to get length of buffer needed. Write your function using C++11 variadic template like this:

    #include <cstdio>
    #include <string>
    #include <cassert>
    
    template< typename... Args >
    std::string string_sprintf( const char* format, Args... args ) {
      int length = std::snprintf( nullptr, 0, format, args... );
      assert( length >= 0 );
    
      char* buf = new char[length + 1];
      std::snprintf( buf, length + 1, format, args... );
    
      std::string str( buf );
      delete[] buf;
      return str;
    }
    

    Compile with C++11 support, for example in GCC: g++ -std=c++11

    Usage:

      std::cout << string_sprintf("%g, %g\n", 1.23, 0.001);
    
    0 讨论(0)
  • 2020-11-22 05:29

    If you are on a system that has asprintf(3), you can easily wrap it:

    #include <iostream>
    #include <cstdarg>
    #include <cstdio>
    
    std::string format(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
    
    std::string format(const char *fmt, ...)
    {
        std::string result;
    
        va_list ap;
        va_start(ap, fmt);
    
        char *tmp = 0;
        int res = vasprintf(&tmp, fmt, ap);
        va_end(ap);
    
        if (res != -1) {
            result = tmp;
            free(tmp);
        } else {
            // The vasprintf call failed, either do nothing and
            // fall through (will return empty string) or
            // throw an exception, if your code uses those
        }
    
        return result;
    }
    
    int main(int argc, char *argv[]) {
        std::string username = "you";
        std::cout << format("Hello %s! %d", username.c_str(), 123) << std::endl;
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 05:29

    Below slightly modified version of @iFreilicht answer, updated to C++14 (usage of make_unique function instead of raw declaration) and added support for std::string arguments (based on Kenny Kerr article)

    #include <iostream>
    #include <memory>
    #include <string>
    #include <cstdio>
    
    template <typename T>
    T process_arg(T value) noexcept
    {
        return value;
    }
    
    template <typename T>
    T const * process_arg(std::basic_string<T> const & value) noexcept
    {
        return value.c_str();
    }
    
    template<typename ... Args>
    std::string string_format(const std::string& format, Args const & ... args)
    {
        const auto fmt = format.c_str();
        const size_t size = std::snprintf(nullptr, 0, fmt, process_arg(args) ...) + 1;
        auto buf = std::make_unique<char[]>(size);
        std::snprintf(buf.get(), size, fmt, process_arg(args) ...);
        auto res = std::string(buf.get(), buf.get() + size - 1);
        return res;
    }
    
    int main()
    {
        int i = 3;
        float f = 5.f;
        char* s0 = "hello";
        std::string s1 = "world";
        std::cout << string_format("i=%d, f=%f, s=%s %s", i, f, s0, s1) << "\n";
    }
    

    Output:

    i = 3, f = 5.000000, s = hello world
    

    Feel free to merge this answer with the original one if desired.

    0 讨论(0)
  • 2020-11-22 05:29

    You can format C++ output in cout using iomanip header file. Make sure that you include iomanip header file before you use any of the helper functions like setprecision, setfill etc.

    Here is a code snippet I have used in the past to print the average waiting time in the vector, which I have "accumulated".

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

    Here is a brief description of how we can format C++ streams. http://www.cprogramming.com/tutorial/iomanip.html

    0 讨论(0)
提交回复
热议问题