作者:HelloGitHub-ChungZH

0x00 介绍 tabulate

tabulate 是一个使用 C++ 17 编写的库,它可以制作表格。使用它,把表格对齐、格式化和着色,不在话下!你甚至可以使用 tabulate,将你的表格导出为 Markdown 代码。下图是一个使用 tabulate 制作的表格输出在命令行的样例:

当然,除了表格,你还可以玩出花样。看见下面这个马里奥了吗?这也是用 tabulate 制作的!源码在 这里

0x10 准备

首先你需要安装 CMake

创建一个文件夹(下文用 X 代替),作为你使用 tabulate 的地方。再将 include 这个文件夹下载到 X 里。然后在 X 里创建 main.cpp 以及一个 CMakeLists.txt

注意:需要下载 include 整个文件夹而不是仅仅下载 tabulate 文件夹

你可以点击 这里 下载 tabulate 项目,然后将 include 文件夹复制到 X 中。

将下面的代码复制进 CMakeLists.txt

cmake_minimum_required(VERSION 3.8)

# 这里的 tabulateDemo 可以换为你喜欢的名字
project(tabulateDemo) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True) include_directories(include) add_executable(main main.cpp)

最后 X 文件夹的结构应该是这样的:

.
├── CMakeLists.txt
├── include
│ └── tabulate
└── main.cpp

认真核对好 X 的结构!

可前往 ChungZH/tabulatedemo 核对文件结构。

0x20 小试身手

将下面这段代码复制进 main.cpp 中:

#include "tabulate/table.hpp"
using namespace std;
using namespace tabulate;
int main()
{
Table hellogithub; // 创建一个叫做 hellogithub 的 Table 对象 hellogithub.add_row({"HelloGitHub"});
hellogithub.add_row({"hellogithub.com"});
hellogithub[1][0].format()
.font_style({FontStyle::underline});
hellogithub.add_row({"github.com/521xueweihan/HelloGitHub"});
hellogithub[2][0].format()
.font_style({FontStyle::underline});
hellogithub.add_row({"xueweihan NB!!!"}); cout << hellogithub << endl;
return 0;
}
  • 如果你使用的是 Linux/MacOS 系统,请在终端进入 X 文件夹并输入以下命令:

    mkdir build
    cd build
    cmake ..
    make
    ./main
  • 如果你使用的是 Windows 系统和 MinGW,请检查是否安装 mingw32-make.exe,并在终端中进入 X 文件夹,输入:

    mkdir build
    cd build
    cmake ..
    mingw32-make
    ./main.exe
  • 如果你使用 Windows 以及 MSVC,在终端中输入:

    mkdir build
    cd build
    cmake ..

然后使用 Visual Studio 打开 build 文件夹下的 tabulateDemo.sln 来运行。

如果没有问题,那么你应该会在终端里看到:

0x30 格式化表格

请先认真分析 0x20 小试身手 章节中的代码并尝试着修改一下它!

0x31 Word Wrapping

为了防止表格中的内容过长导致不整齐,你可以指定表格每一列的宽度,tabulate 就会自动帮你换行。语法如下:

// 将表格第 0 行第 0 列的宽度设为20
table[0][0].format().width(20);

除了自动换行,你也可以在内容中使用 \n 来手动设置换行。

这是一个 Word Wrapping 的例子:

#include "tabulate/table.hpp"
using namespace std;
using namespace tabulate;
int main()
{
Table table; table.add_row({"This paragraph contains a veryveryveryveryveryverylong word. The long word will break and word wrap to the next line.",
"This paragraph \nhas embedded '\\n' \ncharacters and\n will break\n exactly where\n you want it\n to\n break."}); table[0][0].format().width(20); // 设置第 0 行第 0 列的宽度为 20
table[0][1].format().width(50); // 设置第 0 行第 1 列的宽度为 50 cout << table << endl;
return 0;
}
return 0;
}
  • 第 0 行第 0 列的文字是不是很长?但是设置了它的宽度后,就不用担心了。tabulate 将会帮你自动换行。如果不设置的话,表格就会变得很不整齐,你也可以尝试一下。

  • 第 0 行第 1 列的内容里运用了\n 的换行符,所以即使我们给它设置了 50 的宽度,也会先根据内容里的 \n 换行符来换行。

  • 值得注意的是,tabulate 会自动删除每一行内容两边的空白字符。

0x32 字体对齐

tabulate 支持三种对齐设置:左、中和右。默认情况下,全部内容都会靠左对齐。

要手动设置对齐方式,可以使用 .format().font_align(方向)

举一个例子:

