69

を使用して印刷するときにテキストを揃える方法はあります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
4

8 に答える 8

136

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

Boostライブラリを使用できる場合は、実行して(歩かないで)、代わりにBoost.Formatライブラリを使用してください。これは、標準のiostreamと完全に互換性があり、printf / Posixフォーマット文字列を使用して簡単にフォーマットするためのすべての優れた機能を提供しますが、iostream自体のパワーと利便性を失うことはありません。たとえば、最初の2行の最初の部分は次のようになります。

// using Boost.Format
cout << format("%-20s %-20s %-8s\n")  % "Artist" % "Title" % "Price";
cout << format("%-20s %-20s %8.2f\n") % "Merle" % "Blue" % 12.99;
于 2010-03-21T05:41:09.760 に答える
11

参照: 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;
}
于 2010-03-21T09:13:41.223 に答える
11

列を整列させる別の方法は次のとおりです。

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 文字を超えてはなりません。

于 2014-03-12T18:37:33.020 に答える
10

setwマニピュレータ関数がここで役に立ちます。

于 2010-03-21T04:44:58.200 に答える
10

IO マニピュレータが必要です。特にsetw。リファレンス ページの例を次に示します。

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

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

フィールドを左右に揃えるには、 マニピュレータleftrightマニピュレータを使用します。

setfillも見てください。io manipulators を使用した C++ 出力のフォーマットに関するより完全なチュートリアルを次に示します。

于 2010-03-21T04:54:29.313 に答える
4

一番最初の行を発した時点で、

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

「整列」を実現するには、各列の幅を「事前に」知っておく必要があります (そうしないと、整列は不可能です)。各列に必要な幅がわかったら(データの取得元に応じて、それを実現する方法がいくつかあります)、setw他の回答で言及されている関数が役立つか、(より残酷に;-)慎重に出力できます最終的な出力デバイスがそれらをどのようにレンダリングするかを実際に制御できないため、タブはお勧めしません。

コアの問題に戻ると、vector<T>たとえば、各列の値が何らかの形である場合、最初の書式設定パスを実行して列の最大幅を決定できます。もちろん、列のヘッダーも)。

行が「1つずつ」来ており、配置が重要な場合は、行が入ってくるときに行をキャッシュまたはバッファリングする必要があります(収まる場合はメモリに、そうでない場合は後で「巻き戻す」ディスクファイルに)行が来るたびに「各列の最大幅」のベクトルを更新し続けるように注意してください。配置を維持することが重要な場合は、最後の行が表示されるまで何も出力できません (ヘッダーでさえも!) (もちろん、魔法のように列の幅について事前に知っている場合を除きます;-)。

于 2010-03-21T04:57:50.877 に答える