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
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;
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;
}
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 .
La fonction de manipulateur setw sera utile ici.
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.
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 ;-).