#include "tabulate/table.hpp"
using namespace std;
using namespace tabulate;
int main()
{
Table hellogithub; hellogithub.add_row({"HelloGitHub"});
hellogithub[0][0].format()
.font_align(FontAlign::center); // 设置居中对齐
hellogithub.add_row({"hellogithub.com"});
hellogithub[1][0].format()
.font_align(FontAlign::left); // 设置靠左对齐
hellogithub.add_row({"github.com/521xueweihan/HelloGitHub"});
hellogithub[2][0].format()
.font_align(FontAlign::center); // 设置居中对齐
hellogithub.add_row({"xueweihan NB!!!"});
hellogithub[3][0].format()
.font_align(FontAlign::right); // 设置靠右对齐 hellogithub[0][0].format().width(50);
cout << hellogithub << endl;
return 0;
}

0x33 字体样式

tabulate 支持以下八种字体样式:

  • 粗体 bold

  • 深色 dark

  • 斜体 italic

  • 下划线 underline

  • 闪烁 blink

  • 翻转 reverse

  • 隐藏 concealed

  • 删除线 crossed

某些样式可能会因为终端的原因而无法显示。

如:粗体、深色、斜体、闪烁等样式,请慎用。

要使用这些样式,可以调用 .format().font_style({...})。样式也可以叠加使用。

0x34 颜色

你可以对表格的字体、边框、角以及列分隔符号设置它们的前景或背景颜色。

tabulate 支持 8 种颜色:

  • 灰色 gray

  • 红色 red

  • 绿色 green

  • 黄色 yellow

  • 蓝色 blue

  • 洋红色 magenta

  • 青色 cyan

  • 白色 white

可以通过 .format().&lt;element&gt;_color(颜色) 的方式定义前景色或通过 .format().&lt;element&gt;_background_color(颜色) 的方式定义背景色。

#include "tabulate/table.hpp"
using namespace tabulate;
using namespace std;
int main()
{
Table colors; colors.add_row({"Font Color is Red", "Font Color is Blue", "Font Color is Green"});
colors.add_row({"Everything is Red", "Everything is Blue", "Everything is Green"});
colors.add_row({"Font Background is Red", "Font Background is Blue", "Font Background is Green"}); colors[0][0].format()
.font_color(Color::red)
.font_style({FontStyle::bold});
colors[0][1].format()
.font_color(Color::blue)
.font_style({FontStyle::bold});
colors[0][2].format()
.font_color(Color::green)
.font_style({FontStyle::bold}); colors[1][0].format()
.border_left_color(Color::red)
.border_left_background_color(Color::red)
.font_background_color(Color::red)
.font_color(Color::red); colors[1][1].format()
.border_left_color(Color::blue)
.border_left_background_color(Color::blue)
.font_background_color(Color::blue)
.font_color(Color::blue); colors[1][2].format()
.border_left_color(Color::green)
.border_left_background_color(Color::green)
.font_background_color(Color::green)
.font_color(Color::green)
.border_right_color(Color::green)
.border_right_background_color(Color::green); colors[2][0].format()
.font_background_color(Color::red)
.font_style({FontStyle::bold});
colors[2][1].format()
.font_background_color(Color::blue)
.font_style({FontStyle::bold});
colors[2][2].format()
.font_background_color(Color::green)
.font_style({FontStyle::bold}); cout << colors << endl;
return 0;
}

0x35 边框、角

你可以对表格的边框和角的文本、颜色或背景颜色进行自定义。

你可以使用 .corner(..).corner_color(..)corner_background_color(..) 来对所有的角设置一个共同的样式。你也可以使用 .border(..) 、.border_color(..) 和 .border_background_color(..) 来对所有的边框设置一个共同的样式。

这是一个单独设定所有边框和角的示例:

#include <tabulate/table.hpp>
using namespace tabulate; int main()
{
Table table; table.add_row({"ᛏᚺᛁᛊ ᛁᛊ ᚨ ᛊᛏᛟᚱy ᛟᚠᚨ ᛒᛖᚨᚱ ᚨᚾᛞ\n"
"ᚨ ᚹᛟᛚᚠ, ᚹᚺᛟ ᚹᚨᚾᛞᛖᚱᛖᛞ ᛏᚺᛖ\n"
"ᚱᛖᚨᛚᛗᛊ ᚾᛁᚾᛖ ᛏᛟ ᚠᚢᛚᚠᛁᛚᛚ ᚨ ᛈᚱᛟᛗᛁᛊᛖ\n"
"ᛏᛟ ᛟᚾᛖ ᛒᛖᚠᛟᚱᛖ; ᛏᚺᛖy ᚹᚨᛚᚲ ᛏᚺᛖ\n"
"ᛏᚹᛁᛚᛁᚷᚺᛏ ᛈᚨᛏᚺ, ᛞᛖᛊᛏᛁᚾᛖᛞ ᛏᛟ\n"
"ᛞᛁᛊcᛟᚹᛖᚱ ᛏᚺᛖ ᛏᚱᚢᛏᚺ\nᛏᚺᚨᛏ ᛁᛊ ᛏᛟ cᛟᛗᛖ."}); table.format()
.multi_byte_characters(true)
// Font styling
.font_style({FontStyle::bold, FontStyle::dark})
.font_align(FontAlign::center)
.font_color(Color::red)
.font_background_color(Color::yellow)
// Corners
.corner_top_left("ᛰ")
.corner_top_right("ᛯ")
.corner_bottom_left("ᛮ")
.corner_bottom_right("ᛸ")
.corner_top_left_color(Color::cyan)
.corner_top_right_color(Color::yellow)
.corner_bottom_left_color(Color::green)
.corner_bottom_right_color(Color::red)
// Borders
.border_top("ᛜ")
.border_bottom("ᛜ")
.border_left("ᚿ")
.border_right("ᛆ")
.border_left_color(Color::yellow)
.border_right_color(Color::green)
.border_top_color(Color::cyan)
.border_bottom_color(Color::red);
std::cout << table << std::endl;
return 0;
}

