Allineamento C ++ quando si stampa cout <<

C’è un modo per allineare il testo quando si stampa usando std::cout ? Sto usando le tabs, ma quando le parole sono troppo grandi non saranno più allineate.

 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 

Il modo standard ISO C ++ per farlo è #include e usare i manipolatori io come std::setw . Tuttavia, detto questo, quei manipolatori io sono un vero dolore da usare anche per il testo, e sono praticamente inutilizzabili per la formattazione dei numeri (presumo che tu voglia che i tuoi importi in dollari si allineino sul decimale, abbiano il numero corretto di cifre significative, ecc. .). Anche per etichette di solo testo, il codice sarà simile a questo nella prima parte della prima riga:

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

Se si è in grado di utilizzare le librerie Boost , eseguire (non camminare) e utilizzare invece la libreria Boost.Format . È completamente compatibile con gli iostreams standard e offre tutta la bontà per una facile formattazione con la stringa di formattazione printf / Posix, ma senza perdere nulla della potenza e della convenienza degli iostreams stessi. Ad esempio, le prime parti delle prime due linee apparirebbero come:

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

Vedi anche: Quale libreria CI / O dovrebbe essere usata nel codice 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; } 

I manipolatori IO sono ciò di cui hai bisogno. setw , in particolare. Ecco un esempio dalla pagina di riferimento:

 // setw example #include  #include  using namespace std; int main () { cout < < setw (10); cout << 77 << endl; return 0; } 

Giustificare il campo a sinistra ea destra è fatto con i manipolatori left e right .

Dai anche un'occhiata al setfill . Ecco un tutorial più completo sulla formattazione dell'output in C ++ con i manipolatori io .

La funzione di manipolatore di setw sarà di aiuto qui.

Un altro modo per rendere la colonna allineata è la seguente:

 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; 

Dovremmo stimare la lunghezza massima dei valori per ogni colonna. In questo caso, i valori della colonna "Artista" non devono superare i 20 caratteri e così via.

Nel momento in cui emetti la prima riga,

 Artist Title Price Genre Disc Sale Tax Cash 

per ottenere “allineamento”, devi sapere “in anticipo” la larghezza di ogni colonna (altrimenti, l’allineamento è imansible). Una volta che conosci la larghezza necessaria per ogni colonna (ci sono diversi modi possibili per farlo a seconda di dove provengono i tuoi dati), allora la funzione setw menzionata nell’altra risposta ti aiuterà, o (più brutalmente 😉 potresti emettere numero di spazi extra calcolato con cura (clunky, per essere sicuri), ecc. Non consiglio comunque le tabulazioni perché non hai un vero controllo su come il dispositivo di output finale renderà quelle, in generale.

Tornando al problema principale, ad esempio, se si dispone del valore di ogni colonna in un vector di un certo tipo, ad esempio, è ansible eseguire una prima passata di formattazione per determinare la larghezza massima della colonna, ad esempio (assicurarsi di prendere in considerazione anche la larghezza dell’intestazione per la colonna, ovviamente).

Se le tue righe stanno arrivando “una ad una” e l’allineamento è cruciale, dovrai mettere in cache o bufferizzare le righe non appena entrano (in memoria se si adattano, altrimenti su un file su disco che verrà successivamente “riavvolto”) e riletto dall’inizio), avendo cura di mantenere aggiornato il vettore delle “larghezze massime di ogni colonna” man mano che le righe arrivano. Non puoi produrre nulla (nemmeno le intestazioni!), Se mantenere l’allineamento è cruciale, fino a quando non hai visto l’ultima riga (a meno che tu non abbia magicamente una conoscenza delle larghezze delle colonne, ovviamente ;-).