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