打印cout时的C ++对齐<<

时间:2010-03-21 04:43:02

标签: c++ stdout cout text-alignment

使用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

7 个答案:

答案 0 :(得分:119)

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 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;

答案 1 :(得分:10)

另请参阅: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;
}

答案 2 :(得分:8)

IO操纵器是您所需要的。 setw,尤其如此。以下是参考页面的示例:

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

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

使用leftright操纵器完成向左和向右对齐字段。

另请查看setfill。这是关于formatting C++ output with io manipulators的更完整的教程。

答案 3 :(得分:7)

setw操纵器功能在这里会有所帮助。

答案 4 :(得分:6)

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

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个字符,依此类推。

答案 5 :(得分:4)

当你发出第一行时,

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

要实现“对齐”,您必须“提前”知道每列需要的宽度(否则,无法对齐)。一旦知道每列所需的宽度(有几种可能的方法来实现这一点,具体取决于数据的来源),那么另一个答案中提到的setw函数将有助于,或者(更残酷地;-)你可以发出精心计算的额外空间数量(笨重,可以肯定)等等。我不推荐标签,因为你对最终输出设备如何渲染它们没有真正的控制,总的来说。

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

如果您的行“逐个”出现,并且对齐至关重要,则必须在行进入时缓存或缓冲行(如果它们适合则在内存中,否则在稍后的磁盘文件中) “倒回”并从头开始重新阅读,注意保持更新“行的最大宽度”的向量。你不能输出任何东西(甚至不是标题!),如果保持对齐是至关重要的,直到你看到最后一行(除非你以某种方式神奇地知道列的宽度,当然; - )。 / p>

答案 6 :(得分:0)

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