Frank
Frank

Reputation: 66164

Print leading zeros with C++ output operator?

How can I format my output in C++? In other words, what is the C++ equivalent to the use of printf like this:

printf("%05d", zipCode);

I know I could just use printf in C++, but I would prefer the output operator <<.

Would you just use the following?

std::cout << "ZIP code: " << sprintf("%05d", zipCode) << std::endl;

Upvotes: 88

Views: 110400

Answers (6)

paxdiablo
paxdiablo

Reputation: 881263

This will do the trick, at least for non-negative numbers(a) such as the ZIP codes(b) mentioned in your question.

#include <iostream>
#include <iomanip>

using namespace std;
cout << setw(5) << setfill('0') << zipCode << endl;

// or use this if you don't like 'using namespace std;'
std::cout << std::setw(5) << std::setfill('0') << zipCode << std::endl;

The most common IO manipulators that control padding are:

  • std::setw(width) sets the width of the field.
  • std::setfill(fillchar) sets the fill character.
  • std::setiosflags(align) sets the alignment, where align is ios::left or ios::right.

Note that these function affect the global state of the cout object. That means that doing this in one place will have unintended effects in later usages of std::cout, if you don't undo the manipulations!

And just on your preference for using <<, I'd strongly suggest you look into the fmt library (see https://github.com/fmtlib/fmt). This has been a great addition to our toolkit for formatting stuff and is much nicer than massively length stream pipelines, allowing you to do things like:

cout << fmt::format("{:05d}", zipCode);

The fmt::format functionality is included in C++20 as std::format.
C++23 brings std::print, which allows you to do std::print("{:05d}", zipCode); directly (with no need to go through cout).


(a) If you do need to handle negative numbers, you can use std::internal as follows:

cout << internal << setw(5) << setfill('0') << zipCode << endl;

This places the fill character between the sign and the magnitude.


(b) This ("all ZIP codes are non-negative") is an assumption on my part but a reasonably safe one, I'd warrant :-)

Upvotes: 122

vitaut
vitaut

Reputation: 55524

In C++20 you can do:

std::cout << std::format("{:05}", zipCode);

On older systems you can use the {fmt} library, std::format is based on.

Disclaimer: I'm the author of {fmt} and C++20 std::format.

Upvotes: 21

A P
A P

Reputation: 2548

Simple answer but it works!

ostream &operator<<(ostream &os, const Clock &c){
// format the output - if single digit, then needs to be padded with a 0
int hours = c.getHour();

// if hour is 1 digit, then pad with a 0, otherwise just print the hour
(hours < 10) ? os << '0' << hours : os << hours;

return os; // return the stream
}

I'm using a ternary operator but it can be translated into an if/else statement as follows

if(c.hour < 10){
 os << '0' << hours;
}
 else{
  os  << hours;
 }

Upvotes: 0

Jason Newland
Jason Newland

Reputation: 499

or,

char t[32];
sprintf_s(t, "%05d", 1);

will output 00001 as the OP already wanted to do

Upvotes: 2

Nik Reiman
Nik Reiman

Reputation: 40380

Use the setw and setfill calls:

std::cout << std::setw(5) << std::setfill('0') << zipCode << std::endl;

Upvotes: 15

anthony
anthony

Reputation: 41098

cout << setw(4) << setfill('0') << n << endl;

from:

http://www.fredosaurus.com/notes-cpp/io/omanipulators.html

Upvotes: 5

Related Questions