Alinhamento C ++ ao imprimir cout <<

Existe uma maneira de alinhar o texto ao imprimir usando std::cout ? Estou usando abas, mas quando as palavras são muito grandes elas não estarão mais alinhadas.

 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 

A maneira padrão do ISO C ++ de fazer isso é #include e usar manipuladores de io como std::setw . No entanto, dito isso, esses manipuladores são uma dor real para usar até mesmo para texto, e são praticamente inutilizáveis ​​para formatar números (suponho que você queira que seus valores em dólar se alinhem no decimal, tenha o número correto de dígitos significativos, etc. . Mesmo para apenas labels de texto simples, o código será algo parecido com isto para a primeira parte da sua primeira linha:

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

Se você puder usar as bibliotecas do Boost , execute (não ande) e use a biblioteca Boost.Format . É totalmente compatível com o padrão iostreams, e dá a você todo o bem para fácil formatação com string de formatação printf / Posix, mas sem perder a potência e a conveniência do próprio iostreams. Por exemplo, as primeiras partes de suas duas primeiras linhas seriam 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; 

Veja também: Qual biblioteca de CI / O deve ser usada no código 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; } 

Os manipuladores de IO são o que você precisa. setw , em particular. Aqui está um exemplo da página de referência:

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

Justificar o campo à esquerda e à direita é feito com os manipuladores left e right .

Também dê uma olhada no setfill . Aqui está um tutorial mais completo sobre formatação de saída em C ++ com manipuladores de io .

A function manipuladora setw ajudará aqui.

Outra maneira de alinhar colunas é a seguinte:

 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; 

Devemos estimar o comprimento máximo de valores para cada coluna. Nesse caso, os valores da coluna "Artista" não devem exceder 20 caracteres e assim por diante.

No momento em que você emite a primeira linha,

 Artist Title Price Genre Disc Sale Tax Cash 

para alcançar o “alinhamento”, você precisa saber “antecipadamente” qual será a largura de cada coluna (caso contrário, o alinhamento é impossível). Uma vez que você saiba a largura necessária para cada coluna (existem várias maneiras possíveis de conseguir isso dependendo de onde seus dados estão vindo), então a function setw mencionada na outra resposta ajudará, ou (mais brutalmente 😉 você pode emitir Um número cuidadosamente calculado de espaços extras (desajeitado, com certeza), etc. Eu não recomendo abas de qualquer forma, já que você não tem controle real sobre como o dispositivo de saída final renderizará esses, em geral.

De volta ao problema principal, se você tiver o valor de cada coluna em um vector de algum tipo, por exemplo, poderá fazer um primeiro passo de formatação para determinar a largura máxima da coluna, por exemplo (não se esqueça de levar em consideração a largura do header da coluna também, é claro).

Se as suas linhas vierem “uma a uma”, e o alinhamento for crucial, você terá que armazenar em cache ou armazenar em buffer as linhas conforme elas entram (na memory, se elas couberem; caso contrário, em um arquivo de disco que você “retrocederá” mais tarde) e reler desde o início), tendo o cuidado de manter atualizado o vetor de “larguras máximas de cada coluna” à medida que as linhas chegam. Você não pode produzir nada (nem mesmo os headers!), Se manter o alinhamento é crucial, até que você tenha visto a última linha (a menos que, de algum modo, você tenha conhecimento prévio das larguras das colunas, é claro ;-).