Partilhar via


Usando operadores de inserção e controlando o formato

Este tópico mostra como controlar o formato e como criar operadores de inserção para suas próprias classes. O operador de inserção (<<), que é pré-programado para todos os tipos de dados C++ padrão, envia bytes para um objeto de fluxo de saída. Os operadores de inserção trabalham com "manipuladores" predefinidos, que são elementos que alteram o formato padrão de argumentos inteiros.

Você pode controlar o formato com as seguintes opções:

Largura de saída

Para alinhar a saída, especifique a largura de saída para cada item colocando o manipulador de setw no fluxo ou chamando a função de membro width. Este exemplo alinha à direita os valores em uma coluna com pelo menos 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 à esquerda são adicionados a qualquer valor com menos de 10 caracteres de largura.

Para preencher um campo, use a função de membro fill, que define o valor do caractere de preenchimento para campos que têm uma largura especificada. O padrão é um espaço em branco. Para preencher a coluna de números com asteriscos, modifique o loop de for anterior da seguinte maneira:

for (int i = 0; i <4; i++)
{
    cout.width(10);
    cout.fill('*');
    cout << values[i] << endl;
}

O manipulador de 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 larguras para elementos de dados na mesma linha, use o manipulador de 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 de membro width é declarada em <iostream>. Se você usar setw ou qualquer outro manipulador com argumentos, você deve incluir <iomanip>. Na saída, as cadeias de caracteres imprimem em um campo de largura 7 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 truncam valores. Se a saída formatada exceder a largura, todo o valor será impresso, sujeito à configuração de precisão do fluxo. Tanto setw quanto width afetam apenas o campo a seguir. A largura do campo reverte para seu comportamento padrão (a largura necessária) depois que um campo é impresso. No entanto, as outras opções de formato de fluxo permanecem em vigor até serem alteradas.

Alinhamento

Os fluxos de saída são padronizados para texto alinhado à direita. Para alinhar à esquerda os nomes no exemplo anterior e alinhar à direita os números, substitua o loop for da seguinte maneira:

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 de setiosflags com o enumerador left. Esse enumerador é definido na classe ios, portanto, sua referência deve incluir o prefixo ios::. O manipulador de resetiosflags desativa o sinalizador de alinhamento à esquerda. Ao contrário de width e setw, o efeito de setiosflags e resetiosflags é permanente.

Precisão

O valor padrão para precisão de ponto flutuante é seis. Por exemplo, o número 3466.9768 é impresso como 3466.98. Para alterar a forma como esse valor é impresso, use o manipulador de setprecision. O manipulador tem duas bandeiras: fixed e scientific. Se fixed estiver definido, o número será impresso como 3466.976800. Se scientific estiver definido, ele será impresso como 3,4669773+003.

Para exibir os números de vírgula flutuante mostrados em de alinhamento com um dígito significativo, substitua o loop de for da seguinte maneira:

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 esta declaração antes do for loop:

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 de ios::fixed para ios::scientific, o programa imprime isso:

Zoot    1.2e+00
Jimmy   3.5e+01
Al      6.5e+02
Stan    4.4e+03

Novamente, o programa imprime um dígito após o ponto decimal. Se ios::fixed ou ios::scientific estiver definido, o valor de precisão determinará o número de dígitos após a vírgula decimal. Se nenhum sinalizador estiver definido, o valor de precisão determinará o número total de dígitos significativos. O manipulador de resetiosflags limpa essas bandeiras.

Radix

Os manipuladores dec, octe hex definem o radix padrão para entrada e saída. Por exemplo, se você inserir o manipulador de hex no fluxo de saída, o objeto traduzirá corretamente a representação de dados internos de inteiros em um formato de saída hexadecimal. Os números são exibidos com dígitos de a a f em minúsculas se o sinalizador de uppercase estiver claro (o padrão); caso contrário, eles serão exibidos em maiúsculas. O radix padrão é dec (decimal).

Cadeias de caracteres entre aspas (C++14)

Quando você insere uma cadeia de caracteres em um fluxo, você pode facilmente recuperar a mesma cadeia de caracteres chamando a função de membro stringstream::str(). No entanto, se você quiser usar o operador de extração para inserir o fluxo em uma nova cadeia de caracteres em um ponto posterior, você pode obter um resultado inesperado porque o operador >> por padrão irá parar 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 superado manualmente, mas para tornar a string round-tripping mais conveniente, o C++14 adiciona o manipulador de fluxo de std::quoted em <iomanip>. Após a inserção, quoted() envolve a string com um delimitador (aspas duplas ' " ' por padrão) e após a extração manipula o fluxo para extrair todos os caracteres até que o delimitador final seja encontrado. Todas as aspas incorporadas são escapadas com um caractere de escape ('\\' por padrão).

Os delimitadores estão presentes apenas no objeto de fluxo; eles não estão presentes na string extraída, mas estão presentes na string retornada por basic_stringstream::str.

O comportamento de espaço em branco das operações de inserção e extração é independente de como uma cadeia de caracteres é representada no código, portanto, o operador entre aspas é útil independentemente de a cadeia de caracteres de entrada ser uma cadeia de caracteres bruta literal ou uma cadeia de caracteres regular. A cadeia de entrada, seja qual for o seu formato, pode ter aspas incorporadas, quebras de linha, tabulações e assim por diante, e tudo isso será preservado pelo manipulador de quoted().

Para obter mais informações e exemplos de código completo, consulte quoted.

Ver também

Fluxos de saída