Uso degli operatori di inserimento e controllo del formato

Questo argomento illustra come controllare il formato e creare gli operatori di inserimento per le classi personalizzate. L'operatore di inserimento (<<), che è preprogrammato per tutti i tipi di dati C++ standard, invia byte a un oggetto del flusso di output. Gli operatori di inserimento funzionano con "manipolatori" predefiniti, cioè elementi che modificano il formato predefinito di argomenti Integer.

È possibile controllare il formato con le opzioni seguenti:

Larghezza di output

Per allineare l'output, specificare la larghezza di output per ogni elemento inserendo il setw manipolatore nel flusso o chiamando la width funzione membro. Questo esempio allinea a destra i valori in una colonna ampia almeno 10 caratteri:

// 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

Gli spazi a sinistra vengono aggiunti a qualsiasi valore inferiore a 10 caratteri.

Per riempire un campo, utilizzare la fill funzione membro, che imposta il valore del carattere di riempimento per i campi con una larghezza specificata. Il valore predefinito è vuoto. Per riempire la colonna di numeri con asterischi, modificare il ciclo precedente for nel modo seguente:

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

Il manipolatore endl sostituisce il carattere di nuova riga ('\n'). L'output sarà simile al seguente:

******1.23
*****35.36
*****653.7
***4358.24

Per specificare la larghezza per elementi di dati nella stessa riga, usare il manipolatore 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;
}

La width funzione membro viene dichiarata in <iostream>. Se si usa setw o qualsiasi altro manipolatore con argomenti, è necessario includere <iomanip>. Nell'output le stringhe vengono stampate in un campo di larghezza 6 e numeri interi in un campo di larghezza 10:

   Zoot      1.23
  Jimmy     35.36
     Al     653.7
   Stan   4358.24

setw e width non troncare i valori. Se l'output formattato supera la larghezza, viene stampato il valore intero, soggetto alle impostazioni di precisione del flusso. Sia setw che width influiscono solo sul campo seguente. Viene ripristinato il comportamento predefinito della larghezza del campo (larghezza necessaria) dopo la stampa di un campo. Le altre opzioni di formato di flusso, tuttavia, rimangono valide finché non vengono modificate.

Allineamento

Per impostazione predefinita, i flussi di output sono allineati a destra. Per allineare a sinistra i nomi nell'esempio precedente e allineare a destra i numeri, sostituire il for ciclo come segue:

for (int i = 0; i <4; i++)
    cout << setiosflags(ios::left)
         << setw(6) << names[i]
         << resetiosflags(ios::left)
         << setw(10) << values[i] << endl;

L'output sarà simile al seguente:

Zoot        1.23
Jimmy      35.36
Al         653.7
Stan     4358.24

Il flag di allineamento a sinistra viene impostato usando il setiosflags manipolatore con l'enumeratore left . Questo enumeratore è definito nella ios classe , pertanto il relativo riferimento deve includere il ios:: prefisso . Il resetiosflags manipolatore disattiva il flag di allineamento a sinistra. A differenza di width e setw, l'effetto di setiosflags e resetiosflags è permanente.

Precisione

Il valore predefinito per la precisione a virgola mobile è sei. Ad esempio, il numero 3466.9768 viene stampato come 3466.98. Per modificare la modalità di stampa di questo valore, utilizzare il setprecision manipolatore. Il manipolatore ha due flag: fixed e scientific. Se fixed è impostato, il numero viene stampato come 3466,976800. Se scientific è impostato, viene stampato come 3.4669773+003.

Per visualizzare i numeri a virgola mobile visualizzati in Allineamento con una cifra significativa, sostituire il for ciclo come segue:

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;

Il programma stampa questo elenco:

Zoot          1
Jimmy     4e+01
Al        7e+02
Stan      4e+03

Per eliminare la notazione scientifica, inserire questa istruzione prima del for ciclo:

cout << setiosflags(ios::fixed);

Con la notazione fissa, il programma stampa con una cifra dopo il separatore decimale.

Zoot         1.2
Jimmy       35.4
Al         653.7
Stan      4358.2

Se si modifica il ios::fixed flag in ios::scientific, il programma stampa quanto segue:

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

Anche in questo caso, il programma stampa con una cifra dopo il separatore decimale. ios::fixed Se o ios::scientific è impostato, il valore di precisione determina il numero di cifre dopo il separatore decimale. Se nessuno dei due flag è impostato, il valore di precisione determina il numero totale di cifre significative. Il manipolatore resetiosflags cancella questi flag.

Base

I decmanipolatori , octe hex impostano il radix predefinito per l'input e l'output. Ad esempio, se si inserisce il hex manipolatore nel flusso di output, l'oggetto converte correttamente la rappresentazione interna dei dati di interi in un formato di output esadecimale. I numeri vengono visualizzati con cifre da a f in lettere minuscole se il uppercase flag è chiaro (impostazione predefinita). In caso contrario, vengono visualizzati in lettere maiuscole. Il file radix predefinito è dec (decimale).

Stringhe tra virgolette (C++14)

Quando si inserisce una stringa in un flusso, è possibile recuperare facilmente la stessa stringa chiamando la stringstream::str() funzione membro. Tuttavia, se si desidera utilizzare l'operatore di estrazione per inserire il flusso in una nuova stringa in un secondo momento, è possibile ottenere un risultato imprevisto perché l'operatore >> per impostazione predefinita si arresterà quando trova il primo carattere di spazio vuoto.

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

Questo comportamento può essere aggirato manualmente, ma per rendere più pratiche le sequenze di andata e ritorno, C++14 aggiunge il manipolatore del flusso std::quoted in <iomanip>. Al momento dell'inserimento, quoted() racchiude la stringa con un delimitatore (virgolette doppie " " per impostazione predefinita) e quando l'estrazione modifica il flusso per estrarre tutti i caratteri fino a quando non viene trovato il delimitatore finale. Le virgolette incorporate vengono precedute da un carattere di escape ('\\' per impostazione predefinita).

I delimitatori sono presenti solo nell'oggetto flusso; non sono presenti nella stringa estratta, ma sono presenti nella stringa restituita da basic_stringstream::str.

Il comportamento degli spazi vuoti delle operazioni di inserimento e di estrazione è indipendente dal modo in cui una stringa è rappresentata nel codice, dunque l'operatore tra virgolette è utile indipendentemente dal fatto che la stringa di input sia un valore letterale stringa non elaborato o una stringa normale. La stringa di input, indipendentemente dal formato, può avere virgolette incorporate, interruzioni di riga, tabulazioni e così via e tutte queste verranno mantenute dal quoted() manipolatore.

Per altre informazioni ed esempi di codice completi, vedere quoted.

Vedi anche

Output Streams (Flussi di output)