So i'm just starting to learn c++ and i'm curious if its a way to formate your output with cout so it will look nicely and structured in columns
for example.
string fname = "testname";
string lname = "123";
double height = 1.6;
string fname2 = "short";
string lname2 = "123";
double height2 = 1.8;
cout << "Name" << setw(30) << "Height[m]" << endl;
cout << fname + " " + lname << right << setw(20) << setprecision(2) << fixed << height << endl;
cout << fname2 + " " + lname2 << right << setw(20) << setprecision(2) << fixed << height2 << endl
The output looks like this:
Name Height[m]
testname 123 1.60
short 123 1.80
I want it to look like this:
Name Height[m]
testname 123 1.60
short 123 1.80
The problem i'm trying to solve is that i want to place height at a specific position from name but depending what length of name i take the value of height either gets far away to the right or will be very close to the left. Is there a way to fix this?
First of all, with an output stream like std::cout
, you cannot travel back in time and modify output which was already performed. That makes sense -- just imagine std::cout
wrote into a file because you launched your program with program.exe > test.txt
, and test.txt
was on a USB drive which has been disconnected in the meanwhile...
So you have to get it right immediately.
Basically, there are two ways to do so.
You can assume that no entry in the first column will ever be wider than a certain number of characters, which is what you have attempted. The problem is that your setw
is at the wrong position and that right
should be left
. A stream manipulator must be placed before the elements which should be affected. And since you want left-aligned columns, you need left
:
cout << left << setw(20) << "Name" << "Height[m]" << endl;
cout << left << setw(20) << fname + " " + lname << setprecision(2) << fixed << height << endl;
cout << left << setw(20) << fname2 + " " + lname2 << setprecision(2) << fixed << height2 << endl;
But this solution is not very general. What if you'll have a name with 21 characters? Or with 30 characters? Or 100 characters? What you really want is a solution in which the column is automatically set only as wide as necessary.
The only way to do this is to collect all entries before printing them, finding the longest one, setting the column width accordingly and only then print everything.
Here is one possible implementation of this idea:
std::vector<std::string> const first_column_entries
{
"Name",
fname + " " + lname,
fname2 + " " + lname2
};
auto const width_of_longest_entry = std::max_element(std::begin(first_column_entries), std::end(first_column_entries),
[](std::string const& lhs, std::string const& rhs)
{
return lhs.size() < rhs.size();
}
)->size();
// some margin:
auto const column_width = width_of_longest_entry + 3;
std::cout << std::left << std::setw(column_width) << "Name" << "Height[m]" << "\n";
std::cout << std::left << std::setw(column_width) << fname + " " + lname << std::setprecision(2) << std::fixed << height << "\n";
std::cout << std::left << std::setw(column_width) << fname2 + " " + lname2 << std::setprecision(2) << std::fixed << height2 << "\n";
The next step of evolution would be generalising the std::vector
into a self-written class called Table
and iterating that Table
's rows in a loop in order to print the entries.
string fname = "testname";
string lname = "123";
double height = 1.6;
string fname2 = "short";
string lname2 = "123";
double height2 = 1.8;
cout << left << setw(30) << "Name" << left << "Height[m]" << endl;
cout << left << setw(30) << fname + " " + lname << right << setw(6) << setprecision(2) << fixed << height << endl;
cout << left << setw(30) << fname2 + " " + lname2 << right << setw(6) << setprecision(2) << fixed << height2 << endl;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With