Как реализовать вывод данных из структуры на консоль в виде таблицы с равными расстояниями?

Имеется вот такая функция вывода данных из структуры на консоль (структура в своб очередь подтягивает данные напрямую с файла):

cout << "№ товару\tНайменування товару\t\tВартість товару\t\tЗалишок на складі\tОдиниця виміру" << endl;
    for (int i = 0; i < all.size(); i++)
    {
        cout << i << "\t\t" << all[i].name << "\t\t\t\t" << all[i].price << "\t\t" << all[i].amount << "\t\t\t\t" << all[i].unit << endl;
    }

Однако при выводе на консоль получается полная белиберда, как видно на скриншоте:

Как выводить данные на консоль таким образом, что-бы не получалась каша, из-за разной длинны названий товаров?


Ответы (2 шт):

Автор решения: Harry

См. setw(). А если компилятор поновее, то можно использовать форматированные строки. Или плюнуть на cout и работать через printf().

Вот пример с setw() и printf():

struct Item
{
    const char * name;
    int price;
} item[3] =
{
    { "short", 1 },
    { "middle long", 250 },
    { "very very very long", 3000 }
};


int main(int argc, char * argv[])
{
    cout << "#\tProduct\t\tPrice\n";
    for(int i = 0; i < 3; ++i)
        cout << i+1 << "\t" << item[i].name << "\t\t"
             << item[i].price << "\n";

    cout << "----------------\n";
    cout << left << setw(5) << "#" << setw(22) << "Product" << setw(5) << "Price\n";
    for(int i = 0; i < 3; ++i)
        cout << left << setw(5) << i+1 << setw(22) << item[i].name << setw(5)
             << right << item[i].price << "\n";

    cout << "----------------\n";

    printf("#    Product               Price\n");
    for(int i = 0; i < 3; ++i)
        printf("%1d    %-22s%5d\n",i+1,item[i].name,item[i].price);

}
→ Ссылка
Автор решения: Єгор Тітаренко

Пробовал, setw(), бесполезная в данной задаче вещь. Форматированные строки требуют изучения, а в рунете о них информации мало. В общем для решения такой задачи было использовано довольно тривиальное решение, суть которого заключается в том, что сначала мы пишем функцию принимающую целочисленный параметр и выводящую соответсвенное количество пробелов на консоль при вызове, то есть:

void print_space(int num)
{
    for (int i = 0; i < num; i++)
    {
        cout << " ";
    }
}

На примере моей программы, вызов данной функции выглядел так:

for (int i = 0; i < all.size(); i++)
    {
        cout << i << "\t\t" << all[i].name; print_space((max_name_num - all[i].name.length())); cout << all[i].price << "\t\t\t" << all[i].amount << " " << all[i].unit << endl;
    }

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

→ Ссылка