0x36 基于范围的迭代

一个一个设置表格的样式是不是很麻烦?tabulate 提供了迭代器,支持对表、行和列的迭代,更方便地格式化表格。

#include <tabulate/table.hpp>
using namespace tabulate; int main() {
Table table; table.add_row({"Company", "Contact", "Country"});
table.add_row({"Alfreds Futterkiste", "Maria Anders", "Germany"});
table.add_row({"Centro comercial Moctezuma", "Francisco Chang", "Mexico"});
table.add_row({"Ernst Handel", "Roland Mendel", "Austria"});
table.add_row({"Island Trading", "Helen Bennett", "UK"});
table.add_row({"Laughing Bacchus Winecellars", "Yoshi Tannamuri", "Canada"});
table.add_row({"Magazzini Alimentari Riuniti", "Giovanni Rovelli", "Italy"}); // 设置每一行的宽度
table.column(0).format().width(40);
table.column(1).format().width(30);
table.column(2).format().width(30); // 遍历第一行中的单元格
for (auto& cell : table[0]) {
cell.format()
.font_style({FontStyle::underline})
.font_align(FontAlign::center);
} // 遍历第一列中的单元格
for (auto& cell : table.column(0)) {
if (cell.get_text() != "Company") {
cell.format()
.font_align(FontAlign::right);
}
} // 遍历表格中的行
size_t index = 0;
for (auto& row : table) {
row.format()
.font_style({FontStyle::bold}); // 轮流把整行的背景设为蓝色
if (index > 0 && index % 2 == 0) {
for (auto& cell : row) {
cell.format()
.font_background_color(Color::blue);
}
}
index += 1;
} std::cout << table << std::endl;
}

0x37 嵌套表格

在 tabulate 中嵌套表格很容易,因为 Table.add_row(...) 这个函数可以接受 std::string 类型和 tabulate::Table。下面是一个嵌套表格的例子:

#include "tabulate/table.hpp"
using namespace tabulate;
using namespace std;
int main() {
Table hellogithub;
hellogithub.add_row({"HelloGitHub"});
hellogithub[0][0]
.format()
.font_background_color(Color::blue)
.font_align(FontAlign::center); Table hglink;
hglink.add_row({"GitHub repo", "Website"});
hglink.add_row({"github.com/521xueweihan/HelloGitHub", "hellogithub.com"}); hellogithub.add_row({hglink}); // 嵌套!
cout << hellogithub << endl;
return 0;
}

0x40 导出

0x41 Markdown

可以使用 MarkdownExporter 来将一个表格导出为 GFM 风格的 Markdown。

#include "tabulate/markdown_exporter.hpp"  // 注意这个头文件
#include "tabulate/table.hpp"
using namespace tabulate;
using namespace std;
int main() {
Table hellogithub;
hellogithub.add_row({"HelloGitHub"});
hellogithub[0][0].format().font_style({FontStyle::bold}); // 加粗样式,在 Markdown 中可以表现出来
hellogithub.add_row({"GitHub repo: github.com/521xueweihan/HelloGitHub"});
hellogithub.add_row({"Website: hellogithub.com"}); // 导出为 Markdown
MarkdownExporter exporter;
auto markdown = exporter.dump(hellogithub); cout << hellogithub << endl << endl;
cout << "Markdown Source:\n\n" << markdown << endl;
return 0;
}

导出效果如下:

HelloGitHub
GitHub repo: github.com/521xueweihan/HelloGitHub
Website: hellogithub.com

注意:Markdown 不能指定每一个单元格的对齐样式,只能指定一列的对齐样式,像这样 hg.column(1).format().font_align(FontAlign::center);

0x50 尾声

如果想要更详细地了解 tabulate 的用法,请查看官方文档 https://github.com/p-ranav/tabulate

