С++ выравнивание при печати 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

Ответ 1

Стандартный способ ISO С++ для этого - #include <iomanip> и использовать io-манипуляторы, такие как std::setw. Однако, тем не менее, эти 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 libraries, запустите (не ходите) и используйте 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;

Ответ 2

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

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

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

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

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

Ответ 3

Смотрите также: Какую библиотеку ввода/вывода 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;
}

Ответ 4

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

Ответ 5

Другой способ выравнивания столбцов выглядит следующим образом:

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 символов и т.д.

Ответ 6

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

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

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

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

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