I am chaining some stream manipulators in an ofstream like so:
std::string filename = "output.txt";
std::ofstream outputFile;
outputFile.open(filename, std::ios::trunc);
outputFile << std::setw(5) << std::scientific << std::left << variable;
Is it possible to do something like this instead?:
std::string filename = "output.txt";
std::ofstream outputFile;
outputFile.open(filename, std::ios::trunc);
std::ostream m;
m << std::setw(5) << std::scientific << std::left; // Combine manipulators into a single variable
outputFile << m << variable;
A stream manipulator is just a function that a stream calls on itself through one of the operator << overloads (10-12 in the link). You just have to declare such a function (or something convertible to a suitable function pointer):
constexpr auto m = [](std::ostream &s) -> std::ostream& {
return s << std::setw(5) << std::scientific << std::left;
};
std::cout << m << 12.3 << '\n';
See it live on Wandbox
You can write your own manipulator:
struct my_manipulator{};
std::ostream& operator<<(std::ostream& o, const my_manipulator& mm) {
o << std::setw(5) << std::scientific << std::left;
return o;
};
This would allow you to write
outputFile << my_manipulator{} << variable;
PS: Io-manipulators modify the state of the stream. Hence it cannot work exactly the way you asked for. You are modifying the state of m. Transferring the state from one stream to another is possible, but imho more complicated than necessary.
PPS: Note that my way of defining a custom io-manipulator is ok-ish, but to see an implementation that is more in the spirit of stream manipulators see this answer (usually io-manipulators are functions, I used a tag which requires a tiny bit more boilerplate).
Related
I need a C++ function that dumps some text data (multiple lines) to the console:
void DumpData() const
{
std::cout << "My Data 1" << std::endl;
std::cout << "My Data 2" << std::endl;
}
This should be the default behaviour, however, it must also be possible to pass some other stream object that would be used instead of std::cout, something like this:
void DumpData(std::ostream& Stream = std::cout) const
{
Stream << "My Data 1" << std::endl;
Stream << "My Data 2" << std::endl;
}
Now to my questions:
What is the correct type I should use for the paramter (std::ostream& in this example)?
What is the default value, can I use = std::cout directly?
Moreover (3.), after the call to this function, if I pass my own stream object, I need to iterate over all strings in this stream line by line. What would be the best way to achieve this?
Why don't you just try it yourself?
Here's you code in Coliru for std::cout and std::stringstream as an example (constness of DumpData removed obviously):
#include <iostream>
#include <sstream>
void DumpData(std::ostream& Stream = std::cout)
{
Stream << "My Data 1" << std::endl;
Stream << "My Data 2" << std::endl;
}
int main() {
DumpData();
std::stringstream ss;
DumpData(ss);
std::string l;
while(std::getline(ss, l)) {
std::cout << l << std::endl;
}
return 0;
}
Output is what you expected.
1 and 2 are correct. Your other option is to use std::ostringstream, but since std::cout is a std::ostream you would need to define another function with this signature.
To iterate the custom output, I would convert the stream to a string, then use some kind of string splitting to read each line.
Adding to #Jay 's answer, you could use a template parameter to be able to use a variety of streams such as std::stringstream or a std::iostream as long as the template parameter supports the << operator.
template <typename T> // = decltype(something)
void DumpData(T& Stream = std::cout) const
{
Stream << "My Data 1" << std::endl;
Stream << "My Data 2" << std::endl;
}
You can take it one step further by ensuring the type T provided overloads the operator <<.
Also in some cases, certain (possibly custom) streams may not be able to support std::endl so it might be safer to default to using \n which is always nicer since it avoid unnecessary flushes.
It is a pain to do an endline between each value with OFSTREAM.
Here's an example of what I've got:
ofstream fout("~/xample.txt");
fout << val1;
fout << endl;
fout << val2;
I want to be able to do, instead,
ofstream fout("xample.txt");
fout << val1;
fout << val2;
I don't care how the file is stored because I will write a configuration wizard anyways.
If fout << val1 << endl; does not work with you, you might be able to inherit ofstream and create your own stream that adds endl automatically. But also you can drink water from fire hydrant.
It is a pain ...
Besides you could simply write
fout << val1 << endl;
fout << val2 << endl;
you may use any other whitespace character value to delimit your values in the output file:
fout << val1 << ' ';
fout << val2 << ' ';
// ... more value outputs
fout << endl;
Shouldn't matter for the file size, but number of lines definitely.
UPDATE:
As you're asking how to extend the formatting behavior on std::ostream:
I don't think it's a good idea to use inheritance from std::streambuf, std::ostream, et al., and try to (re-)implement the interfaces themselves (as usually never it's a good idea inheriting STL classes, can be done though). I'd say the intended way is to use stream manipulators for such.
To automate appending the endl or any other delimiter you could write a small parameterized stream manipulator (at least this solution is copy/paste and IDE intellisense friendly):
template<typename T>
class auto_delim_manip
{
public:
auto_delim_manip(T value_, char delim_)
: value(value_)
, delim(delim_) {}
void put(std::ostream& os) const {
os << value << delim;
os.flush();
}
private:
T value;
char delim;
};
template<typename T>
auto_delim_manip<T> auto_delim(T value, char delim = '\n') {
return auto_delim_manip<T>(value,delim);
}
template<typename T>
std::ostream& operator<<(std::ostream& os, const auto_delim_manip<T>& autoDelim)
{
autoDelim.put(os);
return os;
}
int main() {
cout << auto_delim(5.2) << auto_delim(3) << auto_delim("Hello!");
return 0;
}
Output:
5.2
3
Hello!
Check the running sample here.
If you have a large number of values, simply put 'endl' on the same line as your output and loop through all of your data. Such as:
for(int i = 0; i < numValues; ++i) {
fout << values[i] << endl;
}
I'm not aware of a built-in way to automate this, but it's honestly not that much work to add line endings manually.
I often do something like:
uint8_t c=some_value;
std::cout << std::setfill('0') << std::setw(2);
std::cout << std::hex << int(c);
std::cout << std::setfill(' ');
(in particular while dumping debugging information). Wouldn't it be nice to have something manipulatorish that I could put in a stream like this:
std::cout << "c value: 0x" << hexb(c) << '\n';
that would do all of that? Does anyone know how to do that?
I've gotten this to work but would love to have a simpler way:
#include <iostream>
#include <iomanip>
class hexcdumper{
public:
hexcdumper(uint8_t c):c(c){};
std::ostream&
operator( )(std::ostream& os) const
{
// set fill and width and save the previous versions to be restored later
char fill=os.fill('0');
std::streamsize ss=os.width(2);
// save the format flags so we can restore them after setting std::hex
std::ios::fmtflags ff=os.flags();
// output the character with hex formatting
os << std::hex << int(c);
// now restore the fill, width and flags
os.fill(fill);
os.width(ss);
os.flags(ff);
return os;
}
private:
uint8_t c;
};
hexcdumper
hexb(uint8_t c)
{
// dump a hex byte with width 2 and a fill character of '0'
return(hexcdumper(c));
}
std::ostream& operator<<(std::ostream& os, const hexcdumper& hcd)
{
return(hcd(os));
}
When I do this:
std::cout << "0x" << hexb(14) << '\n';
hexb(c) is invoked and returns a hexcdumper whose constructor saves c
the overloaded operator<< for hexcdumper invokes
hexcdumper::operator() passing it the stream
hexcdumper's operator() does all the magic for us
after hexcdumper::operator() returns, the overloaded operator<<
returns the stream as returned from hexcdumper::operator() so chaining works.
On the output, I see:
0x0e
Is there a simpler way to do this?
Patrick
You can do this directly on the stream pipe:
std::cout << "Hex = 0x" << hex << 14 << ", decimal = #" << dec << 14 << endl;
Output:
Hex = 0xe, decimal = #14
I would like to print a bunch of integers on 2 fields with '0' as fill character. I can do it but it leads to code duplication. How should I change the code so that the code duplication can be factored out?
#include <ctime>
#include <sstream>
#include <iomanip>
#include <iostream>
using namespace std;
string timestamp() {
time_t now = time(0);
tm t = *localtime(&now);
ostringstream ss;
t.tm_mday = 9; // cheat a little to test it
t.tm_hour = 8;
ss << (t.tm_year+1900)
<< setw(2) << setfill('0') << (t.tm_mon+1) // Code duplication
<< setw(2) << setfill('0') << t.tm_mday
<< setw(2) << setfill('0') << t.tm_hour
<< setw(2) << setfill('0') << t.tm_min
<< setw(2) << setfill('0') << t.tm_sec;
return ss.str();
}
int main() {
cout << timestamp() << endl;
return 0;
}
I have tried
std::ostream& operator<<(std::ostream& s, int i) {
return s << std::setw(2) << std::setfill('0') << i;
}
but it did not work, the operator<< calls are ambigous.
EDIT I got 4 awesome answers and I picked the one that is perhaps the simplest and the most generic one (that is, doesn't assume that we are dealing with timestamps). For the actual problem, I will probably use std::put_time or strftime though.
In C++20 you'll be able to do this with std::format in a less verbose way:
ss << std::format("{}{:02}{:02}{:02}{:02}{:02}",
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
and it's even easier with the {fmt} library that supports tm formatting directly:
auto s = fmt::format("{:%Y%m%d%H%M%S}", t);
You need a proxy for your string stream like this:
struct stream{
std::ostringstream ss;
stream& operator<<(int i){
ss << std::setw(2) << std::setfill('0') << i;
return *this; // See Note below
}
};
Then your formatting code will just be this:
stream ss;
ss << (t.tm_year+1900)
<< (t.tm_mon+1)
<< t.tm_mday
<< t.tm_hour
<< t.tm_min
<< t.tm_sec;
return ss.ss.str();
ps. Note the general format of my stream::operator<<() which does its work first, then returns something.
The "obvious" solution is to use a manipulator to install a custom std::num_put<char> facet which just formats ints as desired.
The above statement may be a bit cryptic although it entirely describes the solution. Below is the code to actually implement the logic. The first ingredient is a special std::num_put<char> facet which is just a class derived from std::num_put<char> and overriding one of its virtual functions. The used facet is a filtering facet which looks at a flag stored with the stream (using iword()) to determine whether it should change the behavior or not. Here is the code:
class num_put
: public std::num_put<char>
{
std::locale loc_;
static int index() {
static int rc(std::ios_base::xalloc());
return rc;
}
friend std::ostream& twodigits(std::ostream&);
friend std::ostream& notwodigits(std::ostream&);
public:
num_put(std::locale loc): loc_(loc) {}
iter_type do_put(iter_type to, std::ios_base& fmt,
char fill, long value) const {
if (fmt.iword(index())) {
fmt.width(2);
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, '0', value);
}
else {
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, fill, value);
}
}
};
The main part is the do_put() member function which decides how the value needs to be formatted: If the flag in fmt.iword(index()) is non-zero, it sets the width to 2 and calls the formatting function with a fill character of 0. The width is going to be reset anyway and the fill character doesn't get stored with the stream, i.e., there is no need for any clean-up.
Normally, the code would probably live in a separate translation unit and it wouldn't be declared in a header. The only functions really declared in a header would be twodigits() and notwodigits() which are made friends in this case to provide access to the index() member function. The index() member function just allocates an index usable with std::ios_base::iword() when called the time and it then just returns this index. The manipulators twodigits() and notwodigits() primarily set this index. If the num_put facet isn't installed for the stream twodigits() also installs the facet:
std::ostream& twodigits(std::ostream& out)
{
if (!dynamic_cast<num_put const*>(
&std::use_facet<std::num_put<char> >(out.getloc()))) {
out.imbue(std::locale(out.getloc(), new num_put(out.getloc())));
}
out.iword(num_put::index()) = true;
return out;
}
std::ostream& notwodigits(std::ostream& out)
{
out.iword(num_put::index()) = false;
return out;
}
The twodigits() manipulator allocates the num_put facet using new num_put(out.getloc()). It doesn't require any clean-up because installing a facet in a std::locale object does the necessary clean-up. The original std::locale of the stream is accessed using out.getloc(). It is changed by the facet. In theory the notwodigits could restore the original std::locale instead of using a flag. However, imbue() can be a relatively expensive operation and using a flag should be a lot cheaper. Of course, if there are lots of similar formatting flags, things may become different...
To demonstrate the use of the manipulators there is a simple test program below. It sets up the formatting flag twodigits twice to verify that facet is only created once (it would be a bit silly to create a chain of std::locales to pass through the formatting:
int main()
{
std::cout << "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits1='" << 1 << "' "
<< "two-digits2='" << 2 << "' "
<< "two-digits3='" << 3 << "' "
<< notwodigits << '\n'
<< "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits4='" << 4 << "' "
<< '\n';
}
Besides formatting integers with std::setw / std::setfill or ios_base::width / basic_ios::fill, if you want to format a date/time object you may want to consider using std::put_time / std::gettime
For convenient output formatting you may use boost::format() with sprintf-like formatting options:
#include <boost/format.hpp>
#include <iostream>
int main() {
int i1 = 1, i2 = 10, i3 = 100;
std::cout << boost::format("%03i %03i %03i\n") % i1 % i2 % i3;
// output is: 001 010 100
}
Little code duplication, additional implementation effort is marginal.
If all you want to do is output formatting of your timestamp, you should obviously use strftime(). That's what it's made for:
#include <ctime>
#include <iostream>
std::string timestamp() {
char buf[20];
const char fmt[] = "%Y%m%d%H%M%S";
time_t now = time(0);
strftime(buf, sizeof(buf), fmt, localtime(&now));
return buf;
}
int main() {
std::cout << timestamp() << std::endl;
}
operator<<(std::ostream& s, int i) is "ambiguous" because such a function already exists.
All you need to do is give that function a signature that doesn't conflict.
When you're overloading the << operator for a class (pretend this is defined as a friend in SomeClass), why do you both take a reference to the ostream and return that ostream?
ostream& operator<<(ostream& s, const SomeClass& c) {
//whatever
return s;
}
What benefit can returning the ostream be when it was already directly modifiable by reference? This seems redundant to me - though I'm sure it's not :)
It allows to "chain" output together. As in :
std::cout << someObj << someValue;
This is equivalent to something like :
operator<<(operator<<(std::cout, someObj), someValue);
This is not redundant, but useful for chaining calls. It's easier to see with functions like std::string::append, so I'll start with that:
std::string mystring("first");
mystring.append(" second");
mystring.append(" third");
can be rewritten as:
std::string mystring("first").append(" second").append(" third");
This is possible because .append() returns a reference to the string it modified, so we can keep adding .append(...) to the end. The code correlating to what you are doing is changing from this:
std::cout << "first";
std::cout << " second";
std::cout << " third";
into this. Since operator<< returns the stream, we can also chain these!
std::cout << "first" << " second" << " third";
see the similarity, and usefulness?
So that you can write chained-invocation of operator<< as:
stream << s1 << s2 << s3 ;
If you don't return ostream&, then you cannot write it more than once.
You can think of that either as:
operator<<(operator<<(operator<<(stream, s1), s2), s3);
Or as,
((stream << s1) << s2) << s3 ;
First (stream << s1) returns stream& on which you again invoke << and it becomes stream << s2 which returns stream& on which you again invoke << and it becomes stream << s3.
Ah, this is so linked output, like
cout << "this " << "is " << "a pen" << endl;
will still work.