web-dev-qa-db-fra.com

Alignement C ++ lors de l'impression cout <<

Existe-t-il un moyen d'aligner du texte lors de l'impression à l'aide de std::cout? J'utilise des tabulations, mais lorsque les mots sont trop gros, ils ne seront plus alignés.

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

La manière standard ISO C++ de le faire est de #include <iomanip> et utilisez des manipulateurs io comme std::setw . Cependant, cela dit, ces manipulateurs io sont vraiment pénibles à utiliser même pour du texte, et sont à peu près inutilisables pour formater les nombres (je suppose que vous voulez que vos montants en dollars soient alignés sur la décimale, aient le nombre correct de chiffres significatifs, etc. .). Même pour les étiquettes en texte brut, le code ressemblera à ceci pour la première partie de votre première ligne:

// using standard iomanip facilities
cout << setw(20) << "Artist"
     << setw(20) << "Title"
     << setw(8) << "Price";
// ... not going to try to write the numeric formatting...

Si vous êtes en mesure d'utiliser les bibliothèques Boost , exécutez (ne marchez pas) et utilisez le Boost.Format bibliothèque à la place. Il est entièrement compatible avec les iostreams standard et vous offre toutes les qualités pour un formatage facile avec la chaîne de formatage printf/Posix, mais sans perdre la puissance et la commodité des iostreams eux-mêmes. Par exemple, les premières parties de vos deux premières lignes ressembleraient à:

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

Voir aussi: Quelle bibliothèque d'E/S C doit être utilisée dans le code C++?

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

Les manipulateurs d'E/S sont ce dont vous avez besoin. setw , en particulier. Voici un exemple de la page de référence:

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

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

La justification du champ à gauche et à droite se fait avec les manipulateurs left et right.

Jetez également un œil à setfill . Voici un tutoriel plus complet sur formatage de la sortie C++ avec des manipulateurs io .

9
Eli Bendersky

La fonction de manipulateur setw sera utile ici.

8
codaddict

Une autre façon d'aligner les colonnes est la suivante:

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;

Nous devons estimer la longueur maximale des valeurs pour chaque colonne. Dans ce cas, les valeurs de la colonne "Artiste" ne doivent pas dépasser 20 caractères, etc.

7
Nguyen

Au moment où vous émettez la toute première ligne,

Artist  Title   Price   Genre   Disc    Sale    Tax Cash

pour réaliser "l'alignement", vous devez savoir "à l'avance" la largeur de chaque colonne (sinon l'alignement est impossible). Une fois que vous faites connaissez la largeur nécessaire pour chaque colonne (il y a plusieurs façons possibles d'atteindre cela en fonction de la provenance de vos données), alors la fonction setw mentionnée dans l'autre réponse sera aide, ou (plus brutalement ;-) vous pourriez émettre un nombre soigneusement calculé d'espaces supplémentaires (maladroit, pour être sûr), etc. Je ne recommande pas les onglets de toute façon car vous n'avez aucun contrôle réel sur la façon dont le périphérique de sortie final rendra ces , en général.

Revenons au problème principal, si vous avez la valeur de chaque colonne dans un vector<T> d'une sorte, par exemple, vous pouvez faire une première passe de mise en forme pour déterminer la largeur maximale de la colonne, par exemple (assurez-vous de prendre également en compte la largeur de l'en-tête de la colonne).

Si vos lignes arrivent "une par une" et que l'alignement est crucial, vous devrez mettre en cache ou mettre en mémoire tampon les lignes au fur et à mesure qu'elles entrent (en mémoire si elles conviennent, sinon sur un fichier disque que vous "rembobinerez" plus tard). et relire depuis le début), en prenant soin de garder à jour le vecteur des "largeurs maximales de chaque colonne" au fur et à mesure que les lignes arrivent. Vous ne pouvez rien produire (pas même les en-têtes!), Si le maintien de l'alignement est crucial, jusqu'à ce que vous ayez vu la toute dernière ligne (à moins que vous n'ayez par magie une connaissance préalable de la largeur des colonnes, bien sûr ;-).

4
Alex Martelli