I have the next code:
ofstream dataIndex;
dataIndex.open("file");
index="2222";
std::stringstream sstr1;
sstr1<<index<<'1';
sstr1<<setfill('0')<<setw(index.length()-9);
string index1= sstr1.str();
dataIndex<<index1;
dataIndex.close()
and i hope the result:
2222100000
but only i get
22221
without zeros? what happened?
Use std::left to left justify the output
#include <iostream>
#include <string>
#include <iomanip>
int main()
{
std::string s( "2222" );
std::cout << std::setw(9)
<< std::setfill('0')
<< std::left
<< s
<< std::endl;
}
Output:
222200000
manipulators are applied to the stream the same as input. For them to take effect they need to be applied first. For example here is how you would fill zeros on a string stream.
std::string index("2222");
std::ostringstream sstr1;
sstr1 << std::setw(9) << std::setfill('0') << index << '1';
std::cout << sstr1.str(); // 0000022221
If you want to fill differently then simply add in a direction manipulator like std::left, std::right, etc.
std::string index("2222");
std::ostringstream sstr1;
sstr1 << index << std::setw(10-index.length()) << std::setfill('0') << std::left << '1';
std::cout << sstr1.str(); // 2222100000
Your setw() manipulator is invoked with a negative number (the length of Index string is just 4). That might be the culprit.
Related
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;
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.
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);
And it's currently being targeted by LEWG toward C++20 as well, meaning it will hopefully be a base part of the language at that point (or almost certainly later if it doesn't quite sneak in).
(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 :-)
Use the setw and setfill calls:
std::cout << std::setw(5) << std::setfill('0') << zipCode << std::endl;
In C++20 you'll be able to do:
std::cout << std::format("{:05}", zipCode);
In the meantime you can use the {fmt} library, std::format is based on.
Disclaimer: I'm the author of {fmt} and C++20 std::format.
cout << setw(4) << setfill('0') << n << endl;
from:
http://www.fredosaurus.com/notes-cpp/io/omanipulators.html
or,
char t[32];
sprintf_s(t, "%05d", 1);
will output 00001 as the OP already wanted to do
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;
}
How do I create a stringstream with a fixed length, filled with a single character?
Desired output:
[xxxxxxxxxx]
I've tried this:
#include <iostream>
#include <iomanip>
using namespace std;
int main () {
stringstream ss;
ss << setfill('x') << setw(10);
cout << "[" << ss.str() << "]\n";
return 0;
}
output:
[]
If I add anything to the stream after I set the width and fill, I get filled stream, which is what I am looking for:
ss << setfill('x') << setw(10) << "B";
output:
[xxxxxxxxxB]
But I want a stream the stream to be filled with just x Is there any way to get the filled stream without needing to add a value to it?
setw and setfill are only used to set width and fill parameters of your stream, so it is normal that
ss << setfill('x') << setw(10);
doesn't work (you don't output anything).
You may want to do something like
ss << setfill('x') << setw(10) << 'x';
which gives
[xxxxxxxxxx]
as you wanted.
You could just use the appropriate string constructor to fill the stream, like this
ss << std::string(10, 'x');
I often do something like:
uint8_t c=some_value;
std::cout << std::setfill('0') << std::setw(2);
std::cout << std::hex << int(c);
std::cout << std::setfill(' ');
(in particular while dumping debugging information). Wouldn't it be nice to have something manipulatorish that I could put in a stream like this:
std::cout << "c value: 0x" << hexb(c) << '\n';
that would do all of that? Does anyone know how to do that?
I've gotten this to work but would love to have a simpler way:
#include <iostream>
#include <iomanip>
class hexcdumper{
public:
hexcdumper(uint8_t c):c(c){};
std::ostream&
operator( )(std::ostream& os) const
{
// set fill and width and save the previous versions to be restored later
char fill=os.fill('0');
std::streamsize ss=os.width(2);
// save the format flags so we can restore them after setting std::hex
std::ios::fmtflags ff=os.flags();
// output the character with hex formatting
os << std::hex << int(c);
// now restore the fill, width and flags
os.fill(fill);
os.width(ss);
os.flags(ff);
return os;
}
private:
uint8_t c;
};
hexcdumper
hexb(uint8_t c)
{
// dump a hex byte with width 2 and a fill character of '0'
return(hexcdumper(c));
}
std::ostream& operator<<(std::ostream& os, const hexcdumper& hcd)
{
return(hcd(os));
}
When I do this:
std::cout << "0x" << hexb(14) << '\n';
hexb(c) is invoked and returns a hexcdumper whose constructor saves c
the overloaded operator<< for hexcdumper invokes
hexcdumper::operator() passing it the stream
hexcdumper's operator() does all the magic for us
after hexcdumper::operator() returns, the overloaded operator<<
returns the stream as returned from hexcdumper::operator() so chaining works.
On the output, I see:
0x0e
Is there a simpler way to do this?
Patrick
You can do this directly on the stream pipe:
std::cout << "Hex = 0x" << hex << 14 << ", decimal = #" << dec << 14 << endl;
Output:
Hex = 0xe, decimal = #14
I would like to print a bunch of integers on 2 fields with '0' as fill character. I can do it but it leads to code duplication. How should I change the code so that the code duplication can be factored out?
#include <ctime>
#include <sstream>
#include <iomanip>
#include <iostream>
using namespace std;
string timestamp() {
time_t now = time(0);
tm t = *localtime(&now);
ostringstream ss;
t.tm_mday = 9; // cheat a little to test it
t.tm_hour = 8;
ss << (t.tm_year+1900)
<< setw(2) << setfill('0') << (t.tm_mon+1) // Code duplication
<< setw(2) << setfill('0') << t.tm_mday
<< setw(2) << setfill('0') << t.tm_hour
<< setw(2) << setfill('0') << t.tm_min
<< setw(2) << setfill('0') << t.tm_sec;
return ss.str();
}
int main() {
cout << timestamp() << endl;
return 0;
}
I have tried
std::ostream& operator<<(std::ostream& s, int i) {
return s << std::setw(2) << std::setfill('0') << i;
}
but it did not work, the operator<< calls are ambigous.
EDIT I got 4 awesome answers and I picked the one that is perhaps the simplest and the most generic one (that is, doesn't assume that we are dealing with timestamps). For the actual problem, I will probably use std::put_time or strftime though.
In C++20 you'll be able to do this with std::format in a less verbose way:
ss << std::format("{}{:02}{:02}{:02}{:02}{:02}",
t.tm_year + 1900, t.tm_mon + 1, t.tm_mday,
t.tm_hour, t.tm_min, t.tm_sec);
and it's even easier with the {fmt} library that supports tm formatting directly:
auto s = fmt::format("{:%Y%m%d%H%M%S}", t);
You need a proxy for your string stream like this:
struct stream{
std::ostringstream ss;
stream& operator<<(int i){
ss << std::setw(2) << std::setfill('0') << i;
return *this; // See Note below
}
};
Then your formatting code will just be this:
stream ss;
ss << (t.tm_year+1900)
<< (t.tm_mon+1)
<< t.tm_mday
<< t.tm_hour
<< t.tm_min
<< t.tm_sec;
return ss.ss.str();
ps. Note the general format of my stream::operator<<() which does its work first, then returns something.
The "obvious" solution is to use a manipulator to install a custom std::num_put<char> facet which just formats ints as desired.
The above statement may be a bit cryptic although it entirely describes the solution. Below is the code to actually implement the logic. The first ingredient is a special std::num_put<char> facet which is just a class derived from std::num_put<char> and overriding one of its virtual functions. The used facet is a filtering facet which looks at a flag stored with the stream (using iword()) to determine whether it should change the behavior or not. Here is the code:
class num_put
: public std::num_put<char>
{
std::locale loc_;
static int index() {
static int rc(std::ios_base::xalloc());
return rc;
}
friend std::ostream& twodigits(std::ostream&);
friend std::ostream& notwodigits(std::ostream&);
public:
num_put(std::locale loc): loc_(loc) {}
iter_type do_put(iter_type to, std::ios_base& fmt,
char fill, long value) const {
if (fmt.iword(index())) {
fmt.width(2);
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, '0', value);
}
else {
return std::use_facet<std::num_put<char> >(this->loc_)
.put(to, fmt, fill, value);
}
}
};
The main part is the do_put() member function which decides how the value needs to be formatted: If the flag in fmt.iword(index()) is non-zero, it sets the width to 2 and calls the formatting function with a fill character of 0. The width is going to be reset anyway and the fill character doesn't get stored with the stream, i.e., there is no need for any clean-up.
Normally, the code would probably live in a separate translation unit and it wouldn't be declared in a header. The only functions really declared in a header would be twodigits() and notwodigits() which are made friends in this case to provide access to the index() member function. The index() member function just allocates an index usable with std::ios_base::iword() when called the time and it then just returns this index. The manipulators twodigits() and notwodigits() primarily set this index. If the num_put facet isn't installed for the stream twodigits() also installs the facet:
std::ostream& twodigits(std::ostream& out)
{
if (!dynamic_cast<num_put const*>(
&std::use_facet<std::num_put<char> >(out.getloc()))) {
out.imbue(std::locale(out.getloc(), new num_put(out.getloc())));
}
out.iword(num_put::index()) = true;
return out;
}
std::ostream& notwodigits(std::ostream& out)
{
out.iword(num_put::index()) = false;
return out;
}
The twodigits() manipulator allocates the num_put facet using new num_put(out.getloc()). It doesn't require any clean-up because installing a facet in a std::locale object does the necessary clean-up. The original std::locale of the stream is accessed using out.getloc(). It is changed by the facet. In theory the notwodigits could restore the original std::locale instead of using a flag. However, imbue() can be a relatively expensive operation and using a flag should be a lot cheaper. Of course, if there are lots of similar formatting flags, things may become different...
To demonstrate the use of the manipulators there is a simple test program below. It sets up the formatting flag twodigits twice to verify that facet is only created once (it would be a bit silly to create a chain of std::locales to pass through the formatting:
int main()
{
std::cout << "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits1='" << 1 << "' "
<< "two-digits2='" << 2 << "' "
<< "two-digits3='" << 3 << "' "
<< notwodigits << '\n'
<< "some-int='" << 1 << "' "
<< twodigits << '\n'
<< "two-digits4='" << 4 << "' "
<< '\n';
}
Besides formatting integers with std::setw / std::setfill or ios_base::width / basic_ios::fill, if you want to format a date/time object you may want to consider using std::put_time / std::gettime
For convenient output formatting you may use boost::format() with sprintf-like formatting options:
#include <boost/format.hpp>
#include <iostream>
int main() {
int i1 = 1, i2 = 10, i3 = 100;
std::cout << boost::format("%03i %03i %03i\n") % i1 % i2 % i3;
// output is: 001 010 100
}
Little code duplication, additional implementation effort is marginal.
If all you want to do is output formatting of your timestamp, you should obviously use strftime(). That's what it's made for:
#include <ctime>
#include <iostream>
std::string timestamp() {
char buf[20];
const char fmt[] = "%Y%m%d%H%M%S";
time_t now = time(0);
strftime(buf, sizeof(buf), fmt, localtime(&now));
return buf;
}
int main() {
std::cout << timestamp() << std::endl;
}
operator<<(std::ostream& s, int i) is "ambiguous" because such a function already exists.
All you need to do is give that function a signature that doesn't conflict.
I'm trying to learn to use namespaces declarations more definitive than not just say "using namespace std". I'm trying to format my data to 2 decimal places, and set the format to be fixed and not scientific. This is my main file:
#include <iostream>
#include <iomanip>
#include "SavingsAccount.h"
using std::cout;
using std::setprecision;
using std::ios_base;
int main()
{
SavingsAccount *saver1 = new SavingsAccount(2000.00);
SavingsAccount *saver2 = new SavingsAccount(3000.00);
SavingsAccount::modifyInterestRate(.03);
saver1->calculateMonthlyInterest();
saver2->calculateMonthlyInterest();
cout << ios_base::fixed << "saver1\n" << "monthlyInterestRate: " << saver1->getMonthlyInterest()
<< '\n' << "savingsBalance: " << saver1->getSavingsBalance() << '\n';
cout << "saver2\n" << "monthlyInterestRate: " << saver2->getMonthlyInterest()
<< '\n' << "savingsBalance: " << saver2->getSavingsBalance() << '\n';
}
On Visual Studio 2008, when I run my program, I get an output of "8192" before the data I want. Is there a reason for that?
Also, I don't think I am setting the fixed part or 2 decimal places correctly since I seem to get scientific notation once I added the setprecision(2). Thanks.
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';
}
It might not be the answer you're looking for, but floating-point numbers are not suited to financial calculations because fractions like 1/100 cannot be represented exactly. You might be better off doing the formatting yourself. This can be encapsulated:
class money {
int cents;
public:
money( int in_cents ) : cents( in_cents ) {}
friend ostream &operator<< ( ostream &os, money const &rhs )
{ return os << '$' << m.cents / 100 << '.' << m.cents % 100; }
};
cout << money( 123 ) << endl; // prints $1.23
Better(?) yet, C++ has a facility called the monetary locale category which includes a money formatter which takes cents as an argument.
locale::global( locale("") );
use_facet< money_put<char> >( locale() ).put( cout, false, cout, ' ', 123 );
This should Do the Right thing internationally, printing the user's local currency and hiding the number of decimal places from your implementation. It even accepts fractions of a cent. Unfortunately, this does not seem to work on my system (Mac OS X), which has generally poor locale support. (Linux and Windows should fare better.)
cout << setiosflags(ios::fixed) << setprecision(2) << 1/3.;
ios_base::fixed is not manipulator it is a value (1 << 13) for the ios flag.