mirror of
https://github.com/tdulcet/Table-and-Graph-Libs.git
synced 2025-05-05 21:41:12 +08:00
Updated to support and use modern C++ features and added more examples.
This commit is contained in:
parent
37e257c5ee
commit
274f949079
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@ -27,9 +27,9 @@ jobs:
|
||||
$CXX --version
|
||||
- name: Script
|
||||
run: |
|
||||
$CXX -Wall -g -fsanitize=address,undefined tables.cpp -o tables
|
||||
$CXX -Wall -g -Og -fsanitize=address,undefined tables.cpp -o tables
|
||||
./tables
|
||||
$CXX -Wall -g -fsanitize=address,undefined graphs.cpp -o graphs
|
||||
$CXX -Wall -g -Og -fsanitize=address,undefined graphs.cpp -o graphs
|
||||
./graphs
|
||||
- name: Cppcheck
|
||||
run: cppcheck --enable=all .
|
||||
|
@ -13,12 +13,12 @@ install:
|
||||
- sudo apt-get -yqq update
|
||||
- sudo apt-get -yqq install cppcheck
|
||||
script:
|
||||
- g++ -Wall -g -fsanitize=address,undefined tables.cpp -o gcc_tables
|
||||
- g++ -Wall -g -Og -fsanitize=address,undefined tables.cpp -o gcc_tables
|
||||
- ./gcc_tables
|
||||
- g++ -Wall -g -fsanitize=address,undefined graphs.cpp -o gcc_graphs
|
||||
- g++ -Wall -g -Og -fsanitize=address,undefined graphs.cpp -o gcc_graphs
|
||||
- ./gcc_graphs
|
||||
- clang++ -Wall -g -fsanitize=address,undefined,integer tables.cpp -o clang_tables
|
||||
- clang++ -Wall -g -Og -fsanitize=address,undefined,integer tables.cpp -o clang_tables
|
||||
- ./clang_tables
|
||||
- clang++ -Wall -g -fsanitize=address,undefined,integer graphs.cpp -o clang_graphs
|
||||
- clang++ -Wall -g -Og -fsanitize=address,undefined,integer graphs.cpp -o clang_graphs
|
||||
- ./clang_graphs
|
||||
- cppcheck --enable=all .
|
||||
|
332
README.md
332
README.md
@ -9,20 +9,29 @@ Copyright © 2018 Teal Dulcet
|
||||
|
||||
These header only libraries use [box-drawing](https://en.wikipedia.org/wiki/Box-drawing_character#Unicode), [Braille](https://en.wikipedia.org/wiki/Braille_Patterns), [fraction](https://en.wikipedia.org/wiki/Number_Forms) and other Unicode characters and [terminal colors and formatting](https://misc.flogisoft.com/bash/tip_colors_and_formatting) to output tables and graphs/plots to the console. All the tables and graphs are created with a single (one) function call and they do not require any special data structures.
|
||||
|
||||
See the [python](python) directory for Python ports of the libraries.
|
||||
|
||||
❤️ Please visit [tealdulcet.com](https://www.tealdulcet.com/) to support these libraries and my other software development.
|
||||
|
||||
## Tables
|
||||
|
||||
### Usage
|
||||
|
||||
Requires support for C++17. See the [tables.hpp](tables.hpp) file for full usage information.
|
||||
|
||||
Complete versions of all of the examples below and more can be found in the [tables.cpp](tables.cpp) file.
|
||||
|
||||
Compile with: `g++ -Wall -g -O3 tables.cpp -o tables`.
|
||||
Compile with:
|
||||
|
||||
Run with: `./tables`.
|
||||
GCC: `g++ -std=c++17 -Wall -g -O3 tables.cpp -o tables`\
|
||||
Clang: `clang++ -std=c++17 -Wall -g -O3 tables.cpp -o tables`
|
||||
|
||||
Run with: `./tables`
|
||||
|
||||
#### Output char array as table
|
||||
|
||||
##### C style char array
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
@ -41,7 +50,7 @@ int main()
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
|
||||
table(rows, columns, array, NULL, NULL, aoptions);
|
||||
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||
|
||||
// Deallocate array
|
||||
|
||||
@ -49,12 +58,43 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ string array
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t rows = 5;
|
||||
size_t columns = 5;
|
||||
|
||||
vector<vector<string>> array(rows, vector<string>(columns));
|
||||
|
||||
// Set array
|
||||
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Table cells can contain [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters), but not newlines and tabs.
|
||||
|
||||

|
||||
|
||||
#### Output array as table with separate header row and column
|
||||
|
||||
##### C style char array
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
@ -84,10 +124,43 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ string array
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t rows = 5;
|
||||
size_t columns = 5;
|
||||
|
||||
string headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
||||
string headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
||||
|
||||
vector<vector<string>> array(rows, vector<string>(columns));
|
||||
|
||||
// Set array
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// or with C++20:
|
||||
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
Output same as example above.
|
||||
|
||||
#### Output array as table
|
||||
|
||||
##### C style pointer
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
@ -102,7 +175,7 @@ int main()
|
||||
|
||||
// Allocate and set array
|
||||
|
||||
table(rows, columns, array, NULL, NULL, tabledefaultoptions);
|
||||
table(rows, columns, array);
|
||||
|
||||
// Deallocate array
|
||||
|
||||
@ -110,10 +183,34 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ array/vector
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t rows = 5;
|
||||
size_t columns = 5;
|
||||
|
||||
vector<vector<double>> array(rows, vector<double>(columns)); // array can be any data type
|
||||
|
||||
// Set array
|
||||
|
||||
table(array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### Output sorted array as table
|
||||
|
||||
##### C style pointer
|
||||
|
||||
```cpp
|
||||
#include <algorithm>
|
||||
#include "tables.hpp"
|
||||
@ -124,7 +221,7 @@ int dimensions; // Number of columns
|
||||
int sortdimension; // Column to sort by
|
||||
|
||||
template <typename T>
|
||||
bool compare(const T *a, const T *b)
|
||||
bool compare(const T &a, const T &b)
|
||||
{
|
||||
if (a[sortdimension] == b[sortdimension])
|
||||
for (int i = 0; i < dimensions; ++i)
|
||||
@ -146,9 +243,9 @@ int main()
|
||||
dimensions = columns;
|
||||
sortdimension = 0;
|
||||
|
||||
sort(array, array + rows, compare<int>);
|
||||
sort(array, array + rows, compare<int *>);
|
||||
|
||||
table(rows, columns, array, NULL, NULL, tabledefaultoptions);
|
||||
table(rows, columns, array);
|
||||
|
||||
// Deallocate array
|
||||
|
||||
@ -156,10 +253,52 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ array/vector
|
||||
|
||||
```cpp
|
||||
#include <algorithm>
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int sortdimension; // Column to sort by
|
||||
|
||||
template <typename T>
|
||||
bool compare(const T &a, const T &b)
|
||||
{
|
||||
if (a[sortdimension] == b[sortdimension])
|
||||
for (int i = 0; i < size(a); ++i)
|
||||
if (sortdimension != i and a[i] != b[i])
|
||||
return a[i] < b[i];
|
||||
|
||||
return a[sortdimension] < b[sortdimension];
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t rows = 5;
|
||||
size_t columns = 5;
|
||||
|
||||
vector<vector<int>> array(rows, vector<int>(columns)); // array can be any data type
|
||||
|
||||
// Set array
|
||||
|
||||
sortdimension = 0;
|
||||
|
||||
sort(array.begin(), array.end(), compare<vector<int>>);
|
||||
|
||||
table(array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### Output single function as table
|
||||
|
||||
##### C style function pointer
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
@ -185,10 +324,37 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ lambda function
|
||||
|
||||
```cpp
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
double xmin = -10;
|
||||
double xmax = 10;
|
||||
double xscl = 2;
|
||||
|
||||
function<double(double)> afunction = [](auto x)
|
||||
{ return x + 1; };
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
|
||||
table(xmin, xmax, xscl, afunction, aoptions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
#### Output multiple functions as table
|
||||
|
||||
##### C style function pointer
|
||||
|
||||
```cpp
|
||||
#include <cmath>
|
||||
#include "tables.hpp"
|
||||
@ -214,7 +380,38 @@ int main()
|
||||
size_t numfunctions = 2;
|
||||
|
||||
// Function parameter and return value can be any data type, as long as they are the same
|
||||
double (*functions[])(double) = {function1, function2};
|
||||
function<double(double)> functions[] = {function1, function2};
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
|
||||
table(xmin, xmax, xscl, numfunctions, functions, aoptions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ lambda function
|
||||
|
||||
```cpp
|
||||
#include <cmath>
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
double xmin = -10;
|
||||
double xmax = 10;
|
||||
double xscl = 2;
|
||||
|
||||
size_t numfunctions = 2;
|
||||
|
||||
// Function parameter and return value can be any data type, as long as they are the same
|
||||
function<double(double)> functions[] = {[](auto x)
|
||||
{ return 2 * x; },
|
||||
[](auto x)
|
||||
{ return pow(x, 2); }};
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
@ -274,7 +471,7 @@ Default value: `false`
|
||||
#### Title
|
||||
|
||||
Option: `title`\
|
||||
Default value: `NULL`
|
||||
Default value: `nullptr`
|
||||
|
||||
The title is word wrapped based on the current width of the terminal, using [this](https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0) solution. Handles newlines, tabs and [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters).
|
||||
|
||||
@ -315,15 +512,21 @@ Values:
|
||||
|
||||
### Usage
|
||||
|
||||
Requires support for C++17. See the [graphs.hpp](graphs.hpp) file for full usage information.
|
||||
|
||||
Complete versions of all of the examples below and more can be found in the [graphs.cpp](graphs.cpp) file.
|
||||
|
||||
Compile with: `g++ -Wall -g -O3 graphs.cpp -o graphs`.
|
||||
Compile with:
|
||||
GCC: `g++ -std=c++17 -Wall -g -O3 graphs.cpp -o graphs`\
|
||||
Clang: `clang++ -std=c++17 -Wall -g -O3 graphs.cpp -o graphs`
|
||||
|
||||
Run with: `./graphs`.
|
||||
Run with: `./graphs`
|
||||
|
||||
If `height` is `0`, it will be set to the current height of the terminal (number of rows times four). If `width` is `0`, it will be set to the current width of the terminal (number of columns times two).
|
||||
|
||||
#### Output array as plot
|
||||
#### Output single array as plot
|
||||
|
||||
##### C style pointer
|
||||
|
||||
```cpp
|
||||
#include "graphs.hpp"
|
||||
@ -346,7 +549,7 @@ int main()
|
||||
|
||||
// Allocate and set array
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, rows, array, graphdefaultoptions);
|
||||
graph(height, width, xmin, xmax, ymin, ymax, rows, array);
|
||||
|
||||
// Deallocate array
|
||||
|
||||
@ -354,12 +557,45 @@ int main()
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ array/vector
|
||||
|
||||
```cpp
|
||||
#include "graphs.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t height = 160;
|
||||
size_t width = 160;
|
||||
|
||||
long double xmin = -20;
|
||||
long double xmax = 20;
|
||||
long double ymin = -20;
|
||||
long double ymax = 20;
|
||||
|
||||
size_t rows = 10;
|
||||
|
||||
vector<vector<double>> array(rows, vector<double>(2)); // array can be any data type, but must have exactly two columns
|
||||
|
||||
// Set array
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, array);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
If `xmin` and `xmax` are both `0`, they will be set to the respective minimum and maximum values of x in the array. If `ymin` and `ymax` are both `0`, they will be set to the respective minimum and maximum values of y in the array.
|
||||
|
||||

|
||||
|
||||
Use `graph()` to plot multiple arrays, which can be of different sizes.
|
||||
|
||||
#### Output single function as graph
|
||||
|
||||
##### C style function pointer
|
||||
|
||||
```cpp
|
||||
#include "graphs.hpp"
|
||||
|
||||
@ -380,7 +616,33 @@ int main()
|
||||
long double ymin = -20;
|
||||
long double ymax = 20;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, afunction, graphdefaultoptions);
|
||||
graph(height, width, xmin, xmax, ymin, ymax, afunction);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ lambda function
|
||||
|
||||
```cpp
|
||||
#include "graphs.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t height = 160;
|
||||
size_t width = 160;
|
||||
|
||||
long double xmin = -20;
|
||||
long double xmax = 20;
|
||||
long double ymin = -20;
|
||||
long double ymax = 20;
|
||||
|
||||
function<double(double)> afunction = [](auto x)
|
||||
{ return x + 1; };
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, afunction);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -390,6 +652,8 @@ int main()
|
||||
|
||||
#### Output multiple functions as graph
|
||||
|
||||
##### C style function pointer
|
||||
|
||||
```cpp
|
||||
#include "graphs.hpp"
|
||||
|
||||
@ -418,9 +682,40 @@ int main()
|
||||
size_t numfunctions = 2;
|
||||
|
||||
// Function parameter and return value can be any data type, as long as they are the same
|
||||
double (*functions[])(double) = {function1, function2};
|
||||
function<double(double)> functions[] = {function1, function2};
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions, graphdefaultoptions);
|
||||
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
##### C++ lambda function
|
||||
|
||||
```cpp
|
||||
#include "graphs.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main()
|
||||
{
|
||||
size_t height = 160;
|
||||
size_t width = 160;
|
||||
|
||||
long double xmin = -20;
|
||||
long double xmax = 20;
|
||||
long double ymin = -20;
|
||||
long double ymax = 20;
|
||||
|
||||
size_t numfunctions = 2;
|
||||
|
||||
// Function parameter and return value can be any data type, as long as they are the same
|
||||
function<double(double)> functions[] = {[](auto x)
|
||||
{ return 2 * x; },
|
||||
[](auto x)
|
||||
{ return pow(x, 2); }};
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, numfunctions, functions);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -452,7 +747,7 @@ Requires `border` and `axislabel` to be `true`.
|
||||
#### Title
|
||||
|
||||
Option: `title`\
|
||||
Default value: `NULL`
|
||||
Default value: `nullptr`
|
||||
|
||||
The title is word wrapped based on the current width of the terminal, using [this](https://gist.github.com/tdulcet/819821ca69501822ad3f84a060c640a0) solution. Handles newlines, tabs and [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters).
|
||||
|
||||
@ -543,5 +838,4 @@ Both:
|
||||
* Port to other languages (C, Java, Rust, etc.)
|
||||
|
||||
C++:
|
||||
* Handle formatted text in the tables
|
||||
* Support plotting multiple arrays of different sizes
|
||||
* Support tables with the `wchar_t`, `char16_t` and `char32_t` C data types and the `wstring`, `u16string` and `u32string` C++ data types.
|
||||
|
102
graphs.cpp
102
graphs.cpp
@ -1,40 +1,42 @@
|
||||
// Teal Dulcet, CS546
|
||||
|
||||
// Compile: g++ -Wall -g -O3 graphs.cpp -o graphs
|
||||
// Compile: g++ -Wall -g -O3 -std=c++17 graphs.cpp -o graphs
|
||||
|
||||
// Run: ./graphs
|
||||
|
||||
#include <cctype>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "graphs.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
long double afunction(long double x)
|
||||
constexpr long double afunction(long double x)
|
||||
{
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
long double function1(long double x)
|
||||
constexpr long double function1(long double x)
|
||||
{
|
||||
return 2 * x;
|
||||
}
|
||||
|
||||
long double function2(long double x)
|
||||
constexpr long double function2(long double x)
|
||||
{
|
||||
return pow(x, 2);
|
||||
}
|
||||
|
||||
long double function3(long double x)
|
||||
constexpr long double function3(long double x)
|
||||
{
|
||||
return sin(x);
|
||||
}
|
||||
|
||||
long double function4(long double x)
|
||||
constexpr long double function4(long double x)
|
||||
{
|
||||
return cos(x);
|
||||
}
|
||||
|
||||
long double function5(long double x)
|
||||
constexpr long double function5(long double x)
|
||||
{
|
||||
return tan(x);
|
||||
}
|
||||
@ -52,7 +54,7 @@ int main()
|
||||
const size_t rows = 10;
|
||||
const size_t columns = 2;
|
||||
|
||||
// Output array as plot
|
||||
// Output single array as plot
|
||||
cout << "\nOutput array as plot\n\n";
|
||||
{
|
||||
long double **array;
|
||||
@ -62,18 +64,18 @@ int main()
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
array[i][j] = i + j; //rand();
|
||||
array[i][j] = i + j; // rand();
|
||||
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, rows, array, aoptions);
|
||||
}
|
||||
|
||||
if (array != NULL)
|
||||
if (array != nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
delete[] array[i];
|
||||
@ -81,12 +83,57 @@ int main()
|
||||
delete[] array;
|
||||
}
|
||||
}
|
||||
{
|
||||
array<array<long double, columns>, rows> aarray;
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
aarray[i][j] = i + j; // rand();
|
||||
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
vector<vector<long double>> array(rows, vector<long double>(columns));
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
array[i][j] = i + j; // rand();
|
||||
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, array, aoptions);
|
||||
}
|
||||
}
|
||||
// Output single function as graph
|
||||
cout << "\nOutput single function as graph\n\n";
|
||||
{
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, afunction, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
function<long double(long double)> afunction = [](auto x)
|
||||
{ return x + 1; };
|
||||
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
@ -96,11 +143,26 @@ int main()
|
||||
// Output multiple functions as graph
|
||||
cout << "\nOutput multiple functions as graph\n\n";
|
||||
{
|
||||
long double (*functions[])(long double) = {function1, function2};
|
||||
function<long double(long double)> functions[] = {function1, function2};
|
||||
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, 2, functions, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
function<long double(long double)> functions[] = {[](auto x)
|
||||
{ return 2 * x; },
|
||||
[](auto x)
|
||||
{ return pow(x, 2); }};
|
||||
|
||||
graphoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
@ -113,28 +175,30 @@ int main()
|
||||
const long double ymin = -4;
|
||||
const long double ymax = 4;
|
||||
|
||||
long double (*functions[])(long double) = {function3, function4, function5};
|
||||
function<long double(long double)> functions[] = {function3, function4, function5};
|
||||
|
||||
graphoptions aoptions;
|
||||
aoptions.axisunitslabel = false;
|
||||
// graphoptions aoptions{.axisunitslabel = false};
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
graph(height, width, xmin, xmax, ymin, ymax, 3, functions, aoptions);
|
||||
}
|
||||
|
||||
/*aoptions.style = 2;
|
||||
/* aoptions.style = 2;
|
||||
|
||||
for (unsigned int k = 10; k < 300; ++k)
|
||||
{
|
||||
cout << "\e[1;1H" << "\e[2J";
|
||||
cout << "\e[1;1H"
|
||||
<< "\e[2J";
|
||||
|
||||
graph(k, k, xmin, xmax, ymin, ymax, 3, functions, aoptions);
|
||||
|
||||
usleep(200000);
|
||||
}*/
|
||||
} */
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
235
graphs.hpp
235
graphs.hpp
@ -4,25 +4,29 @@
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <cfloat>
|
||||
#include <iomanip>
|
||||
#include <cwchar>
|
||||
#include <clocale>
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char *const styles[][11] = {
|
||||
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //ASCII
|
||||
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //Basic
|
||||
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light
|
||||
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, //Heavy
|
||||
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, //Double
|
||||
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light Dashed
|
||||
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} //Heavy Dashed
|
||||
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // ASCII
|
||||
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // Basic
|
||||
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light
|
||||
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, // Heavy
|
||||
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, // Double
|
||||
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light Dashed
|
||||
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} // Heavy Dashed
|
||||
};
|
||||
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
|
||||
|
||||
@ -38,31 +42,15 @@ const long double fractionvalues[] = {1.0L / 4.0L, 1.0L / 2.0L, 3.0L / 4.0L, 1.0
|
||||
|
||||
struct graphoptions
|
||||
{
|
||||
bool border;
|
||||
bool axislabel;
|
||||
bool axisunitslabel;
|
||||
char *title;
|
||||
unsigned int style;
|
||||
unsigned int color;
|
||||
graphoptions(void);
|
||||
~graphoptions(void);
|
||||
bool border = true;
|
||||
bool axislabel = true;
|
||||
bool axisunitslabel = true;
|
||||
const char *title = nullptr;
|
||||
unsigned int style = 2;
|
||||
unsigned int color = 2;
|
||||
};
|
||||
|
||||
graphoptions::graphoptions(void)
|
||||
{
|
||||
border = true;
|
||||
axislabel = true;
|
||||
axisunitslabel = true;
|
||||
style = 2;
|
||||
color = 2;
|
||||
title = NULL;
|
||||
}
|
||||
|
||||
graphoptions::~graphoptions(void)
|
||||
{
|
||||
}
|
||||
|
||||
const graphoptions graphdefaultoptions;
|
||||
const graphoptions defaultoptions;
|
||||
|
||||
// Number of columns needed to represent the string
|
||||
// Adapted from: https://stackoverflow.com/a/31124065
|
||||
@ -76,8 +64,8 @@ int strcol(const char *const str)
|
||||
cout << "Control character: " << (int)str[i] << "\n";
|
||||
}
|
||||
|
||||
length = mbstowcs(NULL, str, 0);
|
||||
if (length == (size_t)-1)
|
||||
length = mbstowcs(nullptr, str, 0);
|
||||
if (length == static_cast<size_t>(-1))
|
||||
{
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
exit(1);
|
||||
@ -86,9 +74,9 @@ int strcol(const char *const str)
|
||||
|
||||
wchar_t *wcstring = new wchar_t[length];
|
||||
|
||||
if (mbstowcs(wcstring, str, length) == (size_t)-1)
|
||||
if (mbstowcs(wcstring, str, length) == static_cast<size_t>(-1))
|
||||
{
|
||||
if (wcstring != NULL)
|
||||
if (wcstring != nullptr)
|
||||
delete[] wcstring;
|
||||
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
@ -102,7 +90,7 @@ int strcol(const char *const str)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (wcstring != NULL)
|
||||
if (wcstring != nullptr)
|
||||
delete[] wcstring;
|
||||
|
||||
return width;
|
||||
@ -168,7 +156,7 @@ size_t outputlabel(const long double label, ostringstream &strm)
|
||||
long double intpart = 0;
|
||||
long double fractionpart = abs(modf(label, &intpart));
|
||||
|
||||
for (unsigned int i = 0; i < (sizeof fractions / sizeof fractions[0]) and !output; ++i)
|
||||
for (unsigned int i = 0; i < size(fractions) and !output; ++i)
|
||||
{
|
||||
if (abs(fractionpart - fractionvalues[i]) < DBL_EPSILON)
|
||||
{
|
||||
@ -224,9 +212,9 @@ size_t outputlabel(const long double label, ostringstream &strm)
|
||||
}
|
||||
|
||||
// Output graph
|
||||
int graph(const size_t height, const size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, unsigned short **array, const graphoptions &aoptions)
|
||||
int graph(const size_t height, const size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const vector<vector<unsigned short>> &array, const graphoptions &aoptions)
|
||||
{
|
||||
if (array == NULL)
|
||||
if (!size(array))
|
||||
return 1;
|
||||
|
||||
const bool border = aoptions.border;
|
||||
@ -235,7 +223,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
const char *const title = aoptions.title;
|
||||
const unsigned int style = aoptions.style;
|
||||
|
||||
if (style >= (sizeof styles / sizeof styles[0]))
|
||||
if (style >= size(styles))
|
||||
return 1;
|
||||
|
||||
if (height == 0)
|
||||
@ -282,7 +270,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
|
||||
setlocale(LC_CTYPE, "");
|
||||
|
||||
if (title != NULL and title[0] != '\0')
|
||||
if (title != nullptr and title[0] != '\0')
|
||||
cout << wrap(title, w.ws_col) << "\n";
|
||||
|
||||
for (unsigned int i = 0; i < height; i += 4)
|
||||
@ -296,12 +284,12 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
if (border and axislabel and axisunitslabel)
|
||||
{
|
||||
bool output = false;
|
||||
long double label;
|
||||
long double label = 0;
|
||||
int adivisor = divisor;
|
||||
if (i < yaxis)
|
||||
adivisor = -adivisor;
|
||||
|
||||
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or !axislabel) and !output; k += adivisor)
|
||||
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and !output; k += adivisor)
|
||||
{
|
||||
if (i <= k and (i + 4) > k)
|
||||
{
|
||||
@ -340,7 +328,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
if (i < yaxis)
|
||||
adivisor = -adivisor;
|
||||
|
||||
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or !axislabel) and !output; k += adivisor)
|
||||
for (long double k = yaxis + adivisor; ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and !output; k += adivisor)
|
||||
{
|
||||
if (i <= k and (i + 4) > k)
|
||||
{
|
||||
@ -368,7 +356,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
if (j < xaxis)
|
||||
adivisor = -adivisor;
|
||||
|
||||
for (long double k = xaxis + adivisor; ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and (j < (width - 4) or !axislabel) and !output; k += adivisor)
|
||||
for (long double k = xaxis + adivisor; ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and j < (width - 4) and !output; k += adivisor)
|
||||
{
|
||||
if (j <= k and (j + 2) > k)
|
||||
{
|
||||
@ -400,7 +388,7 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
}
|
||||
else if (yaxislabel and axislabel and axisunitslabel)
|
||||
{
|
||||
long double label;
|
||||
long double label = 0;
|
||||
int adivisor = divisor;
|
||||
if (j < xaxis)
|
||||
{
|
||||
@ -497,19 +485,24 @@ int graph(const size_t height, const size_t width, const long double xmin, const
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Convert array to graph and output
|
||||
// Convert one or more arrays to graph and output
|
||||
template <typename T>
|
||||
int graph(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const size_t rows, T **array, const graphoptions &aoptions)
|
||||
int graphs(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const T &arrays, const graphoptions &aoptions = defaultoptions)
|
||||
{
|
||||
if (rows == 0)
|
||||
if (!size(arrays))
|
||||
return 1;
|
||||
|
||||
if (array == NULL)
|
||||
if (!all_of(begin(arrays), end(arrays), [](const auto &array)
|
||||
{ return all_of(begin(array), end(array), [](const auto &x)
|
||||
{ return size(x) == 2; }); }))
|
||||
{
|
||||
cerr << "Error: The arrays must have two columns.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
const unsigned int color = aoptions.color;
|
||||
|
||||
if (color >= (sizeof colors / sizeof colors[0]))
|
||||
if (color >= size(colors))
|
||||
return 1;
|
||||
|
||||
struct winsize w;
|
||||
@ -538,32 +531,22 @@ int graph(size_t height, size_t width, long double xmin, long double xmax, long
|
||||
|
||||
if (xmin == 0 and xmax == 0)
|
||||
{
|
||||
xmin = numeric_limits<T>::max();
|
||||
xmax = numeric_limits<T>::min();
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
{
|
||||
if (array[i][0] < xmin)
|
||||
xmin = array[i][0];
|
||||
|
||||
if (array[i][0] > xmax)
|
||||
xmax = array[i][0];
|
||||
}
|
||||
const auto compare = [](const auto &a, const auto &b)
|
||||
{ return a[0] < b[0]; };
|
||||
const auto result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto ¤t, const auto &array)
|
||||
{ const auto minmax = minmax_element(begin(array), end(array), compare); return make_pair(min(current.first, *minmax.first, compare), max(current.second, *minmax.second, compare)); });
|
||||
xmin = result.first[0];
|
||||
xmax = result.second[0];
|
||||
}
|
||||
|
||||
if (ymin == 0 and ymax == 0)
|
||||
{
|
||||
ymin = numeric_limits<T>::max();
|
||||
ymax = numeric_limits<T>::min();
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
{
|
||||
if (array[i][1] < ymin)
|
||||
ymin = array[i][1];
|
||||
|
||||
if (array[i][1] > ymax)
|
||||
ymax = array[i][1];
|
||||
}
|
||||
const auto compare = [](const auto &a, const auto &b)
|
||||
{ return a[1] < b[1]; };
|
||||
const auto result = accumulate(begin(arrays), end(arrays), make_pair(arrays[0][0], arrays[0][0]), [compare](const auto ¤t, const auto &array)
|
||||
{ const auto minmax = minmax_element(begin(array), end(array), compare); return make_pair(min(current.first, *minmax.first, compare), max(current.second, *minmax.second, compare)); });
|
||||
ymin = result.first[1];
|
||||
ymax = result.second[1];
|
||||
}
|
||||
|
||||
if (xmin >= xmax)
|
||||
@ -583,46 +566,65 @@ int graph(size_t height, size_t width, long double xmin, long double xmax, long
|
||||
const long double xaxis = width - (xmax * xscl);
|
||||
const long double yaxis = ymax * yscl;
|
||||
|
||||
unsigned short **aarray;
|
||||
aarray = new unsigned short *[width];
|
||||
for (unsigned int i = 0; i < width; ++i)
|
||||
aarray[i] = new unsigned short[height];
|
||||
vector<vector<unsigned short>> aarray(width, vector<unsigned short>(height, 0));
|
||||
|
||||
for (unsigned int i = 0; i < width; ++i)
|
||||
for (unsigned int j = 0; j < height; ++j)
|
||||
aarray[i][j] = 0;
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < size(arrays); ++j)
|
||||
{
|
||||
if (array[i][0] >= xmin and array[i][0] < xmax and array[i][1] >= ymin and array[i][1] < ymax)
|
||||
{
|
||||
const long long x = (array[i][0] * xscl) + xaxis;
|
||||
const long long y = (yaxis - (array[i][1] * yscl)) - 1;
|
||||
auto array = arrays[j];
|
||||
const unsigned int color = (j % (size(colors) - 2)) + 3;
|
||||
|
||||
aarray[x][y] = color + 1;
|
||||
for (unsigned int i = 0; i < size(array); ++i)
|
||||
{
|
||||
if (array[i][0] >= xmin and array[i][0] < xmax and array[i][1] >= ymin and array[i][1] < ymax)
|
||||
{
|
||||
const long long x = (array[i][0] * xscl) + xaxis;
|
||||
const long long y = (yaxis - (array[i][1] * yscl)) - 1;
|
||||
|
||||
if (aarray[x][y])
|
||||
{
|
||||
if (aarray[x][y] != color)
|
||||
aarray[x][y] = 1;
|
||||
}
|
||||
else
|
||||
aarray[x][y] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int code = graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, aarray, aoptions);
|
||||
}
|
||||
|
||||
if (aarray != NULL)
|
||||
{
|
||||
for (unsigned int i = 0; i < width; ++i)
|
||||
delete[] aarray[i];
|
||||
// Convert single array to graph and output
|
||||
template <typename T>
|
||||
int graph(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const T &aarray, const graphoptions &aoptions = defaultoptions)
|
||||
{
|
||||
const std::array<T, 1> aaarray = {aarray};
|
||||
|
||||
delete[] aarray;
|
||||
}
|
||||
return graphs(height, width, xmin, xmax, ymin, ymax, aaarray, aoptions);
|
||||
}
|
||||
|
||||
return code;
|
||||
// Convert single array to graph and output
|
||||
template <typename T>
|
||||
int graph(size_t height, size_t width, long double xmin, long double xmax, long double ymin, long double ymax, const size_t rows, T **aarray, const graphoptions &aoptions = defaultoptions)
|
||||
{
|
||||
if (rows == 0)
|
||||
return 1;
|
||||
|
||||
const size_t columns = 2;
|
||||
vector<std::array<T, columns>> aaarray(rows);
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
copy(aarray[i], aarray[i] + columns, aaarray[i].begin());
|
||||
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, aoptions);
|
||||
}
|
||||
|
||||
// Convert one or more functions to graph and output
|
||||
template <typename T>
|
||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const size_t numfunctions, T (*functions[])(T), const graphoptions &aoptions)
|
||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const size_t numfunctions, function<T(T)> functions[], const graphoptions &aoptions = defaultoptions)
|
||||
{
|
||||
const unsigned int color = aoptions.color;
|
||||
|
||||
if (color >= (sizeof colors / sizeof colors[0]))
|
||||
if (color >= size(colors))
|
||||
return 1;
|
||||
|
||||
if (numfunctions == 0)
|
||||
@ -671,18 +673,11 @@ int graph(size_t height, size_t width, const long double xmin, const long double
|
||||
const long double xaxis = width - (xmax * xscl);
|
||||
const long double yaxis = ymax * yscl;
|
||||
|
||||
unsigned short **array;
|
||||
array = new unsigned short *[width];
|
||||
for (unsigned int i = 0; i < width; ++i)
|
||||
array[i] = new unsigned short[height];
|
||||
|
||||
for (unsigned int i = 0; i < width; ++i)
|
||||
for (unsigned int j = 0; j < height; ++j)
|
||||
array[i][j] = 0;
|
||||
vector<vector<unsigned short>> array(width, vector<unsigned short>(height, 0));
|
||||
|
||||
for (unsigned int j = 0; j < numfunctions; ++j)
|
||||
{
|
||||
unsigned short acolor = numfunctions == 1 ? color + 1 : (j % ((sizeof colors / sizeof colors[0]) - 2)) + 3;
|
||||
unsigned short acolor = numfunctions == 1 ? color + 1 : (j % (size(colors) - 2)) + 3;
|
||||
|
||||
for (long double i = 0; i < rows; i += 0.5)
|
||||
{
|
||||
@ -705,25 +700,23 @@ int graph(size_t height, size_t width, const long double xmin, const long double
|
||||
}
|
||||
}
|
||||
|
||||
int code = graph(height, width, xmin, xmax, ymin, ymax, array, aoptions);
|
||||
|
||||
if (array != NULL)
|
||||
{
|
||||
for (unsigned int i = 0; i < width; ++i)
|
||||
delete[] array[i];
|
||||
|
||||
delete[] array;
|
||||
}
|
||||
|
||||
return code;
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, array, aoptions);
|
||||
}
|
||||
|
||||
// Convert single function to function array and output
|
||||
template <typename T>
|
||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, T afunction(T), const graphoptions &aoptions)
|
||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, const function<T(T)> &afunction, const graphoptions &aoptions = defaultoptions)
|
||||
{
|
||||
T(*functions[])
|
||||
(T) = {afunction};
|
||||
std::function<T(T)> afunctions[] = {afunction};
|
||||
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, 1, functions, aoptions);
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, 1, afunctions, aoptions);
|
||||
}
|
||||
|
||||
// Convert single function to function array and output
|
||||
template <typename T>
|
||||
int graph(size_t height, size_t width, const long double xmin, const long double xmax, const long double ymin, const long double ymax, T afunction(T), const graphoptions &aoptions = defaultoptions)
|
||||
{
|
||||
std::function<T(T)> afunctions[] = {afunction};
|
||||
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, 1, afunctions, aoptions);
|
||||
}
|
||||
|
@ -2,20 +2,20 @@
|
||||
|
||||
### Usage
|
||||
|
||||
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`.
|
||||
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`. See the [tables.py](tables.py) file for full usage information.
|
||||
|
||||
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
|
||||
|
||||
Run with: `python3 test.py`.
|
||||
|
||||
#### Output char array as table
|
||||
#### Output str array as table
|
||||
|
||||
```py
|
||||
import tables
|
||||
|
||||
# Set array
|
||||
|
||||
tables.array(array, None, None, headerrow=True, headercolumn=True)
|
||||
tables.array(array, headerrow=True, headercolumn=True)
|
||||
```
|
||||
|
||||
Table cells can contain [Unicode characters](https://en.wikipedia.org/wiki/List_of_Unicode_characters), but not newlines and tabs.
|
||||
@ -42,9 +42,9 @@ Output same as example above.
|
||||
```py
|
||||
import tables
|
||||
|
||||
# Set array
|
||||
# Set array, can be any sequence data type
|
||||
|
||||
tables.array(array, None, None)
|
||||
tables.array(array)
|
||||
```
|
||||
|
||||

|
||||
@ -60,7 +60,7 @@ sortdimension = 0 # Column to sort by
|
||||
|
||||
array = sorted(array, key=lambda x: x[sortdimension])
|
||||
|
||||
tables.array(array, None, None)
|
||||
tables.array(array)
|
||||
```
|
||||
|
||||

|
||||
@ -82,6 +82,22 @@ tables.function(xmin, xmax, xscl, afunction, headerrow=True)
|
||||
|
||||

|
||||
|
||||
#### Output lambda function as table
|
||||
|
||||
```py
|
||||
import tables
|
||||
|
||||
xmin = -10
|
||||
xmax = 10
|
||||
xscl = 2
|
||||
|
||||
afunction = lambda x: x + 1
|
||||
|
||||
tables.function(xmin, xmax, xscl, afunction, headerrow=True)
|
||||
```
|
||||
|
||||
Output same as example above.
|
||||
|
||||
#### Output multiple functions as table
|
||||
|
||||
```py
|
||||
@ -105,6 +121,23 @@ tables.functions(xmin, xmax, xscl, functions, headerrow=True)
|
||||
|
||||

|
||||
|
||||
#### Output multiple lambda functions as table
|
||||
|
||||
```py
|
||||
import tables
|
||||
|
||||
xmin = -10
|
||||
xmax = 10
|
||||
xscl = 2
|
||||
|
||||
# Function parameter and return value can be any data type, as long as they are the same
|
||||
functions = [lambda x: 2 * x, lambda x: x ** 2]
|
||||
|
||||
tables.functions(xmin, xmax, xscl, functions, headerrow=True)
|
||||
```
|
||||
|
||||
Output same as example above.
|
||||
|
||||
### Options
|
||||
|
||||
#### Header row
|
||||
@ -182,7 +215,7 @@ Values:
|
||||
|
||||
### Usage
|
||||
|
||||
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`.
|
||||
Requires Python 3.5 or greater and the [wcwidth library](https://pypi.org/project/wcwidth/), which users can install with: `pip3 install wcwidth`. See the [graphs.py](graphs.py) file for full usage information.
|
||||
|
||||
Complete versions of all of the examples below and more can be found in the [test.py](test.py) file.
|
||||
|
||||
@ -190,7 +223,7 @@ Run with: `python3 test.py`.
|
||||
|
||||
If `height` is `0`, it will be set to the current height of the terminal (number of rows times four). If `width` is `0`, it will be set to the current width of the terminal (number of columns times two).
|
||||
|
||||
#### Output array as plot
|
||||
#### Output single array as plot
|
||||
|
||||
```py
|
||||
import graphs
|
||||
@ -203,7 +236,7 @@ xmax = 20
|
||||
ymin = -20
|
||||
ymax = 20
|
||||
|
||||
# Set array
|
||||
# Set array, can be any sequence data type, but must have exactly two columns
|
||||
|
||||
graphs.array(height, width, xmin, xmax, ymin, ymax, array)
|
||||
```
|
||||
@ -212,6 +245,8 @@ If `xmin` and `xmax` are both `0`, they will be set to the respective minimum an
|
||||
|
||||

|
||||
|
||||
Use `graphs.arrays()` to plot multiple arrays, which can be of different sizes.
|
||||
|
||||
#### Output single function as graph
|
||||
|
||||
```py
|
||||
@ -233,6 +268,26 @@ graphs.function(height, width, xmin, xmax, ymin, ymax, afunction)
|
||||
|
||||

|
||||
|
||||
#### Output lambda function as graph
|
||||
|
||||
```py
|
||||
import graphs
|
||||
|
||||
height = 160
|
||||
width = 160
|
||||
|
||||
xmin = -20
|
||||
xmax = 20
|
||||
ymin = -20
|
||||
ymax = 20
|
||||
|
||||
afunction = lambda x: x + 1
|
||||
|
||||
graphs.function(height, width, xmin, xmax, ymin, ymax, afunction)
|
||||
```
|
||||
|
||||
Output same as example above.
|
||||
|
||||
#### Output multiple functions as graph
|
||||
|
||||
```py
|
||||
@ -260,6 +315,27 @@ graphs.functions(height, width, xmin, xmax, ymin, ymax, functions)
|
||||
|
||||

|
||||
|
||||
#### Output multiple lambda functions as graph
|
||||
|
||||
```py
|
||||
import graphs
|
||||
|
||||
height = 160
|
||||
width = 160
|
||||
|
||||
xmin = -20
|
||||
xmax = 20
|
||||
ymin = -20
|
||||
ymax = 20
|
||||
|
||||
# Function parameter and return value can be any data type, as long as they are the same
|
||||
functions = [lambda x: 2 * x, lambda x: x ** 2]
|
||||
|
||||
graphs.functions(height, width, xmin, xmax, ymin, ymax, functions)
|
||||
```
|
||||
|
||||
Output same as example above.
|
||||
|
||||
### Options
|
||||
|
||||
#### Border/Axis
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Teal Dulcet, CS546
|
||||
@ -113,7 +113,7 @@ def outputlabel(label: float) -> Tuple[int, str]:
|
||||
return length, strm
|
||||
|
||||
|
||||
def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, title: Optional[str]=None) -> int:
|
||||
def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, array: List[List[int]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, title: Optional[str] = None) -> int:
|
||||
"""Output graph"""
|
||||
if not array:
|
||||
return 1
|
||||
@ -175,7 +175,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
adivisor = -divisor if i < yaxis else divisor
|
||||
|
||||
k = yaxis + adivisor
|
||||
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or not axislabel) and not output:
|
||||
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and not output:
|
||||
if (i <= k and (i + 4) > k):
|
||||
label = ymax - (k / yscl)
|
||||
|
||||
@ -202,7 +202,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
adivisor = -divisor if i < yaxis else divisor
|
||||
|
||||
k = yaxis + adivisor
|
||||
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and (i >= 4 or not axislabel) and not output:
|
||||
while ((i < yaxis and k >= i) or (i > yaxis and k < (i + 4))) and i >= 4 and not output:
|
||||
if i <= k and (i + 4) > k:
|
||||
strm += styles[style][7]
|
||||
output = True
|
||||
@ -220,7 +220,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
adivisor = -divisor if j < xaxis else divisor
|
||||
|
||||
k = xaxis + adivisor
|
||||
while ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and (j < (width - 4) or not axislabel) and not output:
|
||||
while ((j < xaxis and k >= j) or (j > xaxis and k < (j + 2))) and j < (width - 4) and not output:
|
||||
if j <= k and (j + 2) > k:
|
||||
strm += styles[style][3]
|
||||
output = True
|
||||
@ -314,7 +314,7 @@ def graph(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
return 0
|
||||
|
||||
|
||||
def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
||||
def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarrays: Sequence[Sequence[Sequence[float]]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||
"""Convert one or more arrays to graph and output"""
|
||||
if not aarrays:
|
||||
return 1
|
||||
@ -328,6 +328,12 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
|
||||
w = shutil.get_terminal_size()
|
||||
|
||||
if height == 0:
|
||||
height = w.lines * 4
|
||||
|
||||
if width == 0:
|
||||
width = w.columns * 2
|
||||
|
||||
aheight = height // 4
|
||||
awidth = width // 2
|
||||
|
||||
@ -365,7 +371,8 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
aaarray = [[0 for j in range(height)] for i in range(width)]
|
||||
|
||||
for j, aarray in enumerate(aarrays):
|
||||
acolor = color + 1 if len(aarrays) == 1 else (j % (len(colors) - 2)) + 3
|
||||
acolor = color + 1 if len(aarrays) == 1 else (j %
|
||||
(len(colors) - 2)) + 3
|
||||
|
||||
for i in aarray:
|
||||
if i[0] >= xmin and i[0] < xmax and i[1] >= ymin and i[1] < ymax:
|
||||
@ -381,17 +388,17 @@ def arrays(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax:
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, aaarray, border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, title=title)
|
||||
|
||||
|
||||
def array(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
||||
def array(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, aarray: Sequence[Sequence[float]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||
"""Convert single array to graph and output"""
|
||||
return arrays(height, width, xmin, xmax, ymin, ymax, [aarray], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)
|
||||
|
||||
|
||||
def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
||||
def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ymax: float, afunctions: Sequence[Callable[[float], float]], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||
"""Convert one or more functions to graph and output"""
|
||||
if color < 0 or color >= len(colors):
|
||||
return 1
|
||||
|
||||
if len(afunctions) == 0:
|
||||
if not afunctions:
|
||||
return 1
|
||||
|
||||
w = shutil.get_terminal_size()
|
||||
@ -402,8 +409,8 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
||||
if width == 0:
|
||||
width = w.columns * 2
|
||||
|
||||
aheight = height / 4
|
||||
awidth = width / 2
|
||||
aheight = height // 4
|
||||
awidth = width // 2
|
||||
|
||||
if aheight > w.lines:
|
||||
print("The height of the graph ({0}) is greater then the height of the terminal ({1}).".format(
|
||||
@ -453,6 +460,6 @@ def functions(height: int, width: int, xmin: float, xmax: float, ymin: float, ym
|
||||
return graph(height, width, xmin, xmax, ymin, ymax, array, border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, title=title)
|
||||
|
||||
|
||||
def function(height, width, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool=True, axislabel: bool=True, axisunitslabel: bool=True, style: int=2, color: int=2, title: Optional[str]=None) -> int:
|
||||
def function(height, width, xmin: float, xmax: float, ymin: float, ymax: float, afunction: Callable[[float], float], border: bool = True, axislabel: bool = True, axisunitslabel: bool = True, style: int = 2, color: int = 2, title: Optional[str] = None) -> int:
|
||||
"""Convert single function to function array and output"""
|
||||
return functions(height, width, xmin, xmax, ymin, ymax, [afunction], border=border, axislabel=axislabel, axisunitslabel=axisunitslabel, style=style, color=color, title=title)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Teal Dulcet, CS546
|
||||
@ -39,7 +39,7 @@ def strcol(str: str) -> int:
|
||||
# return len(str)
|
||||
|
||||
|
||||
def table(array: List[List[str]], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
||||
def table(array: List[List[str]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||
"""Output char array as table"""
|
||||
if not array:
|
||||
return 1
|
||||
@ -158,7 +158,7 @@ def table(array: List[List[str]], headerrow: bool=False, headercolumn: bool=Fals
|
||||
return 0
|
||||
|
||||
|
||||
def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]], aheadercolumn: Optional[Sequence[Any]], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
||||
def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]] = None, aheadercolumn: Optional[Sequence[Any]] = None, headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||
"""Convert array to char array and output as table"""
|
||||
if not aarray:
|
||||
return 1
|
||||
@ -220,9 +220,9 @@ def array(aarray: Sequence[Sequence[Any]], aheaderrow: Optional[Sequence[Any]],
|
||||
return table(aaarray, headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
||||
|
||||
|
||||
def functions(xmin: float, xmax: float, xscl: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
||||
def functions(xmin: float, xmax: float, xscl: float, afunctions: Sequence[Callable[[float], float]], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||
"""Convert one or more functions to array and output as table"""
|
||||
if len(afunctions) == 0:
|
||||
if not afunctions:
|
||||
return 1
|
||||
|
||||
if xmin >= xmax:
|
||||
@ -258,6 +258,6 @@ def functions(xmin: float, xmax: float, xscl: float, afunctions: Sequence[Callab
|
||||
return array(aarray, aheaderrow, None, headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
||||
|
||||
|
||||
def function(xmin: float, xmax: float, xscl: float, afunction: Callable[[float], float], headerrow: bool=False, headercolumn: bool=False, tableborder: bool=True, cellborder: bool=False, padding: int=1, alignment: bool=False, title: Optional[str]=None, style: int=2) -> int:
|
||||
def function(xmin: float, xmax: float, xscl: float, afunction: Callable[[float], float], headerrow: bool = False, headercolumn: bool = False, tableborder: bool = True, cellborder: bool = False, padding: int = 1, alignment: bool = False, title: Optional[str] = None, style: int = 2) -> int:
|
||||
"""Convert single function to array and output as table"""
|
||||
return functions(xmin, xmax, xscl, [afunction], headerrow=headerrow, headercolumn=headercolumn, tableborder=tableborder, cellborder=cellborder, padding=padding, alignment=alignment, title=title, style=style)
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Teal Dulcet, CS546
|
||||
@ -78,11 +78,16 @@ for k in range(len(tables.styles)):
|
||||
print("\nOutput single function as table\n")
|
||||
for k in range(len(tables.styles)):
|
||||
tables.function(xmin, xmax, xscl, afunction, headerrow=True, style=k)
|
||||
for k in range(len(tables.styles)):
|
||||
tables.function(xmin, xmax, xscl, lambda x: x + 1, headerrow=True, style=k)
|
||||
|
||||
print("\nOutput multiple functions as table\n")
|
||||
for k in range(len(tables.styles)):
|
||||
tables.functions(xmin, xmax, xscl, [
|
||||
function1, function2], headerrow=True, style=k)
|
||||
for k in range(len(tables.styles)):
|
||||
tables.functions(xmin, xmax, xscl, [
|
||||
lambda x: 2 * x, lambda x: x ** 2], headerrow=True, style=k)
|
||||
|
||||
height = 160
|
||||
width = 160
|
||||
@ -92,20 +97,26 @@ xmax = 20
|
||||
ymin = -20
|
||||
ymax = 20
|
||||
|
||||
print("\nOutput array as plot\n")
|
||||
array = [[i + j for j in range(2)] for i in range(10)]
|
||||
print("\nOutput single array as plot\n")
|
||||
array = [range(i, i + 2) for i in range(10)]
|
||||
for k in range(len(graphs.styles)):
|
||||
graphs.array(height, width, xmin, xmax, ymin, ymax, array, style=k)
|
||||
|
||||
print("\nOutput single function as graph\n")
|
||||
for k in range(len(graphs.styles)):
|
||||
graphs.function(height, width, xmin, xmax, ymin, ymax, afunction, style=k)
|
||||
for k in range(len(graphs.styles)):
|
||||
graphs.function(height, width, xmin, xmax, ymin,
|
||||
ymax, lambda x: x + 1, style=k)
|
||||
|
||||
print("\nOutput multiple functions as graph\n")
|
||||
for k in range(len(graphs.styles)):
|
||||
graphs.functions(height, width, xmin, xmax, ymin,
|
||||
ymax, [function1, function2], style=k)
|
||||
for k in range(len(graphs.styles)):
|
||||
graphs.functions(height, width, xmin, xmax, ymin, ymax, [
|
||||
lambda x: 2 * x, lambda x: x ** 2], style=k)
|
||||
|
||||
for k in range(len(graphs.styles)):
|
||||
graphs.functions(height, width, -(2 * math.pi), 2 *
|
||||
math.pi, -4, 4, [math.sin, math.cos, math.tan], axisunitslabel=False, style=k)
|
||||
graphs.functions(height, width, -(2 * math.pi), 2 * math.pi, -4,
|
||||
4, [math.sin, math.cos, math.tan], axisunitslabel=False, style=k)
|
||||
|
352
tables.cpp
352
tables.cpp
@ -1,27 +1,29 @@
|
||||
// Teal Dulcet, CS546
|
||||
|
||||
// Compile: g++ -Wall -g -O3 tables.cpp -o tables
|
||||
// Compile: g++ -Wall -g -O3 -std=c++17 tables.cpp -o tables
|
||||
|
||||
// Run: ./tables
|
||||
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <vector>
|
||||
#include "tables.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
long double afunction(long double x)
|
||||
constexpr long double afunction(long double x)
|
||||
{
|
||||
return x + 1;
|
||||
}
|
||||
|
||||
long double function1(long double x)
|
||||
constexpr long double function1(long double x)
|
||||
{
|
||||
return 2 * x;
|
||||
}
|
||||
|
||||
long double function2(long double x)
|
||||
constexpr long double function2(long double x)
|
||||
{
|
||||
return pow(x, 2);
|
||||
}
|
||||
@ -32,8 +34,8 @@ int sortdimension = 0;
|
||||
/* template <typename T>
|
||||
int compare(const void *pa, const void *pb)
|
||||
{
|
||||
const T *a = *(const T **)pa;
|
||||
const T *b = *(const T **)pb;
|
||||
const T a = *(const T *)pa;
|
||||
const T b = *(const T *)pb;
|
||||
|
||||
if (a[sortdimension] == b[sortdimension])
|
||||
{
|
||||
@ -58,7 +60,7 @@ int compare(const void *pa, const void *pb)
|
||||
} */
|
||||
|
||||
template <typename T>
|
||||
bool compare(const T *a, const T *b)
|
||||
bool compare(const T &a, const T &b)
|
||||
{
|
||||
if (a[sortdimension] == b[sortdimension])
|
||||
for (int i = 0; i < dimensions; ++i)
|
||||
@ -77,6 +79,9 @@ int main()
|
||||
const long double xmax = 10;
|
||||
const long double xscl = 2; // 80 / (xmax - xmin);
|
||||
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
// Output array as table
|
||||
cout << "\nOutput array as table\n\n";
|
||||
{
|
||||
@ -91,14 +96,14 @@ int main()
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(rows, columns, array, NULL, NULL, aoptions);
|
||||
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||
}
|
||||
|
||||
if (array != NULL)
|
||||
if (array != nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
delete[] array[i];
|
||||
@ -106,6 +111,38 @@ int main()
|
||||
delete[] array;
|
||||
}
|
||||
}
|
||||
{
|
||||
array<array<long long, columns>, rows> aarray;
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
aarray[i][j] = rand();
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
vector<vector<long long>> array(rows, vector<long long>(columns));
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
array[i][j] = rand();
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
long double **array;
|
||||
array = new long double *[rows];
|
||||
@ -118,14 +155,14 @@ int main()
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(rows, columns, array, NULL, NULL, aoptions);
|
||||
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||
}
|
||||
|
||||
if (array != NULL)
|
||||
if (array != nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
delete[] array[i];
|
||||
@ -133,6 +170,38 @@ int main()
|
||||
delete[] array;
|
||||
}
|
||||
}
|
||||
{
|
||||
array<array<long double, columns>, rows> aarray;
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
aarray[i][j] = static_cast<long double>(rand()) / static_cast<long double>(RAND_MAX);
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
vector<vector<long double>> array(rows, vector<long double>(columns));
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
array[i][j] = static_cast<long double>(rand()) / static_cast<long double>(RAND_MAX);
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
// Output char array as table
|
||||
cout << "\nOutput char array as table\n\n";
|
||||
{
|
||||
@ -146,12 +215,32 @@ int main()
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(rows, columns, array, NULL, NULL, aoptions);
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
const array<array<string, columns>, rows> aarray = {{{"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"},
|
||||
{"Header column 2", "Data 1", "Data 2", "Data 3", "Data 4"},
|
||||
{"Header column 3", "Data 5", "Data 6", "Data 7", "Data 8"},
|
||||
{"Header column 4", "Data 9", "Data 10", "Data 11", "Data 12"},
|
||||
{"Header column 5", "Data 13", "Data 14", "Data 15", "Data 16"}}};
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
// Output array as table with separate header row and column
|
||||
@ -172,12 +261,142 @@ int main()
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
// tableoptions aoptions{.headerrow = true, .headercolumn = true};
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(rows, columns, array, headerrow, headercolumn, aoptions);
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
const size_t rows = 4;
|
||||
const size_t columns = 4;
|
||||
|
||||
const array<array<string, columns>, rows> aarray = {{{"Data 1", "Data 2", "Data 3", "Data 4"},
|
||||
{"Data 5", "Data 6", "Data 7", "Data 8"},
|
||||
{"Data 9", "Data 10", "Data 11", "Data 12"},
|
||||
{"Data 13", "Data 14", "Data 15", "Data 16"}}};
|
||||
|
||||
const string headerrow[] = {"Header row/column 1", "Header row 2", "Header row 3", "Header row 4", "Header row 5"};
|
||||
const string headercolumn[] = {"Header column 2", "Header column 3", "Header column 4", "Header column 5"};
|
||||
|
||||
vector<string> aheaderrow(headerrow, headerrow + (rows + 1) - 1);
|
||||
vector<string> aheadercolumn(headerrow, headerrow + 1);
|
||||
aheadercolumn.insert(aheadercolumn.end(), headercolumn, headercolumn + columns - 1);
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
{
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.cellborder = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.headerrow = true, .headercolumn = true, .cellborder = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.headerrow = true, .headercolumn = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = aheaderrow.data();
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.headerrow = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = aheadercolumn.data();
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.headercolumn = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.cellborder = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.cellborder = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.tableborder = false;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.tableborder = false, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
tableoptions aoptions;
|
||||
aoptions.tableborder = false;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.tableborder = false, .headerrow = true, .headercolumn = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = aheaderrow.data();
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.tableborder = false;
|
||||
aoptions.headerrow = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.tableborder = false, .headerrow = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = aheadercolumn.data();
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.tableborder = false;
|
||||
aoptions.headercolumn = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.tableborder = false, .headercolumn = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
{
|
||||
string *headerrow = nullptr;
|
||||
string *headercolumn = nullptr;
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.tableborder = false;
|
||||
aoptions.cellborder = true;
|
||||
aoptions.style = k;
|
||||
// tableoptions aoptions{.tableborder = false, .cellborder = true, .style = k};
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -192,15 +411,16 @@ int main()
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.boolalpha = true;
|
||||
// tableoptions aoptions{.boolalpha = true};
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(rows, columns, array, NULL, NULL, aoptions);
|
||||
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||
}
|
||||
|
||||
if (array != NULL)
|
||||
if (array != nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
delete[] array[i];
|
||||
@ -223,19 +443,19 @@ int main()
|
||||
dimensions = columns;
|
||||
sortdimension = 0;
|
||||
|
||||
// qsort(array, rows, sizeof(array[0]), compare<int>);
|
||||
sort(array, array + rows, compare<int>);
|
||||
// qsort(array, rows, sizeof(array[0]), compare<int *>);
|
||||
sort(array, array + rows, compare<int *>);
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(rows, columns, array, NULL, NULL, aoptions);
|
||||
table(rows, columns, array, nullptr, nullptr, aoptions);
|
||||
}
|
||||
|
||||
if (array != NULL)
|
||||
if (array != nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
delete[] array[i];
|
||||
@ -243,13 +463,71 @@ int main()
|
||||
delete[] array;
|
||||
}
|
||||
}
|
||||
{
|
||||
array<array<int, columns>, rows> aarray;
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
aarray[i][j] = rand();
|
||||
|
||||
dimensions = columns;
|
||||
sortdimension = 0;
|
||||
|
||||
sort(aarray.begin(), aarray.end(), compare<array<int, columns>>);
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(aarray, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
vector<vector<int>> array(rows, vector<int>(columns));
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
array[i][j] = rand();
|
||||
|
||||
dimensions = columns;
|
||||
sortdimension = 0;
|
||||
|
||||
sort(array.begin(), array.end(), compare<vector<int>>);
|
||||
|
||||
tableoptions aoptions;
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(array, headerrow, headercolumn, aoptions);
|
||||
}
|
||||
}
|
||||
// Output single function as table
|
||||
cout << "\nOutput single function as table\n\n";
|
||||
{
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tableoptions aoptions{.headerrow = true};
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(xmin, xmax, xscl, afunction, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
function<long double(long double)> afunction = [](auto x)
|
||||
{ return x + 1; };
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tableoptions aoptions{.headerrow = true};
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
@ -259,12 +537,30 @@ int main()
|
||||
// Output multiple functions as table
|
||||
cout << "\nOutput multiple functions as table\n\n";
|
||||
{
|
||||
long double (*functions[])(long double) = {function1, function2};
|
||||
function<long double(long double)> functions[] = {function1, function2};
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tableoptions aoptions{.headerrow = true};
|
||||
|
||||
for (unsigned int k = 0; k < (sizeof styles / sizeof styles[0]); ++k)
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
table(xmin, xmax, xscl, 2, functions, aoptions);
|
||||
}
|
||||
}
|
||||
{
|
||||
function<long double(long double)> functions[] = {[](auto x)
|
||||
{ return 2 * x; },
|
||||
[](auto x)
|
||||
{ return pow(x, 2); }};
|
||||
|
||||
tableoptions aoptions;
|
||||
aoptions.headerrow = true;
|
||||
// tableoptions aoptions{.headerrow = true};
|
||||
|
||||
for (unsigned int k = 0; k < size(styles); ++k)
|
||||
{
|
||||
aoptions.style = k;
|
||||
|
||||
|
258
tables.hpp
258
tables.hpp
@ -7,60 +7,49 @@
|
||||
#include <cwchar>
|
||||
#include <clocale>
|
||||
#include <cstdlib>
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <sys/ioctl.h>
|
||||
#include <unistd.h>
|
||||
#include <regex>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const char *const styles[][11] = {
|
||||
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //ASCII
|
||||
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, //Basic
|
||||
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light
|
||||
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, //Heavy
|
||||
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, //Double
|
||||
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, //Light Dashed
|
||||
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} //Heavy Dashed
|
||||
{"-", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // ASCII
|
||||
{"—", "|", "+", "+", "+", "+", "+", "+", "+", "+", "+"}, // Basic
|
||||
{"─", "│", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light
|
||||
{"━", "┃", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"}, // Heavy
|
||||
{"═", "║", "╔", "╦", "╗", "╠", "╬", "╣", "╚", "╩", "╝"}, // Double
|
||||
{"╌", "╎", "┌", "┬", "┐", "├", "┼", "┤", "└", "┴", "┘"}, // Light Dashed
|
||||
{"╍", "╏", "┏", "┳", "┓", "┣", "╋", "┫", "┗", "┻", "┛"} // Heavy Dashed
|
||||
};
|
||||
// {" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " "}};//No border
|
||||
|
||||
regex ansi(R"(\x1B\[(?:[0-9]+(?:;[0-9]+)*)?m)");
|
||||
|
||||
struct tableoptions
|
||||
{
|
||||
bool headerrow;
|
||||
bool headercolumn;
|
||||
bool tableborder;
|
||||
bool cellborder;
|
||||
unsigned int padding;
|
||||
ios_base &(*alignment)(ios_base &);
|
||||
bool boolalpha;
|
||||
char *title;
|
||||
unsigned int style;
|
||||
tableoptions(void);
|
||||
~tableoptions(void);
|
||||
bool headerrow = false;
|
||||
bool headercolumn = false;
|
||||
bool tableborder = true;
|
||||
bool cellborder = false;
|
||||
unsigned int padding = 1;
|
||||
ios_base &(*alignment)(ios_base &) = left;
|
||||
bool boolalpha = false;
|
||||
const char *title = nullptr;
|
||||
unsigned int style = 2;
|
||||
};
|
||||
|
||||
tableoptions::tableoptions(void)
|
||||
{
|
||||
headerrow = false;
|
||||
headercolumn = false;
|
||||
tableborder = true;
|
||||
cellborder = false;
|
||||
padding = 1;
|
||||
alignment = left;
|
||||
boolalpha = false;
|
||||
title = NULL;
|
||||
style = 2;
|
||||
}
|
||||
|
||||
tableoptions::~tableoptions(void)
|
||||
{
|
||||
}
|
||||
|
||||
const tableoptions tabledefaultoptions;
|
||||
const tableoptions defaultoptions;
|
||||
|
||||
// Number of columns needed to represent the string
|
||||
// Adapted from: https://stackoverflow.com/a/31124065
|
||||
int strcol(const char *const str)
|
||||
int strcol(const char *str)
|
||||
{
|
||||
const string astr = regex_replace(str, ansi, "");
|
||||
str = astr.c_str();
|
||||
|
||||
size_t length = strlen(str);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
if (iscntrl(str[i]))
|
||||
@ -69,8 +58,8 @@ int strcol(const char *const str)
|
||||
cout << "Control character: " << (int)str[i] << "\n";
|
||||
}
|
||||
|
||||
length = mbstowcs(NULL, str, 0);
|
||||
if (length == (size_t)-1)
|
||||
length = mbstowcs(nullptr, str, 0);
|
||||
if (length == static_cast<size_t>(-1))
|
||||
{
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
exit(1);
|
||||
@ -79,9 +68,9 @@ int strcol(const char *const str)
|
||||
|
||||
wchar_t *wcstring = new wchar_t[length];
|
||||
|
||||
if (mbstowcs(wcstring, str, length) == (size_t)-1)
|
||||
if (mbstowcs(wcstring, str, length) == static_cast<size_t>(-1))
|
||||
{
|
||||
if (wcstring != NULL)
|
||||
if (wcstring != nullptr)
|
||||
delete[] wcstring;
|
||||
|
||||
cerr << "\nError! mbstowcs failed. Invalid multibyte character.\n";
|
||||
@ -95,7 +84,7 @@ int strcol(const char *const str)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (wcstring != NULL)
|
||||
if (wcstring != nullptr)
|
||||
delete[] wcstring;
|
||||
|
||||
return width;
|
||||
@ -154,9 +143,10 @@ string wrap(const char *const str, const size_t line_length)
|
||||
}
|
||||
|
||||
// Output char array as table
|
||||
int table(const size_t rows, const size_t columns, char ***array, const tableoptions &aoptions)
|
||||
template <typename T>
|
||||
int table(const vector<vector<basic_string<T>>> &array, const tableoptions &aoptions)
|
||||
{
|
||||
if (array == NULL)
|
||||
if (!size(array))
|
||||
return 1;
|
||||
|
||||
const bool headerrow = aoptions.headerrow;
|
||||
@ -167,9 +157,12 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
||||
const char *const title = aoptions.title;
|
||||
const unsigned int style = aoptions.style;
|
||||
|
||||
if (style >= (sizeof styles / sizeof styles[0]))
|
||||
if (style >= size(styles))
|
||||
return 1;
|
||||
|
||||
const size_t rows = array.size();
|
||||
const size_t columns = array[0].size();
|
||||
|
||||
int columnwidth[columns];
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
columnwidth[j] = 0;
|
||||
@ -182,7 +175,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
{
|
||||
int cellwidth = strcol(array[i][j]);
|
||||
int cellwidth = strcol(array[i][j].c_str());
|
||||
if (cellwidth > columnwidth[j])
|
||||
columnwidth[j] = cellwidth;
|
||||
}
|
||||
@ -204,7 +197,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (title != NULL and title[0] != '\0')
|
||||
if (title != nullptr and title[0] != '\0')
|
||||
cout << wrap(title, w.ws_col) << "\n";
|
||||
|
||||
if (tableborder)
|
||||
@ -234,29 +227,25 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
||||
else if (tableborder or (i > 0 and j > 0 and headerrow) or (j > 1 and headercolumn))
|
||||
cout << " ";
|
||||
|
||||
const int difference = columnwidth[j] - strcol(array[i][j]);
|
||||
const int difference = columnwidth[j] - strcol(array[i][j].c_str());
|
||||
|
||||
if ((i == 0 and headerrow) or (j == 0 and headercolumn))
|
||||
{
|
||||
const int apadding = (difference / 2);
|
||||
|
||||
for (unsigned int k = 0; k < padding + apadding; ++k)
|
||||
cout << " ";
|
||||
cout << string(padding + apadding, ' ');
|
||||
|
||||
cout << "\e[1m" << array[i][j] << "\e[22m";
|
||||
|
||||
for (unsigned int k = 0; k < padding + (difference - apadding); ++k)
|
||||
cout << " ";
|
||||
cout << string(padding + (difference - apadding), ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int k = 0; k < padding; ++k)
|
||||
cout << " ";
|
||||
cout << string(padding, ' ');
|
||||
|
||||
cout << aoptions.alignment << setw(difference + strlen(array[i][j])) << array[i][j];
|
||||
cout << aoptions.alignment << setw(difference + array[i][j].length()) << array[i][j];
|
||||
|
||||
for (unsigned int k = 0; k < padding; ++k)
|
||||
cout << " ";
|
||||
cout << string(padding, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
@ -281,8 +270,7 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
||||
for (unsigned int k = 0; k < (2 * padding) + columnwidth[j]; ++k)
|
||||
cout << styles[style][0];
|
||||
else if (i < (rows - 1) and headercolumn)
|
||||
for (unsigned int k = 0; k < (2 * padding) + columnwidth[j]; ++k)
|
||||
cout << " ";
|
||||
cout << string((2 * padding) + columnwidth[j], ' ');
|
||||
|
||||
if (j == (columns - 1))
|
||||
{
|
||||
@ -329,29 +317,38 @@ int table(const size_t rows, const size_t columns, char ***array, const tableopt
|
||||
}
|
||||
|
||||
// Convert array to char array and output as table
|
||||
template <typename T>
|
||||
int table(size_t rows, size_t columns, const T &array, const char *const headerrow[], const char *const headercolumn[], const tableoptions &aoptions)
|
||||
template <typename T1, typename T2>
|
||||
int table(const T1 &aarray, T2 headerrow[] = nullptr, T2 headercolumn[] = nullptr, const tableoptions &aoptions = defaultoptions)
|
||||
{
|
||||
if (!size(aarray))
|
||||
return 1;
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int j = 0;
|
||||
|
||||
if (headerrow != NULL)
|
||||
size_t rows = size(aarray);
|
||||
size_t columns = size(aarray[0]);
|
||||
|
||||
if (!all_of(begin(aarray), end(aarray), [columns](auto &x)
|
||||
{ return size(x) == columns; }))
|
||||
{
|
||||
cerr << "Error: The rows of the array must have the same number of columns.";
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (headerrow != nullptr)
|
||||
++rows;
|
||||
|
||||
if (headercolumn != NULL)
|
||||
if (headercolumn != nullptr)
|
||||
++columns;
|
||||
|
||||
char ***aarray;
|
||||
aarray = new char **[rows];
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
aarray[i] = new char *[columns];
|
||||
vector<vector<string>> aaarray(rows, vector<string>(columns));
|
||||
|
||||
if (headerrow != NULL)
|
||||
if (headerrow != nullptr)
|
||||
{
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
{
|
||||
aarray[i][j] = new char[strlen(headerrow[j]) + 1];
|
||||
strcpy(aarray[i][j], headerrow[j]);
|
||||
aaarray[i][j] = headerrow[j];
|
||||
}
|
||||
|
||||
++i;
|
||||
@ -359,15 +356,14 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
|
||||
|
||||
for (unsigned int ii = 0; i < rows; ++i)
|
||||
{
|
||||
if (headercolumn != NULL)
|
||||
if (headercolumn != nullptr)
|
||||
{
|
||||
unsigned int ii = i;
|
||||
|
||||
if (headerrow != NULL)
|
||||
if (headerrow != nullptr)
|
||||
--ii;
|
||||
|
||||
aarray[i][j] = new char[strlen(headercolumn[ii]) + 1];
|
||||
strcpy(aarray[i][j], headercolumn[ii]);
|
||||
aaarray[i][j] = headercolumn[ii];
|
||||
|
||||
++j;
|
||||
}
|
||||
@ -379,10 +375,8 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
|
||||
if (aoptions.boolalpha)
|
||||
strm << boolalpha;
|
||||
|
||||
strm << array[ii][jj];
|
||||
string str = strm.str();
|
||||
aarray[i][j] = new char[str.length() + 1];
|
||||
strcpy(aarray[i][j], str.c_str());
|
||||
strm << aarray[ii][jj];
|
||||
aaarray[i][j] = strm.str();
|
||||
|
||||
++jj;
|
||||
}
|
||||
@ -391,26 +385,48 @@ int table(size_t rows, size_t columns, const T &array, const char *const headerr
|
||||
++ii;
|
||||
}
|
||||
|
||||
int code = table(rows, columns, aarray, aoptions);
|
||||
return table(aaarray, aoptions);
|
||||
}
|
||||
|
||||
if (aarray != NULL)
|
||||
template <typename T>
|
||||
int table(const size_t rows, const size_t columns, T **aarray, const char *const headerrow[] = nullptr, const char *const headercolumn[] = nullptr, const tableoptions &aoptions = defaultoptions)
|
||||
{
|
||||
vector<vector<T>> aaarray(rows, vector<T>(columns));
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
copy(aarray[i], aarray[i] + columns, aaarray[i].begin());
|
||||
|
||||
string *aheaderrow = nullptr;
|
||||
string *aheadercolumn = nullptr;
|
||||
|
||||
if (headerrow and headercolumn)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
{
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
delete[] aarray[i][j];
|
||||
vector<string> aaheaderrow(rows + 1);
|
||||
copy(headerrow, headerrow + rows + 1, aaheaderrow.begin());
|
||||
aheaderrow = aaheaderrow.data();
|
||||
|
||||
delete[] aarray[i];
|
||||
}
|
||||
delete[] aarray;
|
||||
vector<string> aaheadercolumn(columns);
|
||||
copy(headercolumn, headercolumn + columns, aaheadercolumn.begin());
|
||||
aheadercolumn = aaheadercolumn.data();
|
||||
}
|
||||
else if (headerrow)
|
||||
{
|
||||
vector<string> aaheaderrow(rows);
|
||||
copy(headerrow, headerrow + rows, aaheaderrow.begin());
|
||||
aheaderrow = aaheaderrow.data();
|
||||
}
|
||||
else if (headercolumn)
|
||||
{
|
||||
vector<string> aaheadercolumn(columns);
|
||||
copy(headercolumn, headercolumn + columns, aaheadercolumn.begin());
|
||||
aheadercolumn = aaheadercolumn.data();
|
||||
}
|
||||
|
||||
return code;
|
||||
return table(aaarray, aheaderrow, aheadercolumn, aoptions);
|
||||
}
|
||||
|
||||
// Convert one or more functions to array and output as table
|
||||
template <typename T>
|
||||
int table(const long double xmin, const long double xmax, const long double xscl, const size_t numfunctions, T (*functions[])(T), const tableoptions &aoptions)
|
||||
int table(const long double xmin, const long double xmax, const long double xscl, const size_t numfunctions, function<T(T)> functions[], const tableoptions &aoptions = defaultoptions)
|
||||
{
|
||||
if (numfunctions == 0)
|
||||
return 1;
|
||||
@ -433,75 +449,53 @@ int table(const long double xmin, const long double xmax, const long double xscl
|
||||
const char *const aheaderrow[] = {"x", "y"};
|
||||
// const char* const aheaderrow[] = {"", "x", "y"};
|
||||
|
||||
const size_t length = (sizeof aheaderrow / sizeof aheaderrow[0]);
|
||||
const size_t length = size(aheaderrow);
|
||||
|
||||
char **headerrow = new char *[columns];
|
||||
string *headerrow = new string[columns];
|
||||
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
{
|
||||
if (j < (length - 1) or numfunctions == 1)
|
||||
{
|
||||
headerrow[j] = new char[strlen(aheaderrow[j]) + 1];
|
||||
strcpy(headerrow[j], aheaderrow[j]);
|
||||
headerrow[j] = aheaderrow[j];
|
||||
}
|
||||
else
|
||||
{
|
||||
ostringstream strm;
|
||||
strm << aheaderrow[length - 1] << j - length + 2;
|
||||
string str = strm.str();
|
||||
headerrow[j] = new char[str.length() + 1];
|
||||
strcpy(headerrow[j], str.c_str());
|
||||
headerrow[j] = strm.str();
|
||||
}
|
||||
}
|
||||
|
||||
char **headercolumn = NULL;
|
||||
// headercolumn = new char *[rows + 1];
|
||||
string *headercolumn = nullptr;
|
||||
// headercolumn = new string[rows + 1];
|
||||
|
||||
// for (unsigned int i = 0; i < rows + 1; ++i)
|
||||
// {
|
||||
// ostringstream strm;
|
||||
// strm << i + 1;
|
||||
// string str = strm.str();
|
||||
// headercolumn[i] = new char[str.length() + 1];
|
||||
// strcpy(headercolumn[i], str.c_str());
|
||||
// headercolumn[i] = strm.str();
|
||||
// }
|
||||
|
||||
T **array;
|
||||
array = new T *[rows];
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
array[i] = new T[columns];
|
||||
vector<vector<T>> aarray(rows, vector<T>(columns));
|
||||
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
{
|
||||
array[i][0] = (i / xscl) + xmin;
|
||||
aarray[i][0] = (i / xscl) + xmin;
|
||||
|
||||
for (unsigned int j = 0; j < numfunctions; ++j)
|
||||
array[i][j + 1] = (functions[j])(array[i][0]);
|
||||
aarray[i][j + 1] = (functions[j])(aarray[i][0]);
|
||||
}
|
||||
|
||||
int code = table(rows, columns, array, headerrow, headercolumn, aoptions);
|
||||
int code = table(aarray, headerrow, headercolumn, aoptions);
|
||||
|
||||
if (array != NULL)
|
||||
if (headerrow != nullptr)
|
||||
{
|
||||
for (unsigned int i = 0; i < rows; ++i)
|
||||
delete[] array[i];
|
||||
|
||||
delete[] array;
|
||||
}
|
||||
|
||||
if (headerrow != NULL)
|
||||
{
|
||||
for (unsigned int j = 0; j < columns; ++j)
|
||||
delete[] headerrow[j];
|
||||
|
||||
delete[] headerrow;
|
||||
}
|
||||
|
||||
// if (headercolumn != NULL)
|
||||
// if (headercolumn != nullptr)
|
||||
// {
|
||||
// for (unsigned int i = 0; i < rows + 1; ++i)
|
||||
// delete[] headercolumn[i];
|
||||
|
||||
// delete[] headercolumn;
|
||||
// }
|
||||
|
||||
@ -510,10 +504,18 @@ int table(const long double xmin, const long double xmax, const long double xscl
|
||||
|
||||
// Convert single function to array and output as table
|
||||
template <typename T>
|
||||
int table(const long double xmin, const long double xmax, const long double xscl, T afunction(T), const tableoptions &aoptions)
|
||||
int table(const long double xmin, const long double xmax, const long double xscl, const function<T(T)> &afunction, const tableoptions &aoptions = defaultoptions)
|
||||
{
|
||||
T(*functions[])
|
||||
(T) = {afunction};
|
||||
std::function<T(T)> afunctions[] = {afunction};
|
||||
|
||||
return table(xmin, xmax, xscl, 1, functions, aoptions);
|
||||
return table(xmin, xmax, xscl, 1, afunctions, aoptions);
|
||||
}
|
||||
|
||||
// Convert single function to array and output as table
|
||||
template <typename T>
|
||||
int table(const long double xmin, const long double xmax, const long double xscl, T afunction(T), const tableoptions &aoptions = defaultoptions)
|
||||
{
|
||||
std::function<T(T)> afunctions[] = {afunction};
|
||||
|
||||
return table(xmin, xmax, xscl, 1, afunctions, aoptions);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user