本文是作者的第一次关于此类型文章的尝试,如有不足之处,请指正,谢谢!

再见!


关注公众号加入交流群

优雅地使用 C++ 制作表格:tabulate的更多相关文章

  1. ul+li标签制作表格

    table标签制作表格代码繁琐,且不方便后期代码维护. li标签加上css的浮动样式可以制作多种样式的表格. 代码如下: <ul id="ttttt" style=" ...

  2. HTML编辑模式下制作表格

    前面有朋友问如何做图文并茂的音乐帖子,的确音乐能以表格式做出来,更能让人过目不忘,何况帖子制作过程本身就是创作,包含了制作人对音乐的理解和爱好.以下简单介绍用代码HTML制作表格,希望对大家有所帮助. ...

  3. iOS 制作表格 (数据源控制行,列数)

    记得去年面试的过程中,有一个面试官问我怎么制作表格.由于之前也没有做过,当时有点懵逼,今天想起来了,就用tableview制作了一个,望不要有人像我一样掉坑了, 直接上代码: // // ViewCo ...

  4. [Swift通天遁地]二、表格表单-(4)使用系统自带的下拉刷新控件,制作表格的下拉刷新效果

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...

  5. 一个快速制作表格的方法,和熬夜做表say拜拜

    如今已是大数据时代了,统计工作是非常繁琐的一项工作,通常统计老师为了录单工作到下半夜或者是通宵,现在有了很多制作表单的软件,可以大大减轻基层统计老师的工作量,也增加了会员资料的保密性,给我们统计工作带 ...

  6. Android listview 制作表格样式+由下往上动画弹出效果实现

    效果是这样的:点击按下弹出表格的按钮,会由下往上弹出右边的列表,按下返回按钮就由上往下退出界面. 布局文件: activity_main.xml <RelativeLayout xmlns:an ...

  7. MVC小系列(一)【制作表格】

    在Razor引擎中,对于在表格中进行遍历时,一般会这样写 复制代码 <table border="> @{ ; i < ; i++) { <tr> <td ...

  8. LaTex 制作表格 合并行\multirow 合并列\multicolumn

    在latex文件最前面用这个包\usepackage{multirow} multirow 宏包提供了 \multirow 命令可以在表格中排版横跨两行以上的文本.命令的格式如下: \multirow ...

  9. zabbix 硬盘状态收集,制作表格

    将zabbix首页复制到a文件里,这里主要是用到首页里 最近出现的问题 的信息 # -*- coding:utf-8 -*- import time import os from openpyxl i ...

随机推荐

  1. 字符串 hash - 不停地删掉字母

    Censor frog is now a editor to censor so-called sensitive words (敏感词). She has a long text p . Her j ...

  2. TCP/IP协议与HTTP协议(二)

    TCP/IP协议是传输层协议,主要解决数据如何在网络中传输,而HTTP是应用层协议,主要解决如何包装数据. 1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过 ...

  3. jQuery, 文本框获得焦点后, placeholder提示文字消失

    文本框获得焦点后, 提示文字消失, 基于jQuery, 兼容性: html5 //所有文本框获得焦点后, 提示文字消失 $('body').on('focus', 'input[placeholder ...

  4. Mysql-SQL优化-子查询替代LEFT JOIN

    表A:批次信息表, 表B:实际批次明细表, Mysql版本:5.6.36 两表之间的数据体量差异:表B是表A的10000倍. 经过结转,表B通常保留 1千5百万数据.表A就是1千多条数据. 计算近24 ...

  5. Xadmin的实现

    一.启动 1.前提 配置setting.py文件 INSTALLED_APPS 2.定位Xadmin,找到对应的类 'Xadmin.apps.XadminConfig', 3.根据admin源码,实现 ...

  6. Postman 的替代品来了

    Postwoman 一个开源.免费.快速.漂亮的 API 构建器,可以替代 Postman. 这个名字起得挺有意思,感觉像 Postman 的媳妇. Postwoman 的诞生过程: 它的作者是一个全 ...

  7. JS-02-js的变量

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. spring cloud oauth2搭建认证中心与资源中心

    一 认证中心搭建 添加依赖,如果使用spring cloud的话,不管哪个服务都只需要这一个封装好的依赖即可 <dependency> <groupId>org.springf ...

  9. 云原生 - Istio可观察性之监控(四)

    作者:justmine 头条号:大数据与云原生 微信公众号:大数据与云原生 创作不易,在满足创作共用版权协议的基础上可以转载,但请以超链接形式注明出处. 为了方便阅读,微信公众号已按分类排版,后续的文 ...

  10. 【Java并发工具类】Lock和Condition

    前言 Java SDK并发包通过Lock和Condition两个接口来实现管程,其中Lock用于解决互斥问题,Condition用于解决同步问题.我们需要知道,Java语言本身使用synchroniz ...