can't get setw to line up - c++

I'm not sure how to go about lining this up better. I thought by using L = name.length(); and subtracting that from the setw it would line up better but nope. I have name and ID set correctly but I can't seem to get the rest to line up. These are floats btw.
for (int z=0; z<i ;z++){
if( EInfo[z].valid >0){
string name = employee[z].getName();
int L = name.length();
payReportObj << fixed << setprecision (2) << endl;
payReportObj << setw(3) << employee[z].getID()
<< setw(36)
<< employee[z].getName()
<< setw(30-L) << "$" << setw(4) << EInfo[z].grossPaySE
<< setw(25) << "$" << setw(4) << EInfo[z].taxSE
<< setw(15) << "$" << setw(4) << EInfo[z].insuranceSE
<< setw(25) << "$" << setw(4) << EInfo[z].netPaySE;
I'm attempting to get it more like this...
This is what I have...

Replace setw(30-L) with setw(30). And this:
int L = name.length();
is not needed. If you want to right-align numbers, use std::right.
It seams that you opened your output file in nodepad with proportional font. You won't see columns aligned with proportional font even if they are. Change font to fixed or type in your terminal type output.txt.

Related

Use cout to print a number in a certain format (left align & right align)

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;

Interaction between setw and double quoted string character

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.)

How do I properly format this table?

I'm trying to properly format a table so that it prints out values below each column, beginning with the first character of that column. I've had success formatting three columns, but I'm unable to figure out how to format the K Count and LM Count columns so that they are printed out in a neat fashion.
What are some corrections I can make to the while loop portion of the code so that the K count and LM count columns are printed out neatly?
void printTable(const vector<int>& z, const vector<long>& x, const
vector<long>& y,
const vector<int>& a, const vector<int>& b)
{
ostringstream ss;
ss << "\n\n\n" << setw(10) << left << "Digits" << "Input Numbers "
<< setw(11) << right << "K Output " << setw(6)
<< right << "K Count " << setw(10) << right << "LM Output " << setw(6)
<< right << "LM Count" << endl;
int i = 0, n = 0;
while (i < 5)
{
string q = to_string(z[2*n]) + " x " + to_string(z[abs(2*n + 1)]);
string r = to_string(x[i]);
string s = to_string(a[i]);
string t = to_string(y[i]);
string u = to_string(b[i]);
ss << setw(10) << left << (i+1) << q
<< setw(16) << right << r
<< setw(11) << right << s
<< setw(12) << right << t
<< setw(10) << right << u << endl;
i++;
n++;
}
string r = ss.str();
cout << r;
}
You're printing the following:
- Digits left aligned over 10 chars
- Directly followed by the input number without specifying the width
- K output right aligned over 16 chars
You should instead specify the width of the input numbers as well.
Try this:
ss << setw(10) << left << (i+1) <<
setw(16) << left << q <<
setw(10) << right << s <<
setw(12) << right << t <<
...
The exact width of each column may not be correct. Try it out yourself.
To fix K Count output, you should reset the cursor to align left after setting the width for the previous result, then shift back right. Something like this should do what you want.
ss << setw(10) << left << (i+1) << right
setw(16) << left << q << right <<
setw(11) << left << r << right <<
setw(12) << left << s << right <<
setw(12) << left << t << right <<
setw(10) << left << u << right << endl;

Dynamic alignment issue

When I try to list details of all items, each on a different line
with line numbering, there is alignment issue on it. I want instantly put the close bracket after the line numbering. Thanks.
cout << left
<< setw(20) << " Item Code"
<< setw(50) << "Description"
<< setw(20) << "Quantity on hand"
<< setw(20) << "Cost price"
<< setw(20) << "Selling price(RM)"
<< setw(20) << "Status"
<< setw(20) << "Discount(%)" << endl;
for (int i = 0; i <= 100; i++)//counter - 1; i++)
{
cout << left
<< setw(2) << i + 1 << ")"
<< setw(20) << item[i].getItemCode()
<< setw(50) << item[i].getDescription()
<< setw(20) << item[i].getQuantity()
<< setw(20) << item[i].getCostPrice()
<< setw(20) << item[i].getSellPrice()
<< setw(20) << item[i].getStatus()
<< setw(20) << item[i].getDiscount() << endl;
}
The only way of doing this, as far as I can see, is to walk through the list and find out "how long does this get" for each of the columns, and track what the largest is for each of the columns. Then use those values in the column width.
Strings are easy to find the length of, since they have a length as such. Numbers are harder - basically, you have to either take the approach of dividing it by ten down until it's zero (this means the integer part of floating point numbers - presumably for something like this, you have a fixed number of decimals or use "integeer to represent prices in cents" or some such). You may be able to use the std::tostring to produce as string that has a length too. Or you can use stringstream to output to a string - either individual items, or the whole lot and then count the number of characters between some separator character [that doesn't occur in the normal output, or things go wrong pretty easily!]
Example, using a simple struct:
struct Data
{
int x;
string y;
float z;
}
...
Data d[10];
int maxLen[3] = { 0 };
... // code fills in data with stuff.
for(int i = 0; i < 10; i++)
{
stringstream ss;
ss << left << d[i].x << " " << d[i].y << " " << fixed << setprecision(2) << d[i].z;
// Number of elements = 3.
for(int j = 0; j < 3; j++)
{
string s;
ss >> s;
if (s.length() > maxLen[j])
maxLen[j] = s.legnth;
}
}
...
for(int i = 0; i < 10; i++)
{
cout << left << setw(3) i << ": "
<< setw(maxLen[0]+1) << d[i].x
<< setw(maxLen[1]+1) << d[i].y
<< setw(maxLen[2]+1) << fixed << setprecision(2) << d[i].z << endl;
}

C++ - How to reset the output stream manipulator flags [duplicate]

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')