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 7 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 dec
manipolatori , oct
e 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)