Effective Use of C++ Iomanip Library

Effective use of C++ iomanip library

Only std::setw() is temporary. The other two calls, setiosflags, and setprecision have a permanent effect.

So, you could change your code to :

std::ostream& operator<<(std::ostream &output, const Vector &v){
output<<"["
<<std::setiosflags(std::ios::right | std::ios::scientific)
<<std::setw(23)
<<std::setprecision(16)
<<v._x<<", "
<<std::setw(23)
<<v._y<<", "
<<std::setw(23)
<<v._z<<"]";
return output;
}

But now you've borked the flags and precision for the next guy. Try this instead:

std::ostream& operator<<(std::ostream &output, const Vector &v){
std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific);
std::streamsize p = output.precision(16);
output<<"["
<<std::setw(23)
<<v._x<<", "
<<std::setw(23)
<<v._y<<", "
<<std::setw(23)
<<v._z<<"]";
output.flags(f);
output.precision(p);
return output;
}

Finally, if you absolutely have to get rid of the duplication of the constant 23, you could do something like this (but I wouldn't recommend it):

struct width {
int w;
width(int w) : w(w) {}
friend std::ostream& operator<<(std::ostream&os, const width& w) {
return os << std::setw(width.w);
}
};

std::ostream& operator<<(std::ostream &output, const Vector &v){
std::ios_base::fmtflags f = output.flags(std::ios::right | std::ios::scientific);
std::streamsize p = output.precision(16);
width w(23);
output<<"["
<<w
<<v._x<<", "
<<w
<<v._y<<", "
<<w
<<v._z<<"]";
output.flags(f);
output.precision(p);
return output;
}

See also this other question, where they decided that you can't make width permanent.

format, iomanip, c++

You want std::fixed (the other one just inserts its value into the stream, which is why you see 8192), and I don't see a call to std::setprecision in your code anywhere.

This'll fix it:

#include <iostream>
#include <iomanip>

using std::cout;
using std::setprecision;
using std::fixed;

int main()
{
cout << fixed << setprecision(2)
<< "saver1\n"
<< "monthlyInterestRate: " << 5.5 << '\n'
<< "savingsBalance: " << 10928.8383 << '\n';
cout << "saver2\n"
<< "monthlyInterestRate: " << 4.7 << '\n'
<< "savingsBalance: " << 22.44232 << '\n';
}

Using the iomanip directive

Unfortunately, no. You must use setw() before almost every output operation. The problem is that operator<< effectively calls setw(0) after the output, thus you need to set width again. See here for a full list of operations that reset field width.

Note: setw is just a wrapper around width(), so using the latter won't help.

Which C I/O library should be used in C++ code?

To answer the original question:

Anything that can be done using stdio can be done using the iostream library.

Disadvantages of iostreams: verbose
Advantages of iostreams: easy to extend for new non POD types.

The step forward the C++ made over C was type safety.

  • iostreams was designed to be explicitly type safe. Thus assignment to an object explicitly checked the type (at compiler time) of the object being assigned too (generating an compile time error if required). Thus prevent run-time memory over-runs or writing a float value to a char object etc.

  • scanf()/printf() and family on the other hand rely on the programmer getting the format string correct and there was no type checking (I believe gcc has an extension that helps). As a result it was the source of many bugs (as programmers are less perfect in their analysis than compilers [not going to say compilers are perfect just better than humans]).

Just to clarify comments from Colin Jensen.

  • The iostream libraries have been stable since the release of the last standard (I forget the actual year but about 10 years ago).

To clarify comments by Mikael Jansson.

  • The other languages that he mentions that use the format style have explicit safeguards to prevent the dangerous side effects of the C stdio library that can (in C but not the mentioned languages) cause a run-time crash.

N.B. I agree that the iostream library is a bit on the verbose side. But I am willing to put up with the verboseness to ensure runtime safety. But we can mitigate the verbosity by using Boost Format Library.

#include <iostream>
#include <iomanip>
#include <boost/format.hpp>

struct X
{ // this structure reverse engineered from
// example provided by 'Mikael Jansson' in order to make this a running example

char* name;
double mean;
int sample_count;
};
int main()
{
X stats[] = {{"Plop",5.6,2}};

// nonsense output, just to exemplify

// stdio version
fprintf(stderr, "at %p/%s: mean value %.3f of %4d samples\n",
stats, stats->name, stats->mean, stats->sample_count);

// iostream
std::cerr << "at " << (void*)stats << "/" << stats->name
<< ": mean value " << std::fixed << std::setprecision(3) << stats->mean
<< " of " << std::setw(4) << std::setfill(' ') << stats->sample_count
<< " samples\n";

// iostream with boost::format
std::cerr << boost::format("at %p/%s: mean value %.3f of %4d samples\n")
% stats % stats->name % stats->mean % stats->sample_count;
}

is there a good way to combine stream manipulators?

Avoid the macros when you can! They hide code, making things hard to debug, don't respect scope, etc.

You can use a simple function as KenE provided. If you want to get all fancy and flexible, then you can write your own manipulator:

#include <iostream>
#include <iomanip>
using namespace std;

ostream& hex4(ostream& out)
{
return out << "0x" << hex << setw(4) << setfill('0');
}

int main()
{
cout << hex4 << 123 << endl;
}

This makes it a little more general. The reason the function above can be used is because operator<< is already overloaded like this: ostream& operator<<(ostream&, ostream& (*funtion_ptr)(ostream&)). endl and some other manipulators are also implemented like this.

If you want to allow the number of digits to be specified at runtime, we can use a class:

#include <iostream>
#include <iomanip>
using namespace std;

struct formatted_hex
{
unsigned int n;
explicit formatted_hex(unsigned int in): n(in) {}
};

ostream& operator<<(ostream& out, const formatted_hex& fh)
{
return out << "0x" << hex << setw(fh.n) << setfill('0');
}

int main()
{
cout << formatted_hex(4) << 123 << endl;
}

If the size can be determined at compile-time, however, might as well just use a function template [thanks to Jon Purdy for this suggestion]:

template <unsigned int N>
ostream& formatted_hex(ostream& out)
{
return out << "0x" << hex << setw(N) << setfill('0');
}

int main()
{
cout << formatted_hex<4> << 123 << endl;
}

Reset properties of std::cout for integers or doubles in C++

Use resetiosflags:

std::cout << std::resetiosflags( std::ios_base::basefield ); // clears integer manipulations
std::cout << std::resetiosflags( std::ios_base::floatfield ); // clears floating-point manipulations
std::cout << std::resetiosflags( std::cout.flags() ); // clears all flags

iomanip / fixed width persistence

Unfortunately you've wandered into one of the areas of the standard that's a little archaic and seemingly without any overarching design goals.

This is undoubtedly historic as the iostreams library AFAIAA, was not originally part of the STL which is what became the standard library.

It's worth reading the notes on all std::ios_base members and the associated manipulators.

For example:

http://en.cppreference.com/w/cpp/io/ios_base/width

Some I/O functions call width(0) before returning, see std::setw (this results in this field having effect on the next I/O function only, and not on any subsequent I/O)

The exact effects this modifier has on the input and output vary between the individual I/O functions and are described at each operator<< and operator>> overload page individually.

Anticipating:

But that's just <insert expletive>!!!

A: yup.



Related Topics



Leave a reply



Submit