web-dev-qa-db-ja.com

cout <<を印刷するときのC ++アライメント

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
58
user69514

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.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;
121
Herb Sutter

参照: C++コードで使用するC I/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;
}
11
Martin York

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

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

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

左右のフィールドの調整は、leftおよびrightマニピュレーターを使用して行います。

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

9
Eli Bendersky

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

8
codaddict

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

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文字を超えないようにしてください。

7
Nguyen

一番最初の行を出すとき、

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

「アラインメント」を実現するには、各列の幅を「事前に」知る必要があります(そうでない場合、アラインメントは不可能です)。 do各列に必要な幅がわかったら(データの送信元に応じてそれを実現する方法はいくつかあります)、他の答えで言及されているsetw関数は助け、または(より残酷に;-)慎重に計算された数の余分なスペースを出力することができます(確かに不格好です)。 、 一般に。

コアの問題に戻ります。各列の値がvector<T>たとえば、最初の書式設定パスを実行して、たとえば列の最大幅を決定できます(もちろん、列のヘッダーの幅も考慮に入れてください)。

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

4
Alex Martelli