Usando operadores de inserção e controlando o formato
Este tópico mostra como controlar o formato e a criação de operadores de inserção para suas próprias classes. O operador de inserção (<<
), que é programado previamente para todos os tipos de dados C++, envia bytes a um objeto de fluxo de saída. Operadores de inserção trabalham com "manipuladores" predefinidos, que são elementos que alteram o formato padrão de argumentos inteiros.
É possível controlar o formato com as seguintes opções:
Largura da Saída
Para alinhar a saída, especifique a largura da saída para cada item colocando o manipulador setw
no fluxo ou chamando a width
função membro de largura. Este exemplo alinha à direita os valores em uma coluna com pelo menor 10 caracteres de largura:
// output_width.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main( )
{
double values[] = { 1.23, 35.36, 653.7, 4358.24 };
for( int i = 0; i < 4; i++ )
{
cout.width(10);
cout << values[i] << '\n';
}
}
1.23
35.36
653.7
4358.24
Os espaços em branco são adicionados a qualquer valor menor do que 10 caracteres de largura.
Para preencher um campo, use a função membro fill
que define o valor do caractere de preenchimento para campos com uma largura especificada. O padrão é um espaço em branco. Para preencher a coluna de números com asteriscos, modifique o loop for
anterior da seguinte forma:
for (int i = 0; i <4; i++)
{
cout.width(10);
cout.fill('*');
cout << values[i] << endl;
}
O manipulador endl
substitui o caractere de nova linha ('\n'
). A saída tem esta aparência:
******1.23
*****35.36
*****653.7
***4358.24
Para especificar as larguras de elementos de dados na mesma linha, use o manipulador setw
:
// setw.cpp
// compile with: /EHsc
#include <iostream>
#include <iomanip>
using namespace std;
int main( )
{
double values[] = { 1.23, 35.36, 653.7, 4358.24 };
const char *names[] = { "Zoot", "Jimmy", "Al", "Stan" };
for( int i = 0; i < 4; i++ )
cout << setw( 7 ) << names[i]
<< setw( 10 ) << values[i] << endl;
}
A função membro width
é declarada em <iostream>
. Se você usar setw
ou qualquer outro manipulador com argumentos, deverá incluir <iomanip>
. Na saída, as cadeia de caracteres são impressas em um campo de largura 6 e inteiros em um campo de largura 10:
Zoot 1.23
Jimmy 35.36
Al 653.7
Stan 4358.24
setw
e width
não trunque valores. Se a saída formatada exceder a largura, o valor inteiro será impresso, sujeito a configuração de precisão do fluxo. Ambos setw
e width
afetam apenas o campo a seguir. A largura do campo será revertida para seu comportamento padrão (a largura necessária) após a impressão de um campo. No entanto, as outras opções de formato de fluxo permanecerão em vigor até serem alteradas.
Alinhamento
Fluxos de saída padrão para o texto alinhado à direita. Para alinhar os nomes do exemplo anterior à esquerda e os números à direita, substitua o loop for
da seguinte forma:
for (int i = 0; i <4; i++)
cout << setiosflags(ios::left)
<< setw(6) << names[i]
<< resetiosflags(ios::left)
<< setw(10) << values[i] << endl;
A saída tem esta aparência:
Zoot 1.23
Jimmy 35.36
Al 653.7
Stan 4358.24
O sinalizador de alinhamento à esquerda é definido usando o manipulador setiosflags
com o enumerador left
. Esse enumerador é definido na classe ios
portanto, a referência deverá incluir o prefixo ios::
. O manipulador resetiosflags
desliga o sinalizador de alinhamento à esquerda. Ao contrário de width
e setw
, o efeito de setiosflags
e resetiosflags
é permanente.
Precision
O valor padrão para a precisão de ponto flutuante é seis. Por exemplo, o número 3466.9768 será impresso como 3466.98. Para alterar a forma como esse valor será impresso, use o manipulador setprecision
. O manipulador tem dois sinalizadores: fixed
e scientific
. Se fixed
estiver definido, o número será impresso como 3466,976800. Se scientific
estiver definido, será impresso como 3.4669773+003.
Para exibir os números de ponto flutuante mostrados em Alinhamento com um dígito significativo, substitua o loop for
da seguinte forma:
for (int i = 0; i <4; i++)
cout << setiosflags(ios::left)
<< setw(6)
<< names[i]
<< resetiosflags(ios::left)
<< setw(10)
<< setprecision(1)
<< values[i]
<< endl;
O programa imprime esta lista:
Zoot 1
Jimmy 4e+01
Al 7e+02
Stan 4e+03
Para eliminar a notação científica, insira essa instrução antes do loop for
:
cout << setiosflags(ios::fixed);
Com notação fixa, o programa imprime com um dígito após a vírgula decimal.
Zoot 1.2
Jimmy 35.4
Al 653.7
Stan 4358.2
Se você alterar o sinalizador ios::fixed
para ios::scientific
, o programa imprimirá:
Zoot 1.2e+00
Jimmy 3.5e+01
Al 6.5e+02
Stan 4.4e+03
Novamente, o programa imprimirá um dígito após a vírgula decimal. Se ios::fixed
ou ios::scientific
estiver definido, o valor de precisão determinará o número de dígitos após o ponto decimal. Se nenhum sinalizador for definido, o valor de precisão determinará o número total de dígitos significativos. O manipulador resetiosflags
limpará esses sinalizadores.
Radix
Os manipuladores dec
, oct
e hex
definem a base padrão para entrada e saída. Por exemplo, se você inserir o manipulador hex
no fluxo de saída, o objeto converterá corretamente a representação de dados internos de inteiros em um formato de saída hexadecimal. Os números serão exibidos com dígitos de a a f em letras minúsculas se o sinalizador uppercase
estiver limpo (o padrão), caso contrário, serão exibidos em letras maiúsculas. A base padrão é dec
(decimal).
Cadeias de caracteres entre aspas (C++14)
Ao inserir uma cadeia de caracteres em um fluxo, será possível recuperar facilmente a mesma cadeia de caracteres chamando a função membro stringstream::str()
. No entanto, se você quiser usar o operador de extração para inserir o fluxo em uma nova cadeia de caracteres posteriormente, poderá obter um resultado inesperado porque o operador >>
, por padrão, será interrompido quando encontrar o primeiro caractere de espaço em branco.
std::stringstream ss;
std::string inserted = "This is a sentence.";
std::string extracted;
ss << inserted;
ss >> extracted;
std::cout << inserted; // This is a sentence.
std::cout << extracted; // This
Esse comportamento pode ser corrigido manualmente, mas para tornar o ciclo completo de cadeia de caracteres mais conveniente, C++14 adiciona o manipulador de fluxo std::quoted
a <iomanip>
. Na inserção, o quoted()
envolve a cadeia de caracteres com um delimitador (aspas duplas ' " ', por padrão) e na extração manipula o fluxo para extrair todos os caracteres até encontrar o delimitador final. Aspas inseridas são ignoradas com um caractere de escape ('\\' por padrão).
Os delimitadores estão presentes apenas no objeto de fluxo, portanto, não estão presentes na cadeia de caracteres extraída, mas estão presentes na cadeia de caracteres retornada por basic_stringstream::str
.
O comportamento de espaço em branco das operações de inserção e extração é independe de como uma cadeia de caracteres é representada no código, assim, o operador entre aspas será útil mesmo se a cadeia de caracteres de entrada for uma cadeia de caracteres bruta, literal ou regular. A cadeia de caracteres de entrada, independente do seu formato, poderá ter aspas, quebras de linha, tabulações, e assim por diante, que serão preservados pelo manipulador quoted()
.
Para obter mais informações e exemplos de código completos, consulte quoted
.