CS253: Software Development with C++

Fall 2020

Manipulators

Show Lecture.Manipulators as a slide show.

CS253 Manipulators

I/O Manipulators

As you recall, there are a number of I/O manipulators:

<ios> or <iostream><iomanip>
These don’t take an argument  These do take an argument
[no]boolalpharesetiosflags
[no]showbasesetiosflags
[no]showpointsetbase
[no]showpossetfill
[no]skipwssetprecision
[no]uppercasesetw (non-sticky)
left / right / internal
dec / hex / oct
fixed / scientific

[no]boolalpha

cout                << false << ' ' << true << '\n'
     << boolalpha   << false << ' ' << true << '\n'
     << noboolalpha << false << ' ' << true << '\n';
0 1
false true
0 1

[no]showbase

cout               << dec << 65 << ' ' << hex << 65 << ' ' << oct << 65 << '\n'
     << showbase   << dec << 65 << ' ' << hex << 65 << ' ' << oct << 65 << '\n'
     << noshowbase << dec << 65 << ' ' << hex << 65 << ' ' << oct << 65 << '\n';
65 41 101
65 0x41 0101
65 41 101

[no]showpoint

cout                << 123.0 << ' ' << 456.789 << '\n'
     << showpoint   << 123.0 << ' ' << 456.789 << '\n'
     << noshowpoint << 123.0 << ' ' << 456.789 << '\n';
123 456.789
123.000 456.789
123 456.789

[no]showpos

cout              << 123 << ' ' << 0 << ' ' << -456 << '\n'
     << showpos   << 123 << ' ' << 0 << ' ' << -456 << '\n'
     << noshowpos << 123 << ' ' << 0 << ' ' << -456 << '\n';
123 0 -456
+123 +0 -456
123 0 -456

[no]skipws

istringstream iss;
int a;

iss.str("\n\r\v\f 123 ");
iss >> a;
cout << (iss?"good":"bad") << ' ' << a << '\n';

iss.str("\n\r\v\f 456 ");
iss >> skipws >> a;
cout << (iss?"good":"bad") << ' ' << a << '\n';

iss.str("\n\r\v\f 789 ");
iss >> noskipws >> a;
cout << (iss?"good":"bad") << ' ' << a << '\n';
good 123
good 456
bad 0

[no]uppercase

cout                << hex << 64206 << ' ' << 1e99 << " end\n"
     << uppercase   << hex << 64206 << ' ' << 1e99 << " end\n"
     << nouppercase << hex << 64206 << ' ' << 1e99 << " end\n";
face 1e+99 end
FACE 1E+99 end
face 1e+99 end

left / right / internal

cout                         << 123 << "⚓\n"
     << setw(10) <<     left << 123 << "⚓\n"
     << setw(10) <<    right << 123 << "⚓\n"
     << setw(10) << internal << 123 << "⚓\n";
123⚓
123       ⚓
       123⚓
       123⚓
cout                         << -123 << "⚓\n"
     << setw(10) <<     left << -123 << "⚓\n"
     << setw(10) <<    right << -123 << "⚓\n"
     << setw(10) << internal << -123 << "⚓\n";
-123⚓
-123      ⚓
      -123⚓
-      123⚓
cout                                         << -123 << "⚓\n"
     << setw(10) << setfill('x') <<     left << -123 << "⚓\n"
     << setw(10) << setfill('x') <<    right << -123 << "⚓\n"
     << setw(10) << setfill('x') << internal << -123 << "⚓\n";
-123⚓
-123xxxxxx⚓
xxxxxx-123⚓
-xxxxxx123⚓

dec / oct / hex

cout        << 10 << ' ' << 30 << ' ' << 50 << '\n'
     << dec << 10 << ' ' << 30 << ' ' << 50 << '\n'
     << oct << 10 << ' ' << 30 << ' ' << 50 << '\n'
     << hex << 10 << ' ' << 30 << ' ' << 50 << '\n';
