How to format right and left justification on the same line? - c++

If I am making a data table to show the results of several functions, how can I use the setw(), left, and right keywords to create a table which is formatted like this:
Height 8
Width 2
Total Area 16
Total Perimeter 20
Notice how the overall "width" of the table is constant (about 20 spaces). But the elements on the left are left justified and the values on the right are right justified.

#include <iostream>
#include <string>
#include <vector>
#include <iomanip>
struct Result
{
std::string Name;
int Value;
};
int main()
{
std::vector<Result> results = { {"Height", 8}, {"Width", 2}, {"Total Area", 16}, {"Total Perimeter", 20} };
for (auto result : results)
{
std::cout << std::setw(16) << std::left << result.Name;
std::cout << std::setw(4) << std::right << result.Value << std::endl;
}
return 0;
}

You could do something like this:
// "Total Perimiter" is the longest string
// and has length 15, we use that with setw
cout << setw(15) << left << "Height" << setw(20) << right << "8" << '\n';
cout << setw(15) << left << "Width" << setw(20) << right << "2" << '\n';
cout << setw(15) << left << "Total Area" << setw(20) << right << "16" << '\n';
cout << setw(15) << left << "Total Perimeter" << setw(20) << right << "20" << '\n';

Related

Cpp/C++ Output allingment in one line from right AND left

