打印cout <<时的C ++alignment方式
有没有办法使用std::cout
打印时alignment文本? 我正在使用标签,但是当文字太大,他们将不会alignment了。
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
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...
如果你能够使用Boost库 ,运行(不要走),而是使用Boost.Format库。 它与标准的iostreams完全兼容,它为您提供了使用printf / Posix格式化string进行简单格式化的所有优点,同时又不失iostreams本身的强大function和便利性。 例如,前两行的第一部分看起来像这样:
// using Boost.Format cout << format("%-20s %-20s %-8s\n") % "Artist" % "Title" % "Price"; cout << format("%-20s %-20s %8.2f\n") % "Merle" % "Blue" % 12.99;
IO操纵器是你需要的。 特别是。 以下是参考页面的示例:
// setw example #include <iostream> #include <iomanip> using namespace std; int main () { cout << setw (10); cout << 77 << endl; return 0; }
left
right
操纵器完成对left
right
。
也看看setfill 。 下面是一个关于用io操纵器格式化C ++输出的更完整的教程。
另请参见: 应在C ++代码中使用哪个CI / 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; }
Setw操纵器function将在这里帮助。
另一种使列alignment的方法如下:
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个字符,依此类推。
当你发出第一行时,
Artist Title Price Genre Disc Sale Tax Cash
要实现“alignment”,您必须事先知道每列的宽度(否则alignment是不可能的)。 一旦你确实知道每一列所需要的宽度(有几种可能的方法来实现,取决于你的数据来自哪里),那么在其他答案中提到的setw
function将有所帮助,或者(更残忍地;-)你可以发射仔细计算额外空间的数量(笨拙,肯定)等。我不build议选项卡,因为你不能真正控制最终的输出设备将如何呈现这些,一般来说。
回到核心问题,例如,如果某个vector<T>
的每个列的值都是某种types的,例如,可以执行第一个格式化过程以确定列的最大宽度,例如(确保考虑到当然也是列标题的宽度)。
如果你的行是“一个接一个”的,并且alignment是至关重要的,那么你必须caching或者缓冲它们进来的行(如果它们合适的话,在内存中,否则在稍后“倒带”的磁盘文件中)并从头开始重新读取),注意保持更新“每列的最大宽度”的向量随着行来。 你不能输出任何东西(甚至没有头文件!),如果保持alignment是至关重要的,直到你看到了最后一行(除非你有奇迹般地知道列的宽度,当然;-)。