Как я могу легко форматировать таблицу данных на С++?
Я не уверен, но я думаю, что я помню, что в 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
Это единственный способ расчета? Или есть какой-то волшебный еще более простой способ?
Ответы
Ответ 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