I need to write ints from the right and strings from the left into a single line and have them line up properly (view output below the code).
Basically I just need a way to write a table only using iostream and iomanip and change the allingment from right for ints to left for strings and back.
Other tips are also appreciated :)
#include <iostream>
#include <iomanip>
using namespace std;
class foo
{
public:
int i;
std::string s;
int j;
foo(int i1,std::string s1,int j1) : i(i1), s(s1),j(j1) {};
};
int main()
{
foo f1(1, "abc",50);
foo f2(100, "abcde",60);
cout << resetiosflags(ios::adjustfield);
cout << setiosflags(ios::right);
cout << setw(6) << "i" << setw(15) << "s" << setw(15) << "j"<<endl;
cout << setw(8) << f1.i << setw(15)
<< resetiosflags(ios::adjustfield) << setiosflags(ios::left) << f1.s <<setw(5)
<< resetiosflags(ios::adjustfield) << setiosflags(ios::right) << setw(15) << f1.j << endl;
cout << setw(8) << f2.i << setw(15)
<< resetiosflags(ios::adjustfield) << setiosflags(ios::left) << f2.s <<setw(5
<< resetiosflags(ios::adjustfield) << setiosflags(ios::right) << setw(15) << f2.j << endl;
/*i s j
1abc 50
100abcde 60*/
return 0;
}
This is the output:
i s j
1abc 50
100abcde 60
And this is what i need:
i s j
1 abc 50
100 abcde 60
Using left and right in the same line isn't a problem. It looks like the issue you have is not allowing for space after the first value. It looks like the setw(5) may have been for that, but since there's nothing printed after it there's no effect. I used 7 to match the 15 total used for the string width.
Maybe something like this would work? Probably best to extract the magic numbers into constants so you can adjust all of them easily in one place. You could also wrap this in an operator<< to contain all the formatting code in one place.
The first line headings offset one to the left looks weird to me, but it matches your example and is easy to adjust if necessary.
#include <iostream>
#include <iomanip>
using namespace std;
class foo
{
public:
int i;
std::string s;
int j;
foo(int i1, std::string s1, int j1) : i(i1), s(s1), j(j1)
{};
};
int main()
{
foo f1(1, "abc", 50);
foo f2(100, "abcde", 60);
cout
<< right << setw(7) << "i" << setw(7) << ' '
<< left << setw(15) << "s"
<< right << "j"
<< endl;
cout
<< right << setw(8) << f1.i << setw(7) << ' '
<< left << setw(15) << f1.s
<< right << f1.j
<< endl;
cout
<< right << setw(8) << f2.i << setw(7) << ' '
<< left << setw(15) << f2.s
<< right << f2.j
<< endl;
return 0;
}
Output:
i s j
1 abc 50
100 abcde 60

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

Aligning the left most character of each value in a column

For a lab of mine we need to display the output values in a column following a statement of what the value is for.
Example of what I need.
Amount of adult tickets: 16
Amount of children tickets: 12
Revenue from ticket sales: $140.22
I am trying to use setw like
cout << "Amount of adult tickets: " << setw(15) << ticketsAdult` << endl;
cout << "Amount of children tickets: " << setw(15) < ticketsChildren << endl;
I'm assuming either setw is the wrong thing to use for this or I'm using it wrong as it usually results in something like
Amount of adult tickets: 16
Amount of children tickets: 12
What can I use to make the values to the right all align like they did in the example no matter the length of the "Amount of..." statements before each of them?
It looks like there is right and left alignment too. Other than that it looks like it's a pain to use.
C++ iomanip Alignment
Combining everything said together
#include <iostream>
#include <iomanip>
int main()
{
int ticketsAdult = 16;
int ticketsChildren = 12;
double rev =140.22;
std::cout << std::setw(35) << std::left << "Amount of adult tickets: " << ticketsAdult << '\n';
std::cout << std::setw(35) << std::left << "Amount of children tickets: " << ticketsChildren << '\n';
std::cout << std::setw(35) << std::left << "Revenue from ticket sales: " << '$' << rev << '\n';
return 0;
}

C++ Iomanip lib setfill and setw issues

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
}

Having trouble with iomanip, columns not lining up the way I expect

finishing up a long project and the final step is to make sure my data lines up in the proper column. easy. Only I am having trouble with this and have been at it for longer than i wish to admit watching many videos and can't really grasp what the heck to do So here is a little snippet of the code that I'm having trouble with:
#include <iostream>
#include <iomanip>
using namespace std;
int main(){
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << "Student Final Final Letter\n";
cout << "Name Exam Avg Grade\n";
cout << "----------------------------------------------------------------\n";
cout << "bill"<< " " << "joeyyyyyyy" << right << setw(23)
<< "89" << " " << "21.00" << " "
<< "43" << "\n";
cout << "Bob James" << right << setw(23)
<< "89" << " " << "21.00" << " "
<< "43" << "\n";
}
which works for the first entry but the bob james entry has the numbers all askew. I thought setw was supposed to allow you to ignore that? What am i missing?
Thanks
It doesn't work as you think. std::setw sets the width of the field only for the next insertion (i.e., it is not "sticky").
Try something like this instead:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << left << setw(42) << "Student" // left is a sticky manipulator
<< setw(8) << "Final" << setw(6) << "Final"
<< "Letter" << "\n";
cout << setw(42) << "Name"
<< setw(8) << "Exam" << setw(6) << "Avg"
<< "Grade" << "\n";
cout << setw(62) << setfill('-') << "";
cout << setfill(' ') << "\n";
cout << setw(42) << "bill joeyyyyyyy"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
cout << setw(42) << "Bob James"
<< setw(8) << "89" << setw(6) << "21.00"
<< "43" << "\n";
}
Also related: What's the deal with setw()?
The manipulators << right << setw(23) are telling the ostream that you want
the string "89" set in the right-hand edge of a 23-character-wide field.
There is nothing to tell the ostream where you want that field to start,
however, except for the width of the strings that are output since the
last newline.
And << "bill"<< " " << "joeyyyyyyy" writes a lot more characters to the output
than << "Bob James" does, so the 23-character-wide field on the second line
starts quite a bit to the left of the same field on the first line.
Stream manipulators affect the next input/output value being streamed, and then some manipulators (including setw()) reset afterwards. So you need to set the width and alignment BEFORE you output a text string, not afterwards.
Try something more like this:
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
void outputStudent(const string &firstName, const string &lastName,
int finalExam, float finalAvg, int letterGrade)
{
cout << setw(40) << left << (firstName + " " + lastName) << " "
<< setw(6) << right << finalExam << " "
<< setw(6) << right << fixed << setprecision(2) << finalAvg << " "
<< setw(7) << right << letterGrade << "\n";
}
int main()
{
cout << "Student Grade Summary\n";
cout << "---------------------\n\n";
cout << "BIOLOGY CLASS\n\n";
cout << "Student Final Final Letter\n";
cout << "Name Exam Avg Grade\n";
cout << "--------------------------------------------------------------\n";
outputStudent("bill", "joeyyyyyyy", 89, 21.00, 43);
outputStudent("Bob", "James", 89, 21.00, 43);
cin.get();
return 0;
}
Output:
Student Grade Summary
---------------------
BIOLOGY CLASS
Student Final Final Letter
Name Exam Avg Grade
--------------------------------------------------------------
bill joeyyyyyyy 89 21.00 43
Bob James 89 21.00 43