打印 cout << 时的 C++ 对齐
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2485963/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++ alignment when printing cout <<
提问by user69514
Is there a way to align text when printing using std::cout
? I'm using tabs, but when the words are too big they won't be aligned anymore.
打印时有没有办法对齐文本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
回答by Herb Sutter
The ISO C++ standard way to do it is to #include <iomanip>
and use io manipulators like std::setw
. However, that said, those io manipulators are a real pain to use even for text, and are just about unusable for formatting numbers (I assume you want your dollar amounts to line up on the decimal, have the correct number of significant digits, etc.). Even for just plain text labels, the code will look something like this for the first part of your first line:
ISO C++ 标准方法是#include <iomanip>
使用 io 操纵器,如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...
If you are able to use the Boost libraries, run (don't walk) and use the Boost.Formatlibrary instead. It is fully compatible with the standard iostreams, and it gives you all the goodness for easy formatting with printf/Posix formatting string, but without losing any of the power and convenience of iostreams themselves. For example, the first parts of your first two lines would look something like:
如果您能够使用Boost 库,请运行(不要走)并改用Boost.Format库。它与标准 iostreams 完全兼容,它为您提供了使用 printf/Posix 格式化字符串轻松格式化的所有优点,但不会失去 iostreams 本身的任何功能和便利性。例如,前两行的第一部分看起来像:
// using Boost.Format
cout << format("%-20s %-20s %-8s\n") % "Artist" % "Title" % "Price";
cout << format("%-20s %-20s %8.2f\n") % "Merle" % "Blue" % 12.99;
回答by Martin York
See also: 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;
}
回答by Nguyen
Another way to make column aligned is as follows:
另一种使列对齐的方法如下:
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;
We should estimate maximum length of values for each column. In this case, values of "Artist" column should not exceed 20 characters and so on.
我们应该估计每列值的最大长度。在这种情况下,“艺术家”列的值不应超过 20 个字符等。
回答by Eli Bendersky
IO manipulators are what you need. setw, in particular. Here's an example from the reference page:
IO 操纵器正是您所需要的。setw,特别是。这是参考页面中的示例:
// setw example
#include <iostream>
#include <iomanip>
using namespace std;
int main () {
cout << setw (10);
cout << 77 << endl;
return 0;
}
Justifying the field to the left and right is done with the left
and right
manipulators.
使用left
和right
操纵器完成向左和向右的场对齐。
Also take a look at setfill. Here's a more complete tutorial on formatting C++ output with io manipulators.
也看看setfill。这是关于使用 io manipulators 格式化 C++ 输出的更完整教程。
回答by Alex Martelli
At the time you emit the very first line,
在你发出第一行的时候,
Artist Title Price Genre Disc Sale Tax Cash
to achieve "alignment", you have to know "in advance" how wide each column will need to be (otherwise, alignment is impossible). Once you doknow the needed width for each column (there are several possible ways to achieve that depending on where your data's coming from), then the setw
function mentioned in the other answer will help, or (more brutally;-) you could emit carefully computed number of extra spaces (clunky, to be sure), etc. I don't recommend tabs anyway as you have no real control on how the final output device will render those, in general.
要实现“对齐”,您必须“提前”知道每列需要多宽(否则,对齐是不可能的)。一旦你不知道每一列的宽度需要(有几种可能的方式来实现,取决于您的数据的来自),然后setw
在对方的回答中提到的功能会有所帮助,或者(更残酷;-)你可以仔细地发出计算出的额外空格数(当然是笨重的)等。无论如何,我不建议使用制表符,因为通常您无法真正控制最终输出设备如何呈现这些。
Back to the core issue, if you have each column's value in a vector<T>
of some sort, for example, you can do a first formatting pass to determine the maximum width of the column, for example (be sure to take into account the width of the header for the column, too, of course).
回到核心问题,例如,如果您将每一列的值vector<T>
都归为某种类型,那么您可以进行第一次格式化来确定列的最大宽度,例如(一定要考虑到列的宽度)当然,列的标题也是如此)。
If your rows are coming "one by one", and alignment is crucial, you'll have to cache or buffer the rows as they come in (in memory if they fit, otherwise on a disk file that you'll later "rewind" and re-read from the start), taking care to keep updated the vector of "maximum widths of each column" as the rows do come. You can't output anything (not even the headers!), if keeping alignment is crucial, until you've seen the very last row (unless you somehow magically have previous knowledge of the columns' widths, of course;-).
如果您的行“一一”出现,并且对齐至关重要,则您必须在行进入时对其进行缓存或缓冲(如果它们适合,则在内存中,否则在稍后将“倒带”的磁盘文件中并从头开始重新阅读),注意在行出现时保持更新“每列的最大宽度”的向量。你不能输出任何东西(甚至不是标题!),如果保持对齐是至关重要的,直到你看到最后一行(除非你以某种方式神奇地知道列的宽度,当然;-)。