打印 cout << 时的 C++ 对齐
Posted
技术标签:
【中文标题】打印 cout << 时的 C++ 对齐【英文标题】:C++ alignment when printing cout << 【发布时间】:2011-01-29 23:13:39 【问题描述】:有没有办法在使用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
【问题讨论】:
下面的响应允许指定列的宽度。请注意,这需要您知道上限(例如数据库约束)或预先计算它(这可能意味着在实际开始打印之前解析整个结构)。第二个虽然是必要的,但当然更慢:) 【参考方案1】:执行此操作的 ISO C++ 标准方法是 #include <iomanip>
并使用像 std::setw
这样的 io 操作符。然而,也就是说,那些 io 操纵器即使用于文本也很痛苦,并且几乎无法用于格式化数字(我假设您希望您的美元金额在小数点上排列,具有正确的有效位数等.)。即使对于纯文本标签,第一行的第一部分的代码也会如下所示:
// using standard iomanip facilities
cout << setw(20) << "Artist"
<< setw(20) << "Title"
<< setw(8) << "Price";
// ... not going to try to write the numeric formatting...
如果您能够使用 Boost libraries,请运行(不要走路)并改用 Boost.Format 库。它与标准 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;
【讨论】:
Boost.Format
看起来很棒。具有类型安全性的简单 printf
样式格式。
位置格式也很好,因为这意味着您可以从本地化文件中提取它们。【参考方案2】:
另请参阅:Which C I/O library should be used in C++ code?
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;
【讨论】:
【参考方案3】:另一种使列对齐的方法如下:
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;
我们应该估计每列值的最大长度。在这种情况下,“艺术家”列的值不应超过 20 个字符,依此类推。
【讨论】:
【参考方案4】:setw 操纵器函数将在这里提供帮助。
【讨论】:
您还应该提到left
和right
允许指定对齐方式和setfill
允许指定使用哪个字符完成(默认为空格)。【参考方案5】:
IO 操纵器是您所需要的。 setw,尤其是。以下是参考页面中的示例:
// setw example
#include <iostream>
#include <iomanip>
using namespace std;
int main ()
cout << setw (10);
cout << 77 << endl;
return 0;
使用left
和right
操纵器将字段左右对齐。
还可以查看setfill。这是关于formatting C++ output with io manipulators的更完整的教程。
【讨论】:
【参考方案6】:在您发出第一行时,
Artist Title Price Genre Disc Sale Tax Cash
要实现“对齐”,您必须“提前”知道每列需要多宽(否则,对齐是不可能的)。一旦您确实知道每列所需的宽度(有几种可能的方法可以实现这一点,具体取决于数据的来源),那么另一个答案中提到的 setw
函数将有所帮助,或者(更残酷;-)您可以发出仔细计算的额外空格数(可以肯定的是笨重)等。我不推荐标签,因为您无法真正控制最终输出设备如何呈现这些,一般来说.
回到核心问题,例如,如果您在某种vector<T>
中包含每列的值,例如,您可以执行第一次格式化传递以确定列的最大宽度,例如(确保采取当然,还要考虑列标题的宽度)。
如果您的行是“一个接一个”的,并且对齐至关重要,那么您必须在行进入时缓存或缓冲它们(如果它们适合,则在内存中,否则在您稍后将在的磁盘文件中“倒带”并从头开始重新读取),注意随着行的到来保持更新“每列的最大宽度”的向量。你不能输出任何东西(甚至是标题!),如果保持对齐是至关重要的,直到你看到最后一行(除非你以某种方式神奇地预先知道列的宽度;-)。
【讨论】:
【参考方案7】:C++20 std::format
选项 <
、^
和 >
根据https://en.cppreference.com/w/cpp/utility/format/formatter#Standard_format_specification,以下应该成立:
// left: "42 "
std::cout << std::format(":<6", 42);
// right: " 42"
std::cout << std::format(":>6", 42);
// center: " 42 "
std::cout << std::format(":^6", 42);
更多信息请访问:std::string formatting like sprintf
【讨论】:
【参考方案8】:不使用“复杂”函数的最简单方法是手动格式化:
一个例子:
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';
【讨论】:
以上是关于打印 cout << 时的 C++ 对齐的主要内容,如果未能解决你的问题,请参考以下文章