打印时 C + + 对齐 < <

在使用 std::cout打印时,是否有办法对齐文本?我用的是制表符,但是当单词太大的时候,它们就不会对齐了。

Sales Report for September 15, 2010
Artist  Title   Price   Genre   Disc    Sale    Tax Cash
Merle   Blue    12.99   Country 4%  12.47   1.01    13.48
Richard Music   8.49    Classical   8%  7.81    0.66    8.47
Paula   Shut    8.49    Classical   8%  7.81    0.72    8.49
142255 次浏览

IO 操纵器是你所需要的。特别是 Sew。下面是参考页面中的一个例子:

// setw example
#include <iostream>
#include <iomanip>
using namespace std;


int main () {
cout << setw (10);
cout << 77 << endl;
return 0;
}

使用 leftright操纵器对字段的左右进行调整。

也可以看看 填满。这里有一个更完整的关于 使用 io 操作器格式化 C + + 输出的教程。

在你发出第一行的时候,

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

要实现“对齐”,你必须“提前”知道每列需要多宽(否则,对齐是不可能的)。一旦你知道了每一列所需的宽度(根据你的数据来源,有几种可能的方法可以实现这一点) ,那么另一个答案中提到的 setw函数将会有所帮助,或者(更残酷的是; ——)你可以发出精心计算的额外空格数量(当然是笨重的) ,等等。我不推荐使用制表符,因为通常情况下,你不能真正控制最终输出设备如何呈现这些制表符。

回到核心问题,例如,如果每个列的值都在某种类型的 vector<T>中,那么可以进行第一次格式化传递来确定列的最大宽度,例如(当然,也要考虑列标题的宽度)。

如果你的行是“一个接一个”到来,对齐是至关重要的,你将不得不缓存或缓冲的行,因为他们进来(在内存中,如果他们适合,否则在磁盘文件,你将稍后“倒带”和重新读从开始) ,注意保持更新的向量“每列的最大宽度”,因为行来了。您不能输出任何内容(即使是头部!)如果保持对齐是至关重要的,直到你看到最后一行(当然,除非你以某种方式神奇地事先知道列的宽度;)。

ISO C + + 的标准方法是使用 #include <iomanip>和象 std::setw这样的输入输出操作器。尽管如此,这些 io 操作器对于文本来说也是一个麻烦,而且对于格式化数字来说也是不可用的(我假设你希望你的金额排在小数点后,有正确的有效数字数,等等)。即使只是纯文本标签,代码在第一行的第一部分也是这样的:

// using standard iomanip facilities
cout << setw(20) << "Artist"
<< setw(20) << "Title"
<< setw(8) << "Price";
// ... not going to try to write the numeric formatting...

如果您能够使用 增加库,请运行(不要步行)并使用 译自: 美国《科学》杂志网站(http://www.Boost.org/doc/libs/1 _ 53 _ 0/libs/Format/index.html)原著: http://www.Boost.org/doc/libs/1 _ 53 _ 0/libs/Format/index.html库代替。它与标准 iostream 完全兼容,并且它为您提供了使用 printf/Posix 格式字符串进行简单格式化的所有优点,但不会失去 iostream 本身的任何功能和便利性。例如,前两行的第一部分看起来像这样:

// using Boost.Format
cout << format("%-20s %-20s %-8s\n")  % "Artist" % "Title" % "Price";
cout << format("%-20s %-20s %8.2f\n") % "Merle" % "Blue" % 12.99;

参见: 在 C + + 代码中应该使用哪个 C I/O 库?

struct Item
{
std::string     artist;
std::string     c;
integer         price;  // in cents (as floating point is not acurate)
std::string     Genre;
integer         disc;
integer         sale;
integer         tax;
};


std::cout << "Sales Report for September 15, 2010\n"
<< "Artist  Title   Price   Genre   Disc    Sale    Tax Cash\n";
FOREACH(Item loop,data)
{
fprintf(stdout,"%8s%8s%8.2f%7s%1s%8.2f%8.2f\n",
, loop.artist
, loop.title
, loop.price / 100.0
, loop.Genre
, loop.disc , "%"
, loop.sale / 100.0
, loop.tax / 100.0);


// or


std::cout << std::setw(8) << loop.artist
<< std::setw(8) << loop.title
<< std::setw(8) << fixed << setprecision(2) << loop.price / 100.0
<< std::setw(8) << loop.Genre
<< std::setw(7) << loop.disc << std::setw(1) << "%"
<< std::setw(8) << fixed << setprecision(2) << loop.sale / 100.0
<< std::setw(8) << fixed << setprecision(2) << loop.tax / 100.0
<< "\n";


// or


std::cout << boost::format("%8s%8s%8.2f%7s%1s%8.2f%8.2f\n")
% loop.artist
% loop.title
% loop.price / 100.0
% loop.Genre
% loop.disc % "%"
% loop.sale / 100.0
% loop.tax / 100.0;
}

使列对齐的另一种方法如下:

using namespace std;


cout.width(20); cout << left << "Artist";
cout.width(20); cout << left << "Title";
cout.width(10); cout << left << "Price";
...
cout.width(20); cout << left << artist;
cout.width(20); cout << left << title;
cout.width(10); cout << left << price;

我们应该估计每列值的最大长度。在这种情况下,“ Artist”列的值不应超过20个字符,以此类推。

C + + 20 std::format选项 <^>

根据 https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification,以下内容应该成立:

#include <format>


// left: "42    "
std::cout << std::format("{:<6}", 42);


// right: "    42"
std::cout << std::format("{:>6}", 42);


// center: "  42  "


std::cout << std::format("{:^6}", 42);

现有的 fmt库在获得官方支持之前实现了它:

sudo apt install libfmt-dev

修改源代码以替换:

  • <format><fmt/core.h>
  • std::format呼叫 fmt::format

Main.cpp

#include <iostream>


#include <fmt/core.h>


int main() {
std::cout << "123456.\n";
// left
std::cout << fmt::format("{:<6}.\n", 42);
// right
std::cout << fmt::format("{:>6}.\n", 42);
// center
std::cout << fmt::format("{:^6}.\n", 42);
}

编译并运行:

g++ -std=c++11 -o main.out main.cpp -lfmt
./main.out

产出:

123456.
42    .
42.
42  .

更多信息请访问: 字符串格式,如 sprintf

不使用“复杂”函数的最简单方法是手工格式化:

例如:

  std::cout << std::setprecision(10)
<< "integral of sin(x) from x = 0 to x = pi" << '\n'
<< "approximate: " << integrate(a, b, nbins) << '\n'
<< "exact:       " << 2.0                    << '\n';