This question already has answers here:
Restore the state of std::cout after manipulating it
(9 answers)
Closed 4 years ago.
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?
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.
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);
}
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;
}
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
The null character will reset it back to the original state:
setfill('\0')
Related
If I write code like this:
int a = 123456;
cout << setw(20) << setiosflags(ios::right) << a << endl;
cout << setiosflags(ios::left) << setw(20) << a << '*' << endl;
On the 3rd line, I set the alignment as left align, so my expected output is
123456
123456 *
but the REAL output is
123456
123456*
Why did that happen?
The IDE I use is DevCpp.
std::setiosflags() sets new flags without clearing any existing flags. So on the 3rd line, you are enabling the ios::left flag without disabling the ios::right flag. It does not make sense to have both flags enabled at the same time, and it seems the stream prefers the ios::right flag if it is enabled.
Use std::left and std::right instead. They reset the ios::internal, ios::left, and ios::right flags before setting the new alignment.
int a = 123456;
cout << setw(20) << right << a << endl;
cout << left << setw(20) << a << '*' << endl;
Live demo
If you remove the line with setiosflags(ios::right), it works as expected, so it seems all common compilers evaluate right before left and short circuit the program flow. Try either manually unsetting ios::right, or better yet, just use std::left like so:
cout << left << setw(20) << a << '\n';
This, as so many standard library functions, takes care of pesky details.
int a = 123456;
cout.setf(ios::right, ios::adjustfield);
cout << setw(20) << a << endl;
cout.setf(ios::left, ios::adjustfield);
cout << setw(20) << a << '*' << endl;
If I recall, you need to reset the alignment.
The setiosflags sets format flag for the output stream (here it's cout), not for this sentence only. Since the ios::right has priority over ios::left, the second line will be aligned right. So you need to clear the previous format flag and then set the new one.
int a = 123456;
cout << setw(20) << setiosflags(ios::right) << a << endl;
cout << resetiosflags(ios::right) << setiosflags(ios::left) << setw(20) << a << '*' << endl;
But the simplest way is to use std::left and std::right
int a = 123456;
cout << setw(20) << right << a << endl;
cout << left << setw(20) << a << '*' << endl;
I'm trying to make a receipt, andbalways want the " kg" to be ONE SPACE after the weight, and also "$" just before both 'costperkg' and 'totacost' Initially using setw to format the output, could not get it to work, got it done with ostringstream. I Can anyone explain why does pushing double quote string does not work?
This one does not work :
int main()
{
string item = "A" ;
double weight = 2.00 ;
double costperkg = 1.98 ;
double totalcost = 3.96 ;
cout << fixed << showpoint << setprecision(2);
cout << setw(14) << left << "ITEM" << setw(16) << "WEIGHT" << setw(18) << "COST/kg"
<< setw(14) << "COST" << endl ;
cout << setw(14) << left << item << setw(16) << weight << "kg" << setw(18) << "$"
<< costperkg << setw(14) << "$" << totalcost << endl << endl ;
}
This one works:
ostringstream streamweight, streamcostperkg, streamtotalcost;
streamweight << fixed << showpoint << setprecision(2) << weight ;
streamcostperkg << fixed << showpoint << setprecision(2) << costperkg ;
streamtotalcost << fixed << showpoint << setprecision(2) << totalcost ;
string strweight = streamweight.str() + " kg" ;
string strcostperkg = "$" + streamcostperkg.str() ;
string strtotalcost = "$" + streamtotalcost.str() ;
cout << setw(14) << left << item << setw(16) << strweight << setw(18) << strcostperkg
<< setw(14) << strtotalcost << endl << endl ;
The expected result is :
ITEM WEIGHT COST/kg COST
A 2.0 kg $1.98 $3.96
What I got instead is :
ITEM WEIGHT COST/kg COST
A 2.00 kg$ 1.98$ 3.96
Why does the setw one not work? and also for those viewing on phone, the first character from first and second life of every word should align on the first letter (A, 2, $, $)
OP suspected the std::setw() not to work. IMHO, OP is not aware that the setw() does exactly what's expected but the formatting considers as well the std::left manipulator which makes all following output left aligned. (The left alignment becomes effective in combination with setw() only.)
Example:
#include <iostream>
#include <iomanip>
// the rest of sample
int main()
{
std::cout << '|' << std::setw(10) << 2.0 << "|kg" << '\n';
std::cout << std::left << '|' << std::setw(10) << 2.0 << "|kg" << '\n';
// done
return 0;
}
Output:
| 2|kg
|2 |kg
Live Demo on coliru
(A possible fix is exposed in the question by OP her/himself.)
My Code:
#include <iostream>
#include <iomanip>
using namespace std;
int main () {
int time;
int honolulu, seattle, london, moscow, hongkong, auckland;
cout << "What is the current time in Philadelphia? ";
cin >> time;
honolulu = (time+2400-600)%2400;
seattle = (time+2400-300)%2400;
london = (time+2400+500)%2400;
moscow = (time+2400+800)%2400;
hongkong = (time+2400+1200)%2400;
auckland = (time+2400+1700)%2400;
cout << endl << "Current times in other cities: " << endl;
cout << setw (12) << left << "Honolulu:";
cout << setw (4) << setfill('0') << honolulu << endl;
cout << setw (12) << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;
cout << setw (12) << left << "London:";
cout << setw (4) << setfill('0') << london << endl;
cout << setw (12) << left << "Moscow:";
cout << setw (4) << setfill('0') << moscow << endl;
cout << setw (12) << left << "Hong Kong:";
cout << setw (4) << setfill('0') << hongkong << endl;
cout << setw (12) << left << "Auckland:";
cout << setw (4) << setfill('0') << auckland << endl;
return 0;
}
Required Output :
What is the current time in Philadelphia? 0415
Current times in other cities:
Honolulu: 2215
Seattle: 1150
London: 9150
Moscow: 1215
Hong Kong: 1615
Auckland: 2115
My output :
What is the current time in Philadelphia? 0415
Current times in other cities:
Honolulu: 2215
Seattle:00001150
London:000009150
Moscow:000001215
Hong Kong:001615
Auckland:0002115
What am I doing wrong? The first line of output, Honolulu: 2215, is correct. But the next lines have leading zeroes. I do not understand why this is happening? Is there a problem with my code or am I misunderstanding how the functions setfill and setw work?
The fill character is "sticky", so it remains in effect until you change it.
In your case, you want 0 as the fill for the numeric fields, but space as the fill for the character fields, so you'll have to set that explicitly, something like this:
cout << setfill(' ') << setw (12) << left << "Seattle:";
Many of the iomanip objects are "sticky", that is, they stick to the stream and affect subsequent lines.
When you have this:
cout << setw (12) << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;
that is going to leave the setfill active for the next line. So you might instead prefer
cout << setw (12) << setfill(' ') << left << "Seattle:";
cout << setw (4) << setfill('0') << seattle << endl;
As mentioned in other comments many of I/O manipulators are "sticky".
I personally prefer to solve this kind of problem using RAII:
class stream_format_raii {
public:
stream_format_raii(std::ostream &stream)
: stream_(stream)
, state_(NULL) {
state_.copyfmt(stream_);
}
~stream_format_raii() {
stream_.copyfmt(state_);
}
public:
std::ostream &stream_;
std::ios state_;
};
That this class does is backing up your current stream's format upon constructing and setting it back upon destructing.
You can use it this way:
void printCity(std::ostream &os, const std::string name, int time) {
stream_format_raii back(os);
os << std::setw(12) << std::left << (name + ":");
os << std::setw(4) << std::setfill('0') << time;
}
int main() {
// Same as before
printCity(std::cout, "Honolulu", honolulu);
// Same as before
}
I need to write a program for a homework assignment to calculate tuition costs and the output should be formatted like so with the dot padding and space padding after the dollar sign:
Student Name: Name goes here
Address: Address goes here
Number of credits: .......... 5
Cost per credit hour: ............ $ 50
My code so far is:
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
using namespace std;
double const REG_FEE = 700, STUDENT_ASSEMBLY_FEE = 7.19, LEGAL_FEE = 8.50, STUDGOV_FEE = 1.50,
LATE_FEE_PERCENTAGE = 0.015;
int main()
{ double num_credits, cost_per_credit, tuition_total, late_charge, amount_due;
string student_name;
string student_address;
string student_city_state_ZIP;
ifstream info;
info.open ("info.txt");
getline (info, student_name);
getline (info, student_address);
getline (info, student_city_state_ZIP);
info >> num_credits;
info >> cost_per_credit;
tuition_total = num_credits * cost_per_credit + REG_FEE + STUDENT_ASSEMBLY_FEE + LEGAL_FEE
+ STUDGOV_FEE;
late_charge = tuition_total * LATE_FEE_PERCENTAGE;
amount_due = tuition_total + late_charge;
cout << "Tuition and Billing Program by Neal P." << endl
<< setw(18) << "Student Name:" << student_name << endl
<< setw(18) << "Address:" << student_address << endl
<< left << setfill('.') << endl
<< setfill(18) << "Number of Credits:" << setw(5) << "$" << num_credits << endl
<< setfill(18) << "Cost per Credit Hour:" << setw(5) << "$" << cost_per_credit << endl
<< setfill(18) << "Tuition Cost:" << setw(5) << "$" << tuition_total << endl
<< setfill(18) << "Registration Fee:" << setw(5) << "$" << REG_FEE << endl
<< setfill(18) << "MSA Fee:" << setw(5) << "$" << STUDENT_ASSEMBLY_FEE << endl
<< setfill(18) << "Legal Services Fee:" << setw(5) << "$" << LEGAL_FEE << endl
<< setfill(18) << "Student Government Fee:" << setw(5) << "$" << STUDGOV_FEE << endl;
return 0;
}
When I compile I get a very long error, something like : "In function ‘int main()’:
/Users/nealp/Desktop/machine problem 2.cpp:41: error: no match for ‘operator<<’ in ‘((std::basic_ostream >*)std::operator<< [with _CharT = char, _Traits = std::char_traits](((std::basic_ostream >&)((std::basic_ostream >*)((std::basic_ostream >*)((std::basic_ostream >*)std::operator<<" that continues.
Is this an issue with my use of both setw and setfill together? I know that setfill only has to be declared once and setw is only effective on the next line output, but I defined setfill each time because I was using setw before it.
std::setfill is a function template and it's template argument gets deduced based on the type of the argument you pass it to. It's return type is unspecified - it's some implementation defined proxy type that sets fill character on the stream object and enables further chaining of operator<< calls. It's also dependent on the type that setfill gets instantiated with.
The type of literal 18 is int so setfill returns some unrelated type for which there's no operator<< avaliable.
I'm not sure what you meant with setfill(18), I'm guessing you've mistaken it for setw(18).
Just replace setfill(18) in your code, that is the reason for compilation error.
Here is the improved printing portion to fit the requirements,
cout << "Tuition and Billing Program by Neal P." << endl
<< "Student Name:" << student_name << endl
<< "Address:" << student_address << endl
<<endl<<endl<< "Number of Credits:" << setfill('.') << setw(5) <<"$" << num_credits
<< endl<< "Cost per Credit Hour:"<<setfill('.')<<setw(5)<< "$" << cost_per_credit <<
endl<< "Tuition Cost:" << setfill('.')<<setw(5)<< "$" << tuition_total << endl
<< "Registration Fee:" << setfill('.')<<setw(5) << "$" << REG_FEE << endl
<< "MSA Fee:" << setfill('.')<<setw(5) << "$" << STUDENT_ASSEMBLY_FEE << endl
<< "Legal Services Fee:" << setfill('.')<<setw(5) << "$" << LEGAL_FEE << endl
<< "Student Government Fee:" << setfill('.')<<setw(5) << "$" << STUDGOV_FEE << endl;
I am trying to use setw to clean up the output of my program. I want the empty spaces in between "total number of spools to be ordered" and the output.
EDIT this is what im going for:
and this is what I get
here is what I have so far:
UPDATED CODE
/********************************************/
// Name: results /
// Description: Print results /
// Parameters: N/A /
// Reture Value: N/A /
/********************************************/
void results(int spoolnumber, int subtotalspool, float shippingcost, float totalcost)
{
cout << left << setw (45) << "Total number of spools to be ordered is: " << right << spoolnumber << endl << endl;
cout << left << setw (45) << "The subtotal for the spools is:" << right << "$" << subtotalspool << endl << endl;
cout << "The shipping cost is: $" << shippingcost << endl << endl;
cout << "The total cost is: $" << totalcost << endl << endl;
return;
}
You can also do
cout << left << setw (45) << "Total number of spools to be ordered is: " << spoolnumber << endl << endl;
to choose which side the padding goes. The default is left.
EDIT: using stringstream
stringstream ss;
ss << "$" << spoolnumber
I think you can fix the right end by adding another setw. So:
cout << left << setw (45) << "Total number of spools to be ordered is: " << right << setw(5) << ss.str() << endl << endl;