Выравнивание C ++ при печати cout ‹<

Есть ли способ выровнять текст при печати с использованием std::cout? Я использую табуляции, но когда слова слишком большие, они больше не выравниваются.

Sales Report for September 15, 2010
Artist  Title   Price   Genre   Disc    Sale    Tax Cash
Merle   Blue    12.99   Country 4%  12.47   1.01    13.48
Richard Music   8.49    Classical   8%  7.81    0.66    8.47
Paula   Shut    8.49    Classical   8%  7.81    0.72    8.49

person user69514    schedule 21.03.2010    source источник
comment
Ответы ниже позволяют указать ширину столбца. Обратите внимание, что для этого необходимо знать верхнюю границу (например, ограничение базы данных) или вычислить ее заранее (что может означать анализ всей структуры перед ее фактическим началом печати). Второй хоть и нужен, но медленнее конечно :)   -  person Matthieu M.    schedule 21.03.2010


Ответы (7)


Стандартный способ сделать это ISO C ++ - #include <iomanip> и использовать io-манипуляторы, такие как _2 _ . Однако при этом эти io-манипуляторы очень сложно использовать даже для текста и практически непригодны для форматирования чисел (я предполагаю, что вы хотите, чтобы ваши суммы в долларах совпадали с десятичными числами, имели правильное количество значащих цифр и т. Д. .). Даже для простых текстовых меток код для первой части вашей первой строки будет выглядеть примерно так:

// using standard iomanip facilities
cout << setw(20) << "Artist"
     << setw(20) << "Title"
     << setw(8) << "Price";
// ... not going to try to write the numeric formatting...

Если вы можете использовать библиотеки Boost, запустите (не ходите) и используйте Boost.Format. Он полностью совместим со стандартными iostreams и дает вам все возможности для простого форматирования с помощью строки форматирования printf / Posix, но без потери мощности и удобства самих iostreams. Например, первые части ваших первых двух строк будут выглядеть примерно так:

// using Boost.Format
cout << format("%-20s %-20s %-8s\n")  % "Artist" % "Title" % "Price";
cout << format("%-20s %-20s %8.2f\n") % "Merle" % "Blue" % 12.99;
person Herb Sutter    schedule 21.03.2010
comment
Boost.Format отлично выглядит. Простое форматирование в стиле printf с безопасностью типов. - person dreamlax; 29.03.2010
comment
Позиционные форматы тоже, что здорово, так как это означает, что вы можете извлечь их из файла локализации. - person Donal Fellows; 02.05.2010

См. Также: Какая библиотека CI / O следует использовать в коде C ++?

struct Item
{
   std::string     artist;
   std::string     c;
   integer         price;  // in cents (as floating point is not acurate)
   std::string     Genre;
   integer         disc;
   integer         sale;
   integer         tax;
};

std::cout << "Sales Report for September 15, 2010\n"
          << "Artist  Title   Price   Genre   Disc    Sale    Tax Cash\n";
FOREACH(Item loop,data)
{
    fprintf(stdout,"%8s%8s%8.2f%7s%1s%8.2f%8.2f\n",
          , loop.artist
          , loop.title
          , loop.price / 100.0
          , loop.Genre
          , loop.disc , "%"
          , loop.sale / 100.0
          , loop.tax / 100.0);

   // or

    std::cout << std::setw(8) << loop.artist
              << std::setw(8) << loop.title
              << std::setw(8) << fixed << setprecision(2) << loop.price / 100.0
              << std::setw(8) << loop.Genre
              << std::setw(7) << loop.disc << std::setw(1) << "%"
              << std::setw(8) << fixed << setprecision(2) << loop.sale / 100.0
              << std::setw(8) << fixed << setprecision(2) << loop.tax / 100.0
              << "\n";

    // or

    std::cout << boost::format("%8s%8s%8.2f%7s%1s%8.2f%8.2f\n")
              % loop.artist
              % loop.title
              % loop.price / 100.0
              % loop.Genre
              % loop.disc % "%"
              % loop.sale / 100.0
              % loop.tax / 100.0;
}
person Martin York    schedule 21.03.2010

Здесь может помочь функция манипулятора setw.

person codaddict    schedule 21.03.2010
comment
Вы также должны упомянуть left и right, которые позволяют указать выравнивание, и setfill, который позволяет указать, каким символом завершается (по умолчанию пробел). - person Matthieu M.; 21.03.2010

Манипуляторы ввода-вывода - это то, что вам нужно. В частности, setw. Вот пример со справочной страницы:

// setw example
#include <iostream>
#include <iomanip>
using namespace std;

int main () {
  cout << setw (10);
  cout << 77 << endl;
  return 0;
}

Выравнивание поля слева и справа выполняется с помощью манипуляторов left и right.

Также ознакомьтесь с setfill. Вот более полное руководство по форматированию вывода C ++ с помощью io-манипуляторов.

person Eli Bendersky    schedule 21.03.2010

Другой способ выровнять столбец:

using namespace std;

cout.width(20); cout << left << "Artist";
cout.width(20); cout << left << "Title";
cout.width(10); cout << left << "Price";
...
cout.width(20); cout << left << artist;
cout.width(20); cout << left << title;
cout.width(10); cout << left << price;

Мы должны оценить максимальную длину значений для каждого столбца. В этом случае значения столбца «Исполнитель» не должны превышать 20 знаков и так далее.

person Nguyen    schedule 12.03.2014

Когда вы испускаете самую первую строку,

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

чтобы добиться «выравнивания», вы должны «заранее» знать, какой ширины должен быть каждый столбец (в противном случае выравнивание невозможно). Как только вы действительно узнаете необходимую ширину для каждого столбца (есть несколько возможных способов добиться этого в зависимости от того, откуда поступают ваши данные), тогда вам поможет функция setw, упомянутая в другом ответе, или (подробнее зверски ;-) вы можете выдать тщательно рассчитанное количество дополнительных пробелов (неуклюже, конечно) и т.д. Я все равно не рекомендую вкладки, поскольку у вас нет реального контроля над тем, как конечное устройство вывода будет их отображать в целом.

Возвращаясь к основной проблеме, если у вас есть значение каждого столбца в каком-либо vector<T>, например, вы можете выполнить первый проход форматирования, чтобы определить, например, максимальную ширину столбца (обязательно примите во внимание ширину заголовок столбца, конечно, тоже).

Если ваши строки идут «одна за другой» и выравнивание имеет решающее значение, вам придется кэшировать или буферизовать строки по мере их поступления (в памяти, если они подходят, в противном случае в файле на диске, который вы позже «перемотаете» и перечитайте с самого начала), следя за обновлением вектора «максимальной ширины каждого столбца» по мере поступления строк. Вы не можете ничего вывести (даже заголовки!), Если сохранение выравнивания имеет решающее значение, пока вы не увидите самую последнюю строку (если, конечно, вы каким-то волшебным образом не знаете ширину столбцов ;-).

person Alex Martelli    schedule 21.03.2010

C ++ 20 std::format параметры <, ^ и >

Согласно https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification должно содержать следующее:

// left: "42    "
std::cout << std::format("{:<6}", 42);

// right: "    42"
std::cout << std::format("{:>6}", 42);

// center: "  42  "
std::cout << std::format("{:^6}", 42);

Дополнительная информация: std :: string форматирование, например sprintf

person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 24.09.2020