I just want to format a string and an integer value with right justify.
There is no problem to do this without leading space before the integer value.
bytes.....................123981
total bytes..............1030131
But it should look like this:
bytes ................... 123981
total bytes ............ 1030131
Unfortunately the example below wont work, because setw (right justify) relates only to the next stream element.
int iBytes = 123981;
int iTotalBytes = 1030131;
cout << setfill('.');
cout << right;
cout << "bytes " << setw(20) << " " << iBytes << endl;
cout << "total bytes " << setw(14) << " " << iTotalBytes << endl;
I hardly ever use std::cout, so is there a simple way to do this without previously joining a space char to the value?
The simplest way would be to write your " " and value into a std::stringstream and write the resulting str() into your output stream like:
std::stringstream ss;
ss << " " << iBytes;
cout << "bytes " << setw(20) << ss.str() << endl;
And here comes the complete overkill. A templated class prefixed which can be printed and bundles the two constructor arguments prefix,val
into one string to be printed. number format, and precision is taken from the final output stream. Works with ints,floats, strings and const char *. And should work with every arg that has a valid output operator.
#include <fstream>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
template<class T>
class prefixed_base {
public:
prefixed_base(const std::string & prefix,const T val) : _p(prefix),_t(val) {
}
protected:
std::string _p;
T _t;
};
// Specialization for const char *
template<>
class prefixed_base<const char*> {
public:
prefixed_base(const std::string & prefix,const char * val) : _p(prefix),_t(val) {
}
protected:
std::string _p;
std::string _t;
};
template<class T>
class prefixed : public prefixed_base<T> {
private:
typedef prefixed_base<T> super;
public:
prefixed(const std::string & prefix,const T val) : super(prefix,val) {
}
// Output the prefixed value to an ostream
// Write into a stringstream and copy most of the
// formats from os.
std::ostream & operator()(std::ostream & os) const {
std::stringstream ss;
// We 'inherit' all formats from the
// target stream except with. This Way we
// keep informations like hex,dec,fixed,precision
ss.copyfmt(os);
ss << std::setw(0);
ss << super::_p;
ss.copyfmt(os);
ss << std::setw(0);
ss << super::_t;
return os << ss.str();
}
};
// Output operator for class prefixed
template<class T>
std::ostream & operator<<(std::ostream & os,const prefixed<T> & p) {
return p(os);
}
// This function can be used directly for output like os << with_prefix(" ",33.3)
template<class T>
prefixed<T> with_prefix(const std::string & p,const T v) {
return prefixed<T>(p,v);
}
int main() {
int iBytes = 123981;
int iTotalBytes = 1030131;
cout << setfill('.');
cout << right;
cout << "bytes " << setw(20) << with_prefix(" ",iBytes) << endl;
cout << "total bytes " << setw(14) << with_prefix(" ",iTotalBytes) << endl;
cout << "bla#1 " << setw(20) << std::fixed << std::setprecision(9) << with_prefix(" ",220.55) << endl;
cout << "blablabla#2 " << setw(14) << std::hex << with_prefix(" ",iTotalBytes) << endl;
}
@Oncaphillis thx for the piece of source code, I adapt it a bit for my needs. I just wrote a function to convert values. std::to_string is used by C++11 standard, so I decided to use _to_string/_to_wstring instead. The tricky part was to get "wcout" to work with UNICODEs on Windows console. I didn’t really manage it, so I had to do a workaround. Anyway to print e.g. Cyrillic characters you have to change the console font to Consolas or Lucida.
#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#if defined(UNICODE) || defined(_UNICODE)
#define _tcout std::wcout
#define _to_tstring _to_wstring
template <typename T>std::wstring _to_wstring(const T& value) {
std::wostringstream wos;
wos.copyfmt(std::wcout);
wos << value;
return wos.str();
}
#else
#define _tcout std::cout
#define _to_tstring _to_string
template <typename T> std::string _to_string(const T& value) {
std::ostringstream os;
os.copyfmt(std::cout);
os << value;
return os.str();
}
#endif
int _tmain(int argc, _TCHAR* argv[]) {
int iBytes = 123981;
int iTotalBytes = 1030131;
#if defined(UNICODE) || defined(_UNICODE)
wostringstream newCoutBuffer;
wstreambuf* oldCoutBuffer = _tcout.rdbuf(newCoutBuffer.rdbuf()); // redirect cout buffer
#endif
_tcout.imbue(std::locale("German")); // enable thousand separator
_tcout.precision(0);
_tcout << setfill(_T('.')) << right << fixed;
_tcout << _T("bytes ") << setw(20) << _T(" ") + _to_tstring(iBytes) << endl;
_tcout << _T("bytes total ") << setw(14) << _T(" ") + _to_tstring(iTotalBytes) << endl;
_tcout << _T("bla bla ") << fixed << setprecision(9); _tcout << setw(18) << _T(" ") + _to_tstring(0.1337) << endl;
_tcout << _T("Милые женщины ") << hex; _tcout << setw(12) << _T(" ") + _to_tstring(iTotalBytes) << endl;
_tcout << _T("retries ") << dec; _tcout << setw(18) << _T(" ") + _to_tstring(2) + _T(" of ") + _to_tstring(20) << endl;
#if defined(UNICODE) || defined(_UNICODE)
DWORD dwWritten;
WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), newCoutBuffer.str().c_str(),newCoutBuffer.tellp(),&dwWritten,NULL);
_tcout.rdbuf(oldCoutBuffer);
#endif
return 0;
}
Output:
bytes ............ 123.981
bytes total .... 1.030.131
bla bla ...... 0,133700000
Милые женщины ..... fb.7f3
retries .......... 2 of 20