2

I have the following working code which produces formatted output using an ofstream, however I feel that all of the repeated format specifiers make it hard to read. Is there any way to set the precision, width and alignment permanently for a given stream, which would clean things up nicely?

#include <fstream>
#include <iomanip> 

ofstream myfile;
myfile.open(Output.c_str(), ios::trunc);
for (int i = 0; i < iLen; i++) {
   myfile <<std::fixed << std::setw( iWidth ) << std::setprecision( iDecimals )<< std::right << pDist[i]  << "   "
      <<std::fixed << std::setw( iWidth ) << std::setprecision( iDecimals )<< std::right << pRes[i]   << "   "
      <<std::fixed << std::setw( iWidth ) << std::setprecision( iDecimals )<< std::right << pPhase[i] << "\n";
}
myfile.close();
marcp
  • 1,179
  • 2
  • 15
  • 36
  • 4
    Have you tried just removing the repeated format specifiers? Most format specifiers are persisted until they are explicitly changed again. – Code-Apprentice Oct 28 '14 at 16:45
  • 2
    `std::fixed`, `std::setprecision`, and `std::right` are all "permanent". The only one that you need every time is `setw`. – Calvin Scherle Oct 28 '14 at 16:48
  • @CalvinScherle is right. I had tried removing the specifiers as suggested by Code-Apprentice, but that didn't work because I was removing all of them. Thanks Stack Overflow! – marcp Oct 28 '14 at 16:54

2 Answers2

4

std::fixed, std::setprecision, and std::right are all "permanent". They set persistent flags on the stream object.

The only one that you need to put every time is setw, which (as I understand) does not set a flag on the stream object, just adds a certain amount of whitespace by altering the stream itself. But it leaves the stream alone.

This is similar to endl, which operates on the stream but leaves the actual stream object alone.

This answer by @LokiAstari on a similar question details which specifiers are, as they put it, "sticky" (and why).

EDIT: Cleared up distinctions between the stream object and the actual stream

Community
  • 1
  • 1
Calvin Scherle
  • 312
  • 1
  • 9
2

The only manipulator you need to worry about is std::setw as the width is set back to zero whenever operator<< is called. Before your loop, you can set your "permanent" ios flags:

myfile << std::fixed << std::setprecision(iDecimals) << std::right;
for (int i = 0; i < iLen; i++) {
   myfile << std::setw( iWidth ) << pDist[i] << "   "
      << std::setw( iWidth ) << pRes[i] << "   "
      << std::setw( iWidth ) << pPhase[i] << "\n";
}

If you want to unset these flags in one go, you can use:

std::cout.copyfmt(std::ios(NULL));

As stated in this answer.

Community
  • 1
  • 1