Formattazione di stringhe in .NET
Il .NET Framework fornisce una vasta gamma di opzioni per formattare stringhe, così da rappresentare in modo esaustivo i principali tipi (numerici, date, valuta, enumeratori, ecc.)
In questo articolo verranno evidanziati i diversi formati disponibili, fornendo per ciascun caso un esempio esaustivo di utilizzo, così da costituire una valida guida da tenere sempre sottomano.
In particolare verranno fornite indicazioni sugli identificatori di formato per:
Format Item
Tipicamente la formattazione di stringhe è una delle caratteristiche più utilizzate di un linguaggio. In .NET abbiamo diversi metodi che sfruttano la composizione di stringhe tramite l'uso di placeholder (detti anche format item) come ad esempio:
String.Format che restituisce la stringa formattata
Console.WriteLine che mostra la stringa formattata nella console
TextWriter.WriteLine che scrive la stringa formattata in uno stream o in un file
Consideriamo ad esempio l'overload di String.Format seguente:
public static string Format (string format, params Object[] args)
L'elenco di oggetti args rappresenta l'insieme di valori da sostituire ai rispettivi format item che intervallano il testo fisso in ingresso format.
I segnaposto vengono espressi nella forma:
{index[,alignment][:formatString]}
dove:
-
index rappresenta l'indice numerico (che parte da zero) corrispondente all'oggetto nell'elenco degli args.
Eventuali elementi di args privi di un corrispondente segnaposto non verranno considerati, mentre un eventuale segnaposto privo del corrispondente elemento in args solleverà una runtime exception
-
alignment è un elemento opzionale di tipo intero con segno che indica la larghezza del campo formattato risultante. Il valore risultante sarà allineato alla destra del campo se alignment è positivo o a sinistra se alignment è negativo.
Se il valore di alignment è inferiore alla lunghezza della stringa formattata il parametro non viene considerato.
-
formatString è un parametro opzionale che specifica il formato per la rappresentazione del singolo format item. Si veda il seguito dell'articolo per la descrizione dei valori ammessi per formatString in funzione del tipo di oggetto che si desidera rappresentare.
Se formatString viene omesso verrà utilizzato il formato generale ("G")
NOTA: le parentesi graffe sono interpretate come identificatori di placeholder; per rappresentare l'apertuta di una parentesi graffa nel risultato della formattazione è necessario inserire due aperture di parentesi graffe ({{) nel testo fisso format; la gestione dell'escaping della chiusura delle parentesi graffa è analogo a quello per l'apertura della stessa (}} per rappresentare })
Gli oggetti in args verranno rappresentati in formato stringa come:
se null come stringa vuota ("")
se il tipo implementa l'interfaccia ICustomFormatter mediante la chiamata al metodo ICustomFormatter.Format
se il tipo implementa l'interfaccia IFormattable mediante la chiamata al metodo IFormattable.ToString
mediante la chiamata al metodo ToString dell'oggetto (Object.ToString)
L'output di tutti gli esempi che seguono è riferito alle impostazioni internazionali italiane: CultureInfo("it-IT")
DEMO 1
Il seguente codice:
string Name = "Matteo";
Console.WriteLine("I am '{0}'", Name);
Console.WriteLine("I am '{0,10}'", Name);
Console.WriteLine("I am '{0,-10}'", Name);
Produrra:
I am 'Matteo'I am ' Matteo'
I am 'Matteo '
Formattazione di tipi numerici
La formattazione di un tipo numerico può essere in forma standard (mediante l'applicazione di uno stile predefinito per il tipo numerico specifico con la possibilità di definirne la precisione) o custom (mediante un formato specificato dall'utente)
Stringhe di formato numerico standard
La formattazione standard prevede la dichiarazione del formato nella forma Ann dove A è un singolo carattere alfabetico che specifica il formato (vedi tabella seguente) e nn è un intero che specifica la precisione (opzionale)
| Formato | Nome | Esempio | Output |
| C (o c) | Valuta (currency) |
String.Format("{0:c}", 123456.789);
String.Format("{0:c5}", 123456.789);
String.Format("{0:c}", -123456.789);
|
€ 123.456,79 € 123.456,78900 -€ 123.456,79 |
|---|---|---|---|
| D (o d) | Decimale |
String.Format("{0:d}", 123456);
String.Format("{0:d10}", 123456);
|
123456 0000123456 |
| E (o e) | Scientifico (esponenziale) |
String.Format("{0:e}", 123456.789);
String.Format("{0:e10}", 123456.789);
|
1,234568e+005 12345678900+005 |
| F (o f) | A virgola fissa |
String.Format("{0:f}", 123456.789);
String.Format("{0:f5}", 123456.789);
|
123456,79 123456,78900 |
| G (o g) | Generale |
String.Format("{0:g}", 123456.789);
String.Format("{0}", 123456.789);
|
123456,79 123456,79 |
Predefinito (le due notazioni d'esempio sono equivalenti). |
|||
| N (o n) | Numero |
String.Format("{0:n}", 123456.789);
String.Format("{0:n5}", 123456.789);
|
123.456,79 123.456,78900 |
Vengono inseriti separatori delle migliaia tra ciascun gruppo di tre cifre a sinistra del separatore decimale. |
|||
| P (o p) | Percentuale |
String.Format("{0:p}", 0.123456789);
String.Format("{0:p}", 123456.789);
String.Format("{0:p10}", 0.123456789);
|
12,35% 12.345.678,90% 12,3456789000% |
Il numero convertito viene moltiplicato per 100 in modo da essere presentato come una percentuale. L'identificatore di precisione indica il numero di posizioni decimali desiderato. |
|||
| R (o r) | Riconversione |
String.Format("{0:r}", 123456.789);
|
123456,789 |
L'identificatore di riconversione garantisce che un valore numerico convertito in una stringa venga riportato al medesimo valore numerico. Sebbene sia possibile aggiungere un identificatore di precisione all'identificatore di formato di riconversione, tale identificatore di precisione viene comunque ignorato. Quando si utilizza questo identificatore, infatti, il formato della riconversione ha la precedenza sulla precisione. Questo formato è supportato solo dai tipi a virgola mobile. |
|||
| X (o x) | Esadecimale (Hex) |
String.Format("{0:x}", 12);
String.Format("{0:X}", 12);
String.Format("{0:X}", 123456789);
|
c C 75BCD15 |
Il numero viene convertito in una stringa di cifre esadecimali. L'utilizzo della lettera maiuscola e minuscola nell'identificatore di formato indica se verranno utilizzati caratteri maiuscoli o minuscoli per le cifre esadecimali maggiori di 9. |
|||
Stringhe di formato numerico personalizzato
Se gli identificatori di formato numerico standard non forniscono il tipo di formattazione desiderata, sarà possibile utilizzare stringhe di formato personalizzato. Una stringa di formato standard è costituita da un singolo carattere alfabetico, eventualmente seguito da una sequenza di cifre che rappresenta un valore compreso tra 0 e 99. Tutte le altre stringhe di formato corrispondono a stringhe di formato personalizzato.
| Carattere di formato | Nome | Descrizione |
| 0 | Segnaposto per zero | Se il valore da formattare dispone di una cifra nella posizione in cui nella stringa di formato si trova uno "0", tale cifra verrà copiata nella stringa di risultati. La posizione dell'ultimo "0" a sinistra prima del separatore decimale e dell'ultimo "0" a destra dopo il separatore decimale determina l'intervallo di cifre sempre presenti nella stringa di risultati. |
|---|---|---|
| # | Segnaposto per cifre | Se il valore da formattare dispone di una cifra nella posizione in cui nella stringa di formato si trova uno "#", tale cifra verrà copiata nella stringa di risultati. In caso contrario, nella stringa di risultati non verrà memorizzato alcun valore in tale posizione. |
| . | Separatore decimale | Il primo carattere "," della stringa di formato determina la posizione del separatore decimale nel valore formattato. Eventuali ulteriori caratteri "," vengono ignorati. |
| , | Separatore delle migliaia e rappresentazione in scala dei numeri | Il carattere "." ha due funzioni. In primo luogo, se la stringa di formato contiene un carattere "." tra due segnaposti per cifre (0 o #) e se a sinistra del separatore decimale ne è presente uno, l'output presenterà separatori delle migliaia inseriti tra ciascun gruppo di tre cifre a sinistra del separatore decimale. In secondo luogo, se la stringa di formato contiene uno o più caratteri "." immediatamente a sinistra del separatore decimale, il numero verrà diviso per 1000 tante volte quanti sono i caratteri "." prima di essere formattato. |
| % | Segnaposto per percentuale | La presenza di un carattere "%" in una stringa di formato fa sì che un numero venga moltiplicato per 100 prima di essere formattato. Il simbolo appropriato viene inserito nel numero stesso nella posizione in cui è stato inserito il segno "%" nella stringa di formato. |
|
E0 E+0 E-0 e0 e+0 e-0 |
Notazione scientifica | Se nella stringa di formato è presente una delle stringhe "E", "E+", "E-", "e", "e+" o "e-" immediatamente seguita da almeno un carattere "0", il numero verrà formattato utilizzando la notazione scientifica con una "E" o "e" inserita tra il numero e l'esponente. Il numero dei caratteri "0" che seguono l'indicatore della notazione scientifica determina il numero minimo di cifre da visualizzare nell'output per l'esponente. I formati "E+" ed "e+" indicano che l'esponente deve essere sempre preceduto da un carattere di segno (più o meno). I formati "E", "E-", "e" ed "e-" indicano che solo gli esponenti negativi devono essere preceduti da un carattere di segno. |
| \ | Carattere escape | In C# e C++ il carattere barra rovesciata fa sì che il successivo carattere nella stringa di formato venga interpretato come sequenza di escape. Viene utilizzato con sequenze di formattazione tradizionali come "\n" (nuova riga). In alcuni linguaggi è necessario che il carattere di escape stesso sia preceduto da un carattere di escape quando viene utilizzato come un valore letterale. In caso contrario in fase di compilazione il carattere verrà interpretato come una sequenza di escape. Utilizzare la stringa "\\" per visualizzare il carattere "\". Si noti che questo carattere di escape non è supportato in Visual Basic. ControlChars fornisce tuttavia la stessa funzionalità. |
|
'ABC' "ABC" |
Stringa letterale | I caratteri racchiusi tra virgolette semplici o doppie vengono copiati nella stringa di risultati in modo letterale e non influiscono sulla formattazione. |
| ; | Separatore di sezione | Il carattere ";" è utilizzato per separare sezioni di valori positivi, negativi e zero nella stringa di formato. |
| (altro) | Tutti gli altri caratteri | Tutti gli altri caratteri vengono copiati nella stringa di risultati come valori letterali nella posizione in cui sono riportati. |
Esempi di utilizzo di stringhe di formato numerico personalizzato
| Esempio | Output |
( 12 ).ToString("000");
( 12 ).ToString("###");
( 12 ).ToString("0,000.00");
( 123456.789 ).ToString("0,000.00");
( 123456.789 ).ToString("0,###,###.00");
|
012 12 0.012,00 123.456,79 0.123.456,79 |
( 123456789 ).ToString("0,,.####"); |
12,34568 |
( 12 ).ToString("#%");
( 0.5678 ).ToString("#.000%");
( 0.5678 ).ToString("#.0%");
|
1200% 56,780% 56,8% |
( 123456789 ).ToString("###e0");
( 123456789 ).ToString("###E0");
( 123456789 ).ToString("###E+0");
( 0.123456789 ).ToString("###E-0");
|
123e6 123E6 123E+6 123E-6 |
( 123 ).ToString("Output is #"); |
Output is 123 |
( 12 ).ToString("Positive: 0,000.00;Negative: #");
( -12 ).ToString("Positive: 0,000.00;Negative: #");
( -12 ).ToString("Positive: 0,000.00;Negative: -#");
( -0.1 ).ToString("Positive: 0,000.00;Negative: -#;Zero!");
|
Positive: 0.012,00 Negative: 12 Negative: -12 Zero! |
Formattazione di data e ora
La formattazione di un tipo DateTime può essere in forma standard (mediante l'applicazione di uno stile predefinito) o custom (mediante un formato specificato dall'utente)
La data di riferimento (dt) utilizzata negli esempi seguenti corrisponde al 25 Aprile 2007 alle ore 14, 37 minuti, 54 secondi e 309 millesimi ed è definita come:
DateTime dt = new DateTime(2007, 4, 25, 14, 37, 54, 309);
Stringhe di formato DateTime standard
La formattazione standard prevede un singolo carattere tra quelli inclusi nella tabella riportata di seguito. Se l'identificatore di formato non è contenuto nella tabella che segue, verrà generata un'eccezione in fase di esecuzione. Se la stringa di formato è più lunga di un singolo carattere, verrà interpretata come una stringa di formato personalizzato, anche se i caratteri aggiuntivi sono costituiti da spazi.
| Formato | Nome | Esempio | Output |
| d | Data breve | dt.ToString("d"); |
25/04/2007 |
|---|---|---|---|
| D | Data estesa | dt.ToString("D"); |
mercoledì 25 aprile 2007 |
| t | Ora breve | dt.ToString("t"); |
14.37 |
| T | Ora estesa | dt.ToString("T"); |
14.37.54 |
| f | Data e ora completa (ora breve) | dt.ToString("f"); |
mercoledì 25 aprile 2007 14.37 |
| F | Data e ora completa (ora estesa) | dt.ToString("f"); |
mercoledì 25 aprile 2007 14.37.54 |
| g | Generale (ora breve) | dt.ToString("g"); |
25/04/2007 14.37 |
| G | Generale (ora estesa) | dt.ToString("G"); |
25/04/2007 14.37.54 |
| M (o m) | Mese e giorno | dt.ToString("m"); |
25 aprile |
| R (o r) | RFC 1123 | dt.ToString("r"); |
Wed, 25 Apr 2007 14:37:54 GMT |
| s | ISO 8601 | dt.ToString("s"); |
2007-04-25T14:37:54 |
| u | Universale | dt.ToString("u"); |
2007-04-25 14:37:54Z |
In occasione della formattazione della data e dell'ora non viene eseguita alcuna conversione di fuso orario. La conversione della data e dell'ora locali in tempo universale deve quindi essere eseguita prima di utilizzare questo identificatore di formato. |
|||
| U | Universale | dt.ToString("U"); |
mercoledì 25 aprile 2007 12.37.54 |
L'ora visualizzata è quella standard, non quella locale, ed equivale al valore DateTime. |
|||
| Y (o y) | Anno (year) e mese | dt.ToString("y"); |
aprile 2007 |
Stringhe di formato DateTime personalizzato
È possibile esercitare un maggiore controllo sulla formattazione di un oggetto DateTime utilizzando identificatori di formato personalizzati (vedi tabella seguente)
| Formato | Descrizione | Esempio | Output |
| d | Giorno del mese (1 cifra) |
dt.ToString("%d");
( new DateTime(2007, 4, 3) ).ToString("%d");
|
25 3 |
|---|---|---|---|
| dd | Giorno del mese (2 cifre) |
dt.ToString("dd");
( new DateTime(2007, 4, 3) ).ToString("dd");
|
25 03 |
| ddd | Giorno della settimana (abbreviato) | dt.ToString("ddd"); |
mer |
| dddd | Giorno della settimana (esteso) | dt.ToString("dddd"); |
mercoledì |
| f | Frazione di secondo (1 cifra, zeri visualizzati) | dt.ToString("%f"); |
3 |
| ff | Frazione di secondo (2 cifre, zeri visualizzati) | dt.ToString("ff"); |
30 |
| fff | Frazione di secondo (3 cifre, zeri visualizzati) | dt.ToString("fff"); |
309 |
| ffff | Frazione di secondo (4 cifre, zeri visualizzati) | dt.ToString("ffff"); |
3090 |
| fffff | Frazione di secondo (5 cifre, zeri visualizzati) | dt.ToString("fffff"); |
30900 |
| ffffff | Frazione di secondo (6 cifre, zeri visualizzati) | dt.ToString("ffffff"); |
309000 |
| fffffff | Frazione di secondo (7 cifre, zeri visualizzati) | dt.ToString("fffffff"); |
3090000 |
| F | Frazione di secondo (1 cifra, zeri omessi) | dt.ToString("%F"); |
3 |
| FF | Frazione di secondo (2 cifre, zeri omessi) | dt.ToString("FF"); |
3 |
| FFF | Frazione di secondo (3 cifre, zeri omessi) | dt.ToString("FFF"); |
309 |
| FFFF | Frazione di secondo (4 cifre, zeri omessi) | dt.ToString("FFFF"); |
309 |
| FFFFF | Frazione di secondo (5 cifre, zeri omessi) | dt.ToString("FFFFF"); |
309 |
| FFFFFF | Frazione di secondo (6 cifre, zeri omessi) | dt.ToString("FFFFFF"); |
309 |
| FFFFFFF | Frazione di secondo (7 cifre, zeri omessi) | dt.ToString("FFFFFFF"); |
309 |
| g (o gg) | Era (a.C. / d.C.) |
dt.ToString("%g");
dt.ToString("gg");
|
d.C. d.C. |
| h | Ora (1 cifra, 1-12) | dt.ToString("%h"); |
2 |
| hh | Ora (2 cifre, 1-12) | dt.ToString("hh"); |
02 |
| H | Ora (1 cifra, 0-23) |
dt.ToString("%H");
( new DateTime(2007, 4, 25, 9, 5, 7) ).ToString("%H");
|
14 9 |
| HH | Ora (2 cifre, 0-23) |
dt.ToString("HH");
( new DateTime(2007, 4, 25, 9, 5, 7) ).ToString("HH");
|
14 09 |
| m | Minuti (1 cifra) |
dt.ToString("%m");
( new DateTime(2007, 4, 25, 9, 5, 7) ).ToString("%m");
|
37 5 |
| mm | Minuti (2 cifre) |
dt.ToString("mm");
( new DateTime(2007, 4, 25, 9, 5, 7) ).ToString("mm");
|
37 05 |
| M | Mese (1 cifra) | dt.ToString("%M"); |
4 |
| MM | Mese (2 cifre) | dt.ToString("MM"); |
04 |
| MMM | Mese (abbreviato) | dt.ToString("MMM"); |
apr |
| MMMM | Mese (esteso) | dt.ToString("MMMM"); |
aprile |
| s | Secondi (1 cifra) |
dt.ToString("%s");
( new DateTime(2007, 4, 25, 9, 5, 7) ).ToString("%s");
|
54 7 |
| ss | Secondi (2 cifre) |
dt.ToString("ss");
( new DateTime(2007, 4, 25, 9, 5, 7) ).ToString("ss");
|
54 07 |
| t | Indicatore AM / PM (primo carattere) |
DateTimeFormatInfo fi = new DateTimeFormatInfo();
|
P |
Le impostazioni di default della cultura italiana non prevedono nessun simbolo di identificazione per AM e PM. Nell'esempio è stato dunque utilizzato un DateTimeFormatInfo per forzare la visualizzazione di questo formato. |
|||
| tt | Indicatore AM / PM (completo) |
DateTimeFormatInfo fi = new DateTimeFormatInfo();
|
Pomeriggio |
Le impostazioni di default della cultura italiana non prevedono nessun simbolo di identificazione per AM e PM. Nell'esempio è stato dunque utilizzato un DateTimeFormatInfo per forzare la visualizzazione di questo formato. |
|||
| y | Anno (1 cifra) | dt.ToString("%y"); |
7 |
| yy | Anno (2 cifre) | dt.ToString("yy"); |
07 |
| yyyy | Anno (4 cifre) | dt.ToString("yyyy"); |
2007 |
| z | Ore di fuso orario (1 cifra) | dt.ToString("%z"); |
+2 |
| zz | Ore di fuso orario (2 cifre) | dt.ToString("zz"); |
+02 |
| zzz | Ore e minuti di fuso orario | dt.ToString("zzz"); |
+02:00 |
| : | Separatore dell'ora | dt.ToString("%:"); |
. |
| / | Separatore della data | dt.ToString("%/"); |
/ |
| "ABC" (oppure 'ABC') | Valore letterale | dt.ToString("'d'"); |
d |
Si noti che nell'utilizzo dei caratteri di formato personalizzati costituiti da un solo carattere risulta necessario anteporre il carattere % per distinguerli dagli identificatori di formato standard (se disponibili come ad esempio per "d", "f", "F" o "g"; se al singolo carattere non corrisponde un formato standard e si omette il carattere "%" viene generata un'eccezione di tipo FormatException)
Combinando uno o più identificatori di formato personalizzati si può costruire uno schema di formattazione in grado di restituire l'output desiderato:
| Esempio | Output |
dt.ToString("'Ora corrente:' HH:mm:ss"); |
Ora corrente: 14.37.54 |
dt.ToString("dddd d MMMM yyyy - HH:mm:ss (z)"); |
mercoledì 25 aprile 2007 - 14.37.54 (+2) |
Formattazione di enumeratori
È possibile utilizzare il metodo ToString per creare un nuovo oggetto stringa che rappresenti il valore numerico, esadecimale o stringa di un Enum utilizzando le stringe di formattazione disponibili (vedi tabella seguente):
L'enumeratore di riferimento (Colors) utilizzato negli esempi seguenti è definito come:
public enum Colors
{
Default = 0,
White = 1,
Blue = 2,
Red = 3,
Black = 4
}
| Formato | Nome | Esempio | Output |
| G (o g) | Generale | Colors.Red.ToString("g"); |
Red |
|---|---|---|---|
Visualizza la voce di enumerazione sotto forma di valore di stringa, se possibile. In caso contrario, visualizza il valore integer dell'istanza corrente. Se l'enumerazione viene definita con l'attributo Flags impostato, i valori di stringa di ciascuna voce valida saranno concatenati tra loro, separati da virgole. Se l'attributo Flags non è impostato, un valore non valido verrà visualizzato sotto forma di voce numerica. |
|||
| F (o f) | Stringa | Colors.Red.ToString("f"); |
Red |
| D (o d) | Intero | Colors.Red.ToString("d"); |
3 |
| X (o x) | Esadecimale (8 cifre) | Colors.Red.ToString("x"); |
00000003 |