Настройка колонок C++ с использованием cout
Так что я только начинаю изучать C++, и мне любопытно, если это способ форматировать ваш вывод с помощью cout, чтобы он выглядел красиво и структурирован по столбцам
например.
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
Вывод выглядит так:
Name Height[m]
testname 123 1.60
short 123 1.80
Я хочу, чтобы это выглядело так:
Name Height[m]
testname 123 1.60
short 123 1.80
Проблема, которую я пытаюсь решить, состоит в том, что я хочу разместить высоту в определенной позиции от имени, но в зависимости от длины имени, которую я принимаю, значение высоты либо уходит далеко вправо, либо будет очень близко к левому краю. Есть ли способ это исправить?
2 ответа
Прежде всего, с выходным потоком вроде std::cout
Вы не можете путешествовать во времени и изменять результаты, которые уже были выполнены. Это имеет смысл - просто представьте std::cout
записал в файл, потому что вы запустили свою программу с program.exe > test.txt
, а также test.txt
был на USB-накопителе, который тем временем был отключен...
Таким образом, вы должны сделать это правильно сразу.
В принципе, есть два способа сделать это.
Вы можете предположить, что ни одна запись в первом столбце никогда не будет шире, чем определенное количество символов, что вы и пытались сделать. Проблема в том, что ваш setw
находится в неправильном положении, и это right
должно быть left
, Потоковый манипулятор должен быть размещен перед элементами, на которые следует воздействовать. И так как вы хотите выровненные по левому краю столбцы, вам нужно 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;
Но это решение не очень общее. Что если у вас будет имя с 21 символом? Или с 30 символами? Или 100 символов? То, что вы действительно хотите, это решение, в котором столбец автоматически устанавливается только настолько широким, насколько это необходимо.
Единственный способ сделать это - собрать все записи перед их печатью, найти самую длинную, установить соответствующую ширину столбца и только потом распечатать все.
Вот одна из возможных реализаций этой идеи:
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";
Следующим этапом эволюции будет обобщение std::vector
в самописный класс под названием Table
и повторять, что Table
строки в цикле для печати записей.
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;