2010-03-21 3 views
54

Y a-t-il un moyen d'aligner le texte lors de l'impression à l'aide de std::cout? J'utilise des onglets, mais quand les mots sont trop gros, ils ne seront plus alignés.Alignement C++ lors de l'impression 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 
+2

Les réponses ci-dessous permettent de spécifier la largeur d'une colonne. Notez que cela nécessite de connaître une limite supérieure (contrainte de base de données par exemple) ou de la calculer au préalable (ce qui peut signifier l'analyse de toute la structure avant de commencer à l'imprimer). La seconde, bien que nécessaire, est bien sûr plus lente :) –

Répondre

7

La fonction manipulateur setw sera utile ici.

+3

Vous devez également mentionner 'left' et' right' qui permettent de spécifier l'alignement et 'setfill' qui permet de spécifier avec quel caractère compléter (espace par défaut). –

8

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

Justifiant le champ à gauche et à droite se fait avec les manipulateurs left et right.

Jetez également un coup d'œil à setfill. Voici un tutoriel plus complet sur formatting C++ output with io manipulators.

4

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

Artist Title Price Genre Disc Sale Tax Cash 

pour atteindre « l'alignement », vous devez savoir « à l'avance » la largeur de chaque colonne devra être (sinon, l'alignement est impossible) . Une fois que vous connaissez la largeur nécessaire pour chaque colonne (il y a plusieurs façons d'y parvenir selon l'origine de vos données), la fonction setw mentionnée dans l'autre réponse vous aidera, ou (plus brutalement ;-) pourrait émettre un nombre soigneusement calculé d'espaces supplémentaires (clunky, 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 les rendra, en général. Pour revenir au problème principal, par exemple, si vous avez une valeur de colonne dans un vector<T>, vous pouvez par exemple effectuer une première passe de mise en forme pour déterminer la largeur maximale de la colonne (assurez-vous de prendre en compte compte aussi la largeur de l'en-tête de la colonne, bien sûr). 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 à mesure qu'elles entrent (en mémoire si elles correspondent, sinon sur un fichier disque que vous aurez plus tard "rembobiner" et relire depuis le début), en prenant soin de garder à jour le vecteur des "largeurs maximales de chaque colonne" comme les lignes viennent. Vous ne pouvez rien sortir (pas même les en-têtes!), Si l'alignement est crucial, jusqu'à ce que vous ayez vu la toute dernière rangée (à moins que vous ayez magiquement connaissance des largeurs des colonnes, bien sûr ;-).

112

La manière standard ISO C++ de le faire est de #include <iomanip> et d'utiliser des manipulateurs io comme std::setw. Cependant, cela dit, ces manipulateurs io sont une vraie peine à utiliser même pour le texte, et sont pratiquement inutilisables pour le formatage des nombres (je suppose que vous voulez que vos montants soient alignés sur la décimale, aient le nombre correct de chiffres significatifs, etc. .). Même pour les étiquettes de texte tout simplement, le code ressemblera à quelque chose comme cela 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 le Boost libraries, courir (ne pas marcher) et utiliser le Boost.Format à la place. Il est entièrement compatible avec les iostreams standard, et il vous donne tout le bien 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 ressemblerait à quelque chose comme:

// using Boost.Format 
cout << format("%-20s %-20s %-8s\n") % "Artist" % "Title" % "Price"; 
cout << format("%-20s %-20s %8.2f\n") % "Merle" % "Blue" % 12.99; 
+5

Boost.Format est vraiment sympa :) –

+2

'Boost.Format' est superbe. Format 'printf' simple avec style-sécurité. – dreamlax

+4

Formats de position aussi, ce qui est génial car cela signifie que vous pouvez les extraire d'un fichier de localisation. –

9

Voir aussi: 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; 
} 
5

Une autre façon de faire la colonne alignée 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 devrions 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 et ainsi de suite.