27

I've got a line of code that sets the fill value to a '-' character in my output, but need to reset the setfill flag to its default whitespace character. How do I do that?

cout << setw(14) << "  CHARGE/ROOM" << endl;
cout << setfill('-') << setw(11) << '-' << "  " << setw(15) << '-' << "   " << setw(11) << '-' << endl;

I thought this might work:

cout.unsetf(ios::manipulatorname) // Howerver I dont see a manipulator called setfill

Am I on the wrong track?

John Carter
  • 53,924
  • 26
  • 111
  • 144
noobzilla
  • 1,095
  • 2
  • 11
  • 17

5 Answers5

32

You can use copyfmt to save cout's initial formatting. Once finished with formatted output you can use it again to restore the default settings (including fill character).

{
    // save default formatting
    ios init(NULL);
    init.copyfmt(cout);

    // change formatting...
    cout << setfill('-') << setw(11) << '-' << "  ";
    cout << setw(15) << '-' << "   ";
    cout << setw(11) << '-' << endl;

    // restore default formatting
    cout.copyfmt(init);
}
deancutlet
  • 581
  • 6
  • 6
  • Surprised nobody posted this earlier :) Rolling it into an RAII guard would be good though, in case an exception is thrown. Have run into that issue in a logging framework. – M.M Jan 24 '15 at 03:49
  • Is that working on all systems? When I try it, my std::cout refuses to output anything after...ever! – BitTickler Jan 26 '15 at 06:59
  • this is great! it works also for std::hex – kingsjester Oct 04 '22 at 08:00
  • Here you have RAII simple impl: https://github.com/gelldur/gcpp/blob/master/src/gcpp/stream/StreamScopeFormat.hpp – Gelldur Oct 05 '22 at 07:48
31

Have a look at the Boost.IO_State_Savers, providing RAII-style scope guards for the flags of an iostream.

Example:

#include <boost/io/ios_state.hpp>

{
  boost::io::ios_all_saver guard(cout); // Saves current flags and format

  cout << setw(14) << "  CHARGE/ROOM" << endl;
  cout << setfill('-') << setw(11) << '-' << "  " << setw(15) << '-' << "   " << setw(11) << '-' << endl;
// dtor of guard here restores flags and formats
}

More specialized guards (for only fill, or width, or precision, etc... are also in the library. See the docs for details.

gd1
  • 11,300
  • 7
  • 49
  • 88
Éric Malenfant
  • 13,938
  • 1
  • 40
  • 42
  • Great answer, should be the accepted one. – gd1 Sep 29 '15 at 09:43
  • 22
    @gd1: Good answer, but not _great_, as I have to include Boost just to save the iostream flags. – Isaac Jan 05 '16 at 08:41
  • 3
    @Isaac: in C++, it seems to me that you either use boost or end up reimplementing it, or wait for Boost.Something to be included in the standard. – gd1 Jan 07 '16 at 18:32
10

You can use the ios::fill() function to set and restore the fill character instead.

http://www.cplusplus.com/reference/iostream/ios/fill/

#include <iostream>
using namespace std;

int main () {
  char prev;

  cout.width (10);
  cout << 40 << endl;

  prev = cout.fill ('x');
  cout.width (10);
  cout << 40 << endl;

  cout.fill(prev);

  return 0;
}
John Carter
  • 53,924
  • 26
  • 111
  • 144
3

You can manually change the setfill flag to whatever you need it to be:

float number = 4.5;
cout << setfill('-');
cout << setw(11) << number << endl; // --------4.5
cout << setfill(' ');
cout << setw(11) << number << endl; // 4.5
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Dmitry V
  • 39
  • 2
-2

The null character will reset it back to the original state: setfill('\0')

Matt
  • 27
  • 2
  • 2
    The original state is not necessarily the *previous* state. Besides, where is this claimed function of `'\0'` documented? All I can see are statements that `setfill()` just takes a `char`, with no special meaning for it. So you would be setting the fill character to `NUL`, which is not going to be what it originally was and is not going to be very useful at all. Or did I miss something in the Standard that makes it work? – underscore_d Sep 29 '18 at 23:25