Настройка колонок 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;
Другие вопросы по тегам