10 30 50
10 30 50
12 36 62
a 1e 32
cout << bin << 10;
c.cc:1: error: 'bin' was not declared in this scope

fixed / scientific / hexfloat / defaultfloat

cout               << 16e5 << ' ' << 3.14159 << ' ' << 4.5e-12 << '\n'
   << fixed        << 16e5 << ' ' << 3.14159 << ' ' << 4.5e-12 << '\n'
   << scientific   << 16e5 << ' ' << 3.14159 << ' ' << 4.5e-12 << '\n'
   << hexfloat     << 16e5 << ' ' << 3.14159 << ' ' << 4.5e-12 << '\n'
   << defaultfloat << 16e5 << ' ' << 3.14159 << ' ' << 4.5e-12 << '\n';
1.6e+06 3.14159 4.5e-12
1600000.000000 3.141590 0.000000
1.600000e+06 3.141590e+00 4.500000e-12
0x1.86ap+20 0x1.921f9f01b866ep+1 0x1.3ca8cb153a753p-38
1.6e+06 3.14159 4.5e-12

setfill

cout                             << 123 << '\n'
                     << setw(10) << 456 << '\n'
     << setfill('*') << setw(10) << 789 << '\n';
123
       456
*******789

setprecision

https://cplusplus.com/reference/ios/ios_base/precision/ says:

setprecision

cout << 123.45 << '\n'
     << setprecision(1) << 123.45 << '\n'
     << setprecision(9) << 123.45 << '\n';
123.45
1e+02
123.45
cout << fixed
     << 123.45 << '\n'
     << setprecision(1) << 123.45 << '\n'
     << setprecision(9) << 123.45 << '\n';
123.450000
123.5
123.450000000
cout << scientific
     << 123.45 << '\n'
     << setprecision(1) << 123.45 << '\n'
     << setprecision(9) << 123.45 << '\n';
1.234500e+02
1.2e+02
1.234500000e+02

setw

cout << setw(5) << 1 << 2 << 3 << 4 << '\n';
    1234
cout << setw(9) <<   6.7 << '\n'
     << setw(9) <<   'x' << '\n'
     << setw(9) << "foo" << '\n';
      6.7
        x
      foo
cout << setfill('*') << setw(4) <<     8.9 << '\n'
                     << setw(4) <<     'y' << '\n'
                     << setw(4) <<   "bar" << '\n'
                     << setw(4) << "alpha" << '\n';
*8.9
***y
*bar
alpha

Etiquette

void showhex(int n) {
    cout << hex << setw(8) << setfill('0') << n << '\n';
}

int main() {
    showhex(100);
    cout << 42 << '\n';
}
00000064
2a

It’s rude to change a global resource. showhex()’s job is to display a number, not to display a number and change the state of cout.

main() didn’t expect the base of cout, or its fill character, to get changed. Now, of course, if it’s main() that’s changing those settings, who else would complain? Well, perhaps main() calls general-purpose functions that don’t work well if the settings of cout are changed.

Etiquette

void showhex(int n) {
    const auto save_flags = cout.flags();
    const auto save_fill = cout.fill();
    cout << hex << setw(8) << setfill('0') << n << '\n';
    cout.flags(save_flags);
    cout.fill(save_fill);
}

int main() {
    showhex(100);
    cout << 42 << '\n';
}
00000064
42

Defining Your Own

It’s easy to define your own I/O manipulators:

ostream &dog(ostream &os) {
    return os << "Kokopelli";
}

int main() {
    cout << "My dog is " << dog << ".\n";
    return 0;
}
My dog is Kokopelli.

Of course, if that’s all you want:

const string dog = "Kokopelli";
cout << "My dog is " << dog << ".\n";
My dog is Kokopelli.

Better Example

ostream &bucks(ostream &os) {
    return os << fixed << setprecision(2);
}

int main() {
    cout << 34.5 << ' ' << bucks << 78.9 << '\n';
    return 0;
}
34.5 78.90