2010-03-21 53 views
54

¿Hay alguna manera de alinear el texto al imprimir usando std::cout? Estoy usando pestañas, pero cuando las palabras son demasiado grandes ya no estarán alineadas.Alineación de C++ al imprimir 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

Las respuestas a continuación permiten especificar el ancho de una columna. Tenga en cuenta que esto requiere que conozca un límite superior (por ejemplo, la restricción de la base de datos) o que lo calcule de antemano (lo que puede significar analizar toda la estructura antes de comenzar a imprimirla). El segundo, aunque necesario, es más lento, por supuesto :) –

Respuesta

7

La función del manipulador setw será de ayuda aquí.

+3

También debe mencionar 'left' y' right' que permite especificar la alineación y 'setfill' que permite especificar con qué carácter se completa (espacio de forma predeterminada). –

8

IO manipuladores son lo que necesita. setw, en particular. He aquí un ejemplo de la página de referencia:

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

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

Justificar el campo a la izquierda y la derecha se hace con los left y right manipuladores.

También eche un vistazo a setfill. Aquí hay un tutorial más completo en formatting C++ output with io manipulators.

4

En el momento de emitir la primera línea,

Artist Title Price Genre Disc Sale Tax Cash 

para lograr la "alineación", usted tiene que saber "por adelantado" el ancho de cada columna tendrá que ser (de lo contrario, la alineación es imposible) . Una vez que haga conozca el ancho necesario para cada columna (hay varias maneras posibles de lograr eso dependiendo de dónde provengan sus datos), entonces la función setw mencionada en la otra respuesta le ayudará, o (más brutalmente ;-) usted podría emitir una cantidad calculada de espacios adicionales (torpe, para estar seguro), etc. No recomiendo las pestañas de todos modos ya que no tiene control real sobre cómo el dispositivo de salida final los renderizará, en general.

Volviendo a la cuestión central, si tiene el valor de cada columna en un vector<T> de algún tipo, por ejemplo, puede hacer un primer pase de formateo para determinar el ancho máximo de la columna, por ejemplo (asegúrese de tener en cuenta cuenta el ancho del encabezado de la columna, también, por supuesto).

Si sus filas vienen "una por una", y la alineación es crucial, tendrá que almacenar en caché o almacenar las filas tal como vienen (en la memoria si caben, de lo contrario en un archivo de disco que más tarde "rebobinar" y volver a leer desde el principio), teniendo cuidado de mantener actualizado el vector de "anchos máximos de cada columna" a medida que llegan las filas. No se puede generar nada (¡ni siquiera los encabezados!), Si mantener la alineación es crucial, hasta que hayas visto la última fila (a menos que de alguna manera mágicamente tengas conocimiento previo del ancho de las columnas, por supuesto ;-).

112

La forma estándar de ISO C++ para hacerlo es #include <iomanip> y utiliza manipuladores io como std::setw. Sin embargo, dicho esto, los manipuladores son un verdadero dolor para usar incluso para texto, y son casi inutilizables para formatear números (supongo que quiere que sus cantidades en dólares se alineen en el decimal, que tengan la cantidad correcta de dígitos significativos, etc. .). Incluso para las etiquetas de sólo texto plano, el código se verá algo como esto durante la primera parte de su primera línea:

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

Si usted es capaz de utilizar el Boost libraries, ejecute (no a pie) y el uso de la Boost.Format biblioteca en su lugar. Es totalmente compatible con los iostremas estándar, y le da toda la bondad para un fácil formateo con la cadena de formateo de impresión/Posix, pero sin perder nada de la potencia y la conveniencia de los propios iostreams.Por ejemplo, las primeras partes de sus dos primeras líneas se vería algo como:

// 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 es realmente agradable :) –

+2

'Boost.Format' se ve genial. Formato directo de estilo 'printf' con seguridad de tipo. – dreamlax

+4

Formatos posicionales también, lo cual es excelente, ya que significa que puede extraerlos de un archivo de localización. –

9

Ver también: 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

Otra manera de hacer que la columna alineada es el siguiente:

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; 

Debemos estimar la longitud máxima de los valores para cada columna. En este caso, los valores de la columna "Artista" no deben exceder los 20 caracteres, etc.

Cuestiones relacionadas