In a question I found something like this: Write a custom I/O manipulator that prints
123.456%%%
against the following code cout<<setup<<123.456789;
How can this be achieved? I tried this:
#include <iostream>
#include <iomanip>
using namespace std;
std::ostream& setup(std::ostream& os, double num) {
os << std::setprecision(3) << std::fixed << std::showpoint << std::setw(10) << std::left << num << "%%%";
return os;
}
int main() {
//cout << setfill('?') << setw(10) << 2343.0;
cout<<setup<<123.45678;
return 0;
}
Output: 1123.457
Building on @IgorTandetnik's comments above:
The problem:
Your setup
function does not match the required signature of I/O manipulators as specified here for func
- see overloads (18)-(20) of basic_ostream& operator<<
:
(18): basic_ostream& operator<<(std::ios_base& (*func)(std::ios_base&) );
(19): basic_ostream& operator<<(std::basic_ios<CharT, Traits>& (*func)std::basic_ios<CharT, Traits>&) );
(20): basic_ostream& operator<<(std::basic_ostream<CharT, Traits>& (*func)(std::basic_ostream<CharT, Traits>&) );
Therefore when you use cout << setup
, the setup
function is not called (as it was done if it was a proper manipulator).
Instead the address of it is converted to bool
and displayed as 1
(this is the initial 1
that you see).
clang even gives a meaniniful warning:
warning: address of function 'setup' will always evaluate to 'true'
A solution:
You can achieve what you want by using one of the I/O manipulators signatures.
Using the signature of func
from overload (18) is shown below:
#include <iostream>
#include <iomanip>
std::ostream& setup(std::ostream& os) {
return os << std::setprecision(3) << std::fixed << std::showpoint << std::setw(10) << std::left << std::setfill('%');
}
int main() {
std::cout<<setup<<123.45678;
return 0;
}
Output:
123.457%%%
A side note: Why is "using namespace std;" considered bad practice?.
Update:
If you want to truncate the value and avoid rounding, you can multiply the value by 1000 (for 3 digits precision), floor
it, and then divide by 1000:
#include <iostream>
#include <iomanip>
#include <cmath>
std::ostream& setup(std::ostream& os) {
return os << std::setprecision(3) << std::fixed << std::showpoint << std::setw(10) << std::left << std::setfill('%');
}
int main() {
double val = 123.45678;
double val_truncated = std::floor(val*1000) / 1000;
std::cout<<setup<<val_truncated;
return 0;
}
Output:
123.456%%%