How to use C++ std::ostream with printf-like formatting?

前端 未结 8 2004

I am learning C++. cout is an instance of std::ostream class. How can I print a formatted string with it?

I can still use printf

相关标签:
8条回答
  • 2020-12-05 07:32

    I suggest using ostringstream instead of ostream see following example :

    #include <vector>
    #include <string>
    #include <iostream>
    #include "CppUnitTest.h"
    
    #define _CRT_NO_VA_START_VALIDATION
    
    std::string format(const std::string& format, ...)
    {
        va_list args;
        va_start(args, format);
        size_t len = std::vsnprintf(NULL, 0, format.c_str(), args);
        va_end(args);
        std::vector<char> vec(len + 1);
        va_start(args, format);
        std::vsnprintf(&vec[0], len + 1, format.c_str(), args);
        va_end(args);
        return &vec[0];
    }
    

    example usage:

    std::ostringstream ss;
    ss << format("%s => %d", "Version", Version) << std::endl;
    Logger::WriteMessage(ss.str().c_str()); // write to unit test output
    std::cout << ss.str() << std::endl; // write to standard output
    
    0 讨论(0)
  • 2020-12-05 07:32

    I wrote independently but came up with answer similar to user3283405

    My solution uses vasprintf() to acheive formatting, and uses operator overloading of << of std::ostream to free the memory in right place.

    Usage:

    std::cout << putf(const char *format, ...); //Same format as C printf(3)
    

    Code:

    #define _GNU_SOURCE
    #include <cstdarg>
    #include <iostream>
    #include <cstdio>
    
    struct putf_r{
            char *s;
    };
    
    putf_r putf(const char *fmt, ...){
            va_list ap;
            va_start(ap, fmt);
            putf_r a;
    #pragma GCC diagnostic push
    #pragma GCC diagnostic ignored "-Wformat-nonliteral"
            vasprintf(&a.s, fmt, ap);
    #pragma GCC diagnostic pop
            va_end(ap);
            return a;
    }
    
    std::ostream& operator<<(std::ostream& os, putf_r a){
            os<<a.s;
            free(a.s);
            return os;
    }
    
    int main(){
            std::cout << putf("%3d\n", 23) << putf("%a\n", 256.);
    }
    

    Note that compiler doesn't check format inside putf(), so compiler flag -Wformat-nonliteral will not warn for suspicious code in putf() and you need to care uncontrolled format string problem by yourself.
    Detailed info can be found on GitHub

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