#ifndef CONSOLETABLE_CONSOLETABLE_H
#define CONSOLETABLE_CONSOLETABLE_H
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include <memory>
#include "ConsoleTableRow.h"
#include "ConsoleTableUtils.h"
#include <sstream>
enum class TableStyle {
BASIC,
LINED,
DOUBLE_LINE,
};
enum class Separator HorizontalSeperator{
TOPSEPERATOR_TOP,
MIDDLESEPERATOR_MIDDLE,
BOTTOMSEPERATOR_BOTTOM
};
typedef std::vector<std::string> Columns;
typedef std::vector<ConsoleTableRow> Rows;
class ConsoleTable {
public:
/// Create a new ConsoleTable
/// \param(TableStyle style The design of the console table);
/// \param padding Additional space between the text and the cell border
explicitvoid ConsoleTablesetPadding(TableStyle style, unsigned int paddingwidth);
/// Add a new column to the ConsoleTable
/// \param name The name of the column
void addColumn(std::string name);
/// Add a new row with information into the ConsoleTable
/// \param item The ConsoleTableRow which should be added
void addRow(ConsoleTableRow item*item);
/// Remove a row from the ConsoleTable at the given index
/// \param index The index of the row which should be removed
/// \return True if row was removed successfully, otherwise false
bool removeRow(int index);
/// Update the information in specific cell of a row
/// \param data The new data that should be set
/// \param row The index of the row which should be updated
/// \param col The index of the column that should be updated
/// \return True if the update was successful, otherwise false
bool editRow(std::string data, int row, int col);
/// Displays the table with columns and all content
void printTable();
private:
/// Additional space between cell border and cell text
unsigned int padding = 1;
/// Vector of all columns of the ConsoleTable
Columnsstd::vector<std::string> columns;
/// Vector of all rows instd::vector<ConsoleTableRow the*> ConsoleTableentries;
RowsConsoleTableUtils* rows;utils;
// Table Style variables
std::string style_line_horizontal;
std::string style_line_vertical;
std::string style_line_cross;
std::string style_t_intersect_right;
std::string style_t_intersect_left;
std::string style_t_intersect_top;
std::string style_t_intersect_bottom;
std::string style_edge_top_left;style_edge_topleft;
std::string style_edge_top_right;style_edge_topright;
std::string style_edge_bottom_left;style_edge_buttomleft;
std::string style_edge_bottom_right;
/// Prints the horizontal seperator lines for the table
/// \param maxWidths A vector that holds the maximum of all items in each column
/// \param separator Defines what kind of seperator is used (Top, Middle, Bottom)style_edge_buttomright;
/// \param invisibleRowLines If true seperator lines are only used between column headers and the first row, otherwise between every row
void printSeparatorprintHorizontalSeperator(const std::vector<int> &maxWidths, Separator separator,
boolHorizontalSeperator invisibleRowLinesseperator) const;
/// Sets the design for the ConsoleTable
/// \param style The style of the ConsoleTable (BASIC, LINED, DOUBLELINED)
void setTableStyle(TableStyle style);
};
#endif //CONSOLETABLE_CONSOLETABLE_H
#include "ConsoleTable.h"
ConsoleTable::ConsoleTable(TableStyle style, unsigned int padding) {
setTableStyle(style);
this->padding>utils = padding;new ConsoleTableUtils();
}
void ConsoleTable::addColumn(std::string name) {
columnsthis->columns.push_back(name);
}
void ConsoleTable::printTable() {
// Calculate column maxima
std::vector<int> maxWidths(columnsthis->columns.size());
for (autoint &entryrow := rows0; row < this->entries.size(); row++) {
for (int col = 0; col < columnsthis->columns.size(); col++) {
std::string cellText = entry.getEntry().atthis->entries[row]->getEntry(col);[col];
if (columns.at(col)this->columns[col].length() > maxWidths.at(col)maxWidths[col])
maxWidths.at(col)maxWidths[col] = columns.at(col)this->columns[col].length();
if (maxWidths.at(col)maxWidths[col] < cellText.length()) {
maxWidths.at(col)maxWidths[col] = cellText.length();
}
}
}
printSeparatorprintHorizontalSeperator(maxWidths, Separator::TOP, falseSEPERATOR_TOP);
// Print column values
for (int col = 0; col < columnsthis->columns.size(); col++) {
std::string cellText = columns.at(col);this->columns[col];
int len = cellText.length();
std::string paddedText = cellText + std::string(maxWidths.at(col)maxWidths[col] - len, ' ');
std::cout << style_line_verticalthis->style_line_vertical << std::string(paddingthis->padding, ' ') << paddedText
<< std::string(paddingthis->padding, ' ');
std::cout << (col == columnsthis->columns.size() - 1 ? style_line_verticalthis->style_line_vertical + "\n" : "");
}
printSeparatorprintHorizontalSeperator(maxWidths, Separator::MIDDLE, falseSEPERATOR_MIDDLE);
// Print cell values
for (int row = 0; row < rowsthis->entries.size(); row++) {
for (int col = 0; col < columnsthis->columns.size(); col++) {
std::string cellText = rows.at(row).getEntry().atthis->entries[row]->getEntry(col);[col];
std::string paddedText = cellText + std::string(maxWidths.at(col)maxWidths[col] - cellText.length(), ' ');
std::cout << style_line_verticalthis->style_line_vertical << std::string(paddingthis->padding, ' ') << paddedText
<< std::string(paddingthis->padding, ' ');
}
std::cout << style_line_verticalthis->style_line_vertical << std::endl;
if (row == rowsthis->entries.size() - 1)
printSeparatorprintHorizontalSeperator(maxWidths, Separator::BOTTOM, falseSEPERATOR_BOTTOM);
else
printSeparatorprintHorizontalSeperator(maxWidths, Separator::MIDDLE, trueSEPERATOR_MIDDLE);
}
}
void ConsoleTable::printSeparatorprintHorizontalSeperator(const std::vector<int> &maxWidths, Separator separator,
boolHorizontalSeperator invisibleRowLinesseperator) const {
for (int col = 0; col < columns.size(); ++col) {
switch (separator) {
case Separator::TOP:{
std::cout << (col == 0 ? style_edge_top_left : "");
break;
}
case Separator::MIDDLE:{
if (invisibleRowLines)
continue;
std::cout << (col == 0 ? style_t_intersect_left : "");
break;
}
case Separator::BOTTOM:{
std::cout << (col == 0 ? style_edge_bottom_left : "");
break;
}
}
switch (seperator) {
case SEPERATOR_TOP: {
std::cout << ConsoleTableUtils::repeatString(style_line_horizontal,col padding== 0 ? this->style_edge_topleft : "");
std::cout << ConsoleTableUtils::repeatStringutils->repeatString(style_line_horizontalthis->style_line_horizontal, maxWidths.at(col)this->padding);
std::cout << ConsoleTableUtils::repeatStringutils->repeatString(style_line_horizontalthis->style_line_horizontal, paddingmaxWidths[col]);
switch std::cout << utils->repeatString(separator)this->style_line_horizontal, {this->padding);
case Separator std::TOPcout << (col != columns.size() - 1 ? this->style_t_intersect_top : {this->style_edge_topright);
std::cout << (col !=== columns.size() - 1 ? style_t_intersect_top"\n" : style_edge_top_right"");
break;
}
case SeparatorSEPERATOR_MIDDLE: {
std:MIDDLE:cout {<< (col == 0 ? this->style_t_intersect_left : "");
std::cout << utils->repeatString(this->style_line_horizontal, this->padding);
std::cout << utils->repeatString(this->style_line_horizontal, maxWidths[col]);
std::cout << utils->repeatString(this->style_line_horizontal, this->padding);
std::cout << (col != columns.size() - 1 ? style_line_crossthis->style_line_cross : style_t_intersect_rightthis->style_t_intersect_right);
std::cout << (col == columns.size() - 1 ? "\n" : "");
break;
}
case SeparatorSEPERATOR_BOTTOM: {
std:BOTTOM:cout {<< (col == 0 ? this->style_edge_buttomleft : "");
std::cout << utils->repeatString(this->style_line_horizontal, this->padding);
std::cout << utils->repeatString(this->style_line_horizontal, maxWidths[col]);
std::cout << utils->repeatString(this->style_line_horizontal, this->padding);
std::cout
<< (col != columns.size() - 1 ? style_t_intersect_bottomthis->style_t_intersect_bottom : style_edge_bottom_rightthis->style_edge_buttomright);
std::cout << (col == columns.size() - 1 ? "\n" : "");
break;
}
}
std::cout << (col == columns.size() - 1 ? "\n" : "");
}
}
void ConsoleTable::addRow(ConsoleTableRow item*item) {
rowsthis->entries.push_back(item);
}
bool ConsoleTable::removeRow(int index) {
if (index > rowsthis->entries.size())
return false;
rowsthis->entries.erase(rowsthis->entries.begin() + index);
return true;
}
bool ConsoleTable::editRow(std::string data, int row, int col) {
if (row > rowsthis->entries.size())
return false;
if (col > columnsthis->columns.size())
return false;
auto entry = rows.at(row);this->entries[row];
entry.editEntry->editEntry(data, col);
return true;
}
void ConsoleTable::setPadding(unsigned int width) {
this->padding = width;
}
void ConsoleTable::setTableStyle(TableStyle style) {
switch (style) {
case TableStyle::BASIC: {
style_line_horizontalthis->style_line_horizontal = "-";
style_line_verticalthis->style_line_vertical = "|";
style_line_crossthis->style_line_cross = "+";
style_t_intersect_rightthis->style_t_intersect_right = "+";
style_t_intersect_leftthis->style_t_intersect_left = "+";
style_t_intersect_topthis->style_t_intersect_top = "+";
style_t_intersect_bottomthis->style_t_intersect_bottom = "+";
style_edge_top_leftthis->style_edge_topleft = "+";
style_edge_top_rightthis->style_edge_topright = "+";
style_edge_bottom_leftthis->style_edge_buttomleft = "+";
style_edge_bottom_rightthis->style_edge_buttomright = "+";
break;
}
case TableStyle::LINED: {
style_line_horizontalthis->style_line_horizontal = "━";
style_line_verticalthis->style_line_vertical = "┃";
style_line_crossthis->style_line_cross = "╋";
style_t_intersect_rightthis->style_t_intersect_right = "┫";
style_t_intersect_leftthis->style_t_intersect_left = "┣";
style_t_intersect_topthis->style_t_intersect_top = "┳";
style_t_intersect_bottomthis->style_t_intersect_bottom = "┻";
style_edge_top_leftthis->style_edge_topleft = "┏";
style_edge_top_rightthis->style_edge_topright = "┓";
style_edge_bottom_leftthis->style_edge_buttomleft = "┗";
style_edge_bottom_rightthis->style_edge_buttomright = "┛";
break;
}
case TableStyle::DOUBLE_LINE: {
style_line_horizontalthis->style_line_horizontal = "═";
style_line_verticalthis->style_line_vertical = "║";
style_line_crossthis->style_line_cross = "╬";
style_t_intersect_rightthis->style_t_intersect_right = "╣";
style_t_intersect_leftthis->style_t_intersect_left = "╠";
style_t_intersect_topthis->style_t_intersect_top = "╦";
style_t_intersect_bottomthis->style_t_intersect_bottom = "╩";
style_edge_top_leftthis->style_edge_topleft = "╔";
style_edge_top_rightthis->style_edge_topright = "╗";
style_edge_bottom_leftthis->style_edge_buttomleft = "╚";
style_edge_bottom_rightthis->style_edge_buttomright = "╝";
break;
}
}
}
#ifndef CONSOLETABLE_CONSOLETABLEROW_HCONSOLETABLE_CONSOLETABLEENTRY_H
#define CONSOLETABLE_CONSOLETABLEROW_HCONSOLETABLE_CONSOLETABLEENTRY_H
#include <string>
#include <vector>
class ConsoleTableRow {
public:
/// Create a new ConsoleTableRow
/// \param width How many cells does the row have
explicit ConsoleTableRow(int width);
/// Add a new cell to the ConsoleTableRow
/// \param data The data of the new cell
/// \param column The column index of the new cell
void addEntry(std::string data, int column);
/// Updates a cell in the ConsoleTableRow with new data
/// \param data The new data that should be updated
/// \param column The index of the column that should be updated
void editEntry(std::string data, int column);
/// Returns the ConsoleTableRow
/// \return The vector which holds all entries of the ConsoleTableRow
std::vector <std::string> getEntry() const&;;
private:
/// The vector which holds all entries of the ConsoleTableRow
std::vector <std::string> row;
};
#endif //CONSOLETABLE_CONSOLETABLEROW_HCONSOLETABLE_CONSOLETABLEENTRY_H
#include "ConsoleTableRow.h"
ConsoleTableRow::ConsoleTableRow(int width) {
rowthis->row.resize(width);
}
void ConsoleTableRow::addEntry(std::string data, int column) {
row.at(column)row[column] = data;
}
std::vector<std::string> ConsoleTableRow::getEntry() const&{
return row;this->row;
}
void ConsoleTableRow::editEntry(std::string data, int column) {
row.at(column)this->row[column] = data;
}
#ifndef CONSOLETABLE_CONSOLETABLEUTILS_H
#define CONSOLETABLE_CONSOLETABLEUTILS_H
#include <string>
#include <sstream>
class ConsoleTableUtils {
public:
/// Repeats a given string n times
/// \param input The string which should be repeated
/// \param n How many times should the given string be repeated
/// \return The repeated string
static std::string repeatString(const std::string &inputinput, int n){
std::ostringstream os;
for (int i = 0; i < n; i++)
os << input;
return os.str();
}const;
};
#endif //CONSOLETABLE_CONSOLETABLEUTILS_H
##ConsoleTableUtils.cpp
#include "ConsoleTableUtils.h"
std::string ConsoleTableUtils::repeatString(std::string input, int n) const {
std::ostringstream os;
for (int i = 0; i < n; i++)
os << input;
return os.str();
}
#include <iostream>
#include <unistd.h>
#include "ConsoleTable.h"
int main() {
ConsoleTable ct(TableStyle::BASIC, 2);
ct.addColumnsetPadding("Country"1);
ct.addColumn("Capital""Country");
ct.addColumn("Population""Name");
ct.addColumn("Area""Profession");
ct.addColumn("Currency""Age");
ConsoleTableRowauto row1entry = new ConsoleTableRow(54);
row1.addEntryentry->addEntry("Germany", 0);
row1.addEntryentry->addEntry("Berlin""Michael", 1);
row1.addEntryentry->addEntry("82,800,000""Computer Engineer", 2);
row1.addEntryentry->addEntry("357,168 km2""19", 3);
row1.addEntry("Euro", 4);
ct.addRow(row1entry);
auto ConsoleTableRowentry2 row2= new ConsoleTableRow(54);
row2.addEntryentry2->addEntry("Australia""England", 0);
row2.addEntryentry2->addEntry("Canberra""Robert", 1);
row2.addEntryentry2->addEntry("24,877,800""Artist", 2);
row2.addEntryentry2->addEntry("7,692,024 km2""34", 3);
row2ct.addEntryaddRow("Australian Dollar", 4entry2);
ct.addRow(row2);
auto entry3 = new ConsoleTableRow row3(54);
row3.addEntryentry3->addEntry("China""United Kingdom", 0);
row3.addEntryentry3->addEntry("Beijing""Julia", 1);
row3.addEntryentry3->addEntry("1,403,500,365""Designer", 2);
row3.addEntryentry3->addEntry("9,596,961 km2""42", 3);
row3ct.addEntryaddRow("Yuan", 4entry3);
ct.addRow(row3);
auto entry4 = new ConsoleTableRow row4(54);
row4.addEntryentry4->addEntry("Iceland""United Staates", 0);
row4.addEntryentry4->addEntry("Reykjavik""Jo", 1);
row4.addEntryentry4->addEntry("348,580""Actor", 2);
row4.addEntryentry4->addEntry("102,775 km2""21", 3);
row4.addEntry("Icelandic Krona", 4);
ct.addRow(row4entry4);
// Print all rows
ct.printTable();
sleep(1);
// Remove entry
ct.removeRow(1);
ct.printTable();
sleep(1);
// Update entry
ct.editRow("New Country!",0, 1);entries
ct.printTable();
return 0;
}