Как я могу легко форматировать таблицу данных на С++? - программирование
Подтвердить что ты не робот

Как я могу легко форматировать таблицу данных на С++?

Я не уверен, но я думаю, что я помню, что в Java есть что-то, что может указывать, как далеко от окна окна начинается строка или цифра.

Как легко форматировать таблицу? У меня есть это (используя setw):

Bob Doe     10.96      7.61     14.39      2.11     47.30     14.21     44.58      5.00     60.23
Helen City     10.44      7.78     16.27      1.99     48.92     13.93     53.79      5.00     70.97
Joe Green     10.90      7.33     14.49      2.05     47.91     14.15     44.45      4.70     73.98

и в идеале хотел бы:

Bob           Doe        BLR  10.96   7.61  14.39   2.11  47.30  14.21  44.58   5.00  60.23  4:27.47
Helen         City       CUB  10.90   7.33  14.49   2.05  47.91  14.15  44.45   4.70  73.98  4:29.17
Joe           Green      USA  10.44   7.78  16.27   1.99  48.92  13.93  53.79   5.00  70.97  5:06.59

Это единственный способ расчета? Или есть какой-то волшебный еще более простой способ?

4b9b3361

Ответ 1

В С++ у вас есть три функции, которые помогут вам делать то, что вы хотите. Определены в <iomanip>.
 - setw() поможет вам определить ширину вывода.
 - setfill() Заполните остальные символом, который вы хотите (в вашем случае ").
 - left (или справа) позволяет определить выравнивание.

Вот код для написания вашей первой строки:

#include <iostream>
#include <iomanip>

using namespace std;

int main() {
    const char separator    = ' ';
    const int nameWidth     = 6;
    const int numWidth      = 8;

    cout << left << setw(nameWidth) << setfill(separator) << "Bob";
    cout << left << setw(nameWidth) << setfill(separator) << "Doe";
    cout << left << setw(numWidth) << setfill(separator) << 10.96;
    cout << left << setw(numWidth) << setfill(separator) << 7.61;
    cout << left << setw(numWidth) << setfill(separator) << 14.39;
    cout << left << setw(numWidth) << setfill(separator) << 2.11;
    cout << left << setw(numWidth) << setfill(separator) << 47.30;
    cout << left << setw(numWidth) << setfill(separator) << 14.21;
    cout << left << setw(numWidth) << setfill(separator) << 44.58;
    cout << left << setw(numWidth) << setfill(separator) << 5.00;
    cout << left << setw(numWidth) << setfill(separator) << 60.23;
    cout << endl;

    cin.get();
}


EDIT: Чтобы уменьшить код, вы можете использовать функцию шаблона:

template<typename T> void printElement(T t, const int& width)
{
    cout << left << setw(width) << setfill(separator) << t;
}

Что вы можете использовать следующим образом:

printElement("Bob", nameWidth);
printElement("Doe", nameWidth);
printElement(10.96, numWidth);
printElement(17.61, numWidth);
printElement(14.39, numWidth);
printElement(2.11, numWidth);
printElement(47.30, numWidth);
printElement(14.21, numWidth);
printElement(44.58, numWidth);
printElement(5.00, numWidth);
printElement(60.23, numWidth);
cout << endl;

Ответ 2

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

Поскольку функции используют строковые потоки, они не так быстро, как другие решения, но для меня это никогда не имеет значения - вычислительная бутылка в другом месте.

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


ОТОБРАЖЕНИЕ АРБИТРАЖНОЙ ТОЧНОСТИ

Эта функция prd (сокращение от "double double" ) просто печатает двойное значение с заданной точностью.

/* Convert double to string with specified number of places after the decimal. */
std::string prd(const double x, const int decDigits) {
    stringstream ss;
    ss << fixed;
    ss.precision(decDigits); // set # places after decimal
    ss << x;
    return ss.str();
}

Ниже представлен только вариант, который позволяет указать пробел в пустом месте слева от номера. Это может быть полезно при отображении таблиц.

/* Convert double to string with specified number of places after the decimal
   and left padding. */
std::string prd(const double x, const int decDigits, const int width) {
    stringstream ss;
    ss << fixed << right;
    ss.fill(' ');        // fill space around displayed #
    ss.width(width);     // set  width around displayed #
    ss.precision(decDigits); // set # places after decimal
    ss << x;
    return ss.str();
}

ФУНКЦИЯ ЦЕНТРАЛЬНОГО ИСПОЛЬЗОВАНИЯ

Эта функция просто выравнивает по центру текст, заполняя левый и правый пробелы, пока возвращаемая строка не будет такой же, как указанная ширина.

/*! Center-aligns string within a field of width w. Pads with blank spaces
    to enforce alignment. */
std::string center(const string s, const int w) {
    stringstream ss, spaces;
    int padding = w - s.size();                 // count excess room to pad
    for(int i=0; i<padding/2; ++i)
        spaces << " ";
    ss << spaces.str() << s << spaces.str();    // format with padding
    if(padding>0 && padding%2!=0)               // if odd #, add 1 space
        ss << " ";
    return ss.str();
}

ПРИМЕР ТАБУЛЯРНОГО ВЫХОДА

Итак, мы могли бы использовать функции prd и center выше, чтобы вывести таблицу следующим образом.

Код:

std::cout << center("x",10)       << " | "
          << center("x^2",10)     << " | "
          << center("(x^2)/8",10) << "\n";

std::cout << std::string(10*3 + 2*3, '-') << "\n";

for(double x=1.5; x<200; x +=x*2) {
    std::cout << prd(x,1,10)       << " | "
              << prd(x*x,2,10)     << " | "
              << prd(x*x/8.0,4,10) << "\n";
}

напечатает таблицу:

    x      |    x^2     |  (x^2)/8  
------------------------------------
       1.5 |       2.25 |     0.2812
       4.5 |      20.25 |     2.5312
      13.5 |     182.25 |    22.7812
      40.5 |    1640.25 |   205.0312
     121.5 |   14762.25 |  1845.2812

ФУНКЦИИ RIGHT- и LEFT-ALIGN

И, конечно, вы можете легко построить варианты функции center, которые выравнивают по правому краю или по левому краю и добавляют пробелы для заполнения нужной ширины. Вот такие функции:

/* Right-aligns string within a field of width w. Pads with blank spaces
   to enforce alignment. */
string right(const string s, const int w) {
    stringstream ss, spaces;
    int padding = w - s.size();                 // count excess room to pad
    for(int i=0; i<padding; ++i)
        spaces << " ";
    ss << spaces.str() << s;                    // format with padding
    return ss.str();
}

/*! Left-aligns string within a field of width w. Pads with blank spaces
    to enforce alignment. */
string left(const string s, const int w) {
    stringstream ss, spaces;
    int padding = w - s.size();                 // count excess room to pad
    for(int i=0; i<padding; ++i)
        spaces << " ";
    ss << s << spaces.str();                    // format with padding
    return ss.str();
}

Я уверен, что есть много более элегантных способов сделать такие вещи - конечно, есть более сжатые способы. Но это то, что я делаю. Хорошо работает для меня.

Ответ 3

Просто используйте sprintf с спецификаторы формата для форматирования полей. Вы также можете использовать MFC CString

#include <iostream>
#include "stdio.h"

using namespace std;

int main()
{
    char buf[256];
    char pattern[]  = "%10s %10s     %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f %7.2f";
    sprintf(buf, pattern, "Bob",  "Doe",     10.96,      7.61,     14.39,      2.11,     47.30,     14.21,     44.58,      5.00,     60.23);
    cout << buf << endl;
    sprintf(buf, pattern, "Helen", "City",     10.44,      7.78,     16.27,      1.99,     48.92,     13.93,     53.79,      5.00,     70.97);
    cout << buf << endl;
    sprintf(buf, pattern, "Joe", "Green",     10.90,      7.33,     14.49,      2.05,     47.91,     14.15,     44.45,      4.70,     73.98);
    cout << buf << endl;
}

Ответ 4

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

Ответ 5

Вы можете сделать что-то подобное, чтобы немного упростить процесс.

#include <iomanip>
#include <iostream>

struct TableFormat {
    int width;
    char fill;
    TableFormat(): width(14), fill(' ') {}
    template<typename T>
    TableFormat& operator<<(const T& data) {
        std::cout << data << std::setw(width) << std::setfill(fill);
        return *this;
    }
    TableFormat& operator<<(std::ostream&(*out)(std::ostream&)) {
        std::cout << out;
        return *this;
    }
};

int main() {
    TableFormat out;
    out << "Bob" << "Doe";
    out.width = 8;
    out << "BLR" << 10.96 << 7.61 << 14.39 << 2.11 << 47.30;
}

Что бы напечатать (ужасно в моем случае, но оно "настраивается" до некоторой степени):

Bob           Doe           BLR   10.96    7.61   14.39    2.11    47.3

Код довольно понятен, это всего лишь обертка вокруг std::cout, чтобы упростить утомительные звонки, вторая перегрузка для operator<< позволяет вам отправлять std::endl..

Ответ 6

Рассмотрим пример:

string firstname = "Bob";
string lastname = "Doe";
string country = "BLR";
float f1 = 10.96f, f2=7.61f, f3=14.39f, f4=2.11f, f5=47.30f, f6=14.21f, f7=44.58f, f8=5.00f, f9=60.23f;
string time = "4:27.47";
cout << setw(12) << firstname << set(12) << lastname;
cout << setw(5) << country << setprecision(2) << f1 << setprecision(2) << f2 << setprecision(2) << f3..
  • используйте setw() для установки ширины при печати строки
  • использовать setprecision для установки точности для плавающих значений
  • прочитайте MSDN

Ответ 7

Я не уверен, что вы написали, поэтому я не могу понять, что неправильно, но вы можете получить результаты, которые вы хотите, с помощью std:: setw:

#include <iostream>
#include <iomanip>

int main() {
   std::cout << std::left << std::setw(20) << "BoB" << std::setw(20) << 123.456789 << '\n';
   std::cout << std::left << std::setw(20) << "Richard" << std::setw(20) << 1.0 << '\n';
}

http://ideone.com/Iz5RXr