One of the painful things about good old ASP was string formatting, VBScript
simply didn't have anything useful. C# (and VB.Net) do, but MSDN doesn't provide
a quick reference to the formatting options. So here's a quick reference.
To compare string formatting in C# to those in C lets have an example,
char szOutput[256];
sprintf(szOutput, "At loop position %d.\n", i);
sprintf takes an output buffer, a format string and any number of arguments to
substitute into the format string.
The C# equivalent for sprintf is String.Format, which takes a format string and
the arguments. It returns a string, and because you're not passing in a buffer
there's no chance of a buffer overflow.
string outputString = String.Format("At loop position {0}.\n", i);
So why doesn't have the format argument have parameters specifying what data
type you're formatting? The CLR objects have metadata which informs the CLR what
the objects are, and each object has a standard ToString() method which returns
a string representation of that object. Much nicer than C where if you passed
the wrong type of variable into sprintf everything could come crashing down.
The ToString method can accept a string parameter which tells the object how to
format itself. In the call to String.Format , the formatting string is passed
after the position, for example, "{0:##}". The text inside the curly braces is
{argumentIndex[,alignment][:formatString]}. If alignment is positive, the text
is right-padding to fill the specified field length, if it's negative, it's
left-padded.
formatting strings
There's not much formatting that can be applied to a string. Only the padding /alignment formatting options can be applied. These options are also available to
every argument, regardless of type.
example | output |
---|---|
String.Format("--{0,10}--", "test"); | -- test-- |
String.Format("--{0,-10}--", "test"); | --test -- |
formatting numbers
Number formatting is culture dependant. For
example, formatting a currency string on my laptop will return a result like
£9.99, formatting a currency on a machine set for the US region would return
$9.99.
specifier | type | format | output (double 1.2345) | output (int -12345) |
---|---|---|---|---|
c | currency | {0:c} | £1.23 | -£12,345.00 |
d | decimal (whole number) | {0:d} | System.FormatException | -12345 |
e | exponent / scientific | {0:e} | 1.234500e+000 | -1.234500e+004 |
f | fixed point | {0:f} | 1.23 | -12345.00 |
g | general | {0:g} | 1.2345 | -12345 |
n | number | {0:n} | 1.23 | -12,345.00 |
r | round trippable | {0:r} | 1.23 | System.FormatException |
x | hexadecimal | {0:x4} | System.FormatException | ffffcfc7 |
custom number formatting
specifier | type | format | output (double 1234.56) |
---|---|---|---|
0 | zero placeholder | {0:00.000} | 1234.560 |
# | digit placeholder | {0:#.##} | 1234.56 |
. | decimal point placeholder | {0:0.0} | 1234.6 |
, | thousand separator | {0:0,0} | 1,235 |
% | percentage | {0:0%} | 123456% |
In addition there is the group separator; this is useful for varying the format,
depending on the value of the parameter passed. For example
String.Format("{0:£#,##0.00;(£#,##0.00);Nothing}", value);
This will output "£1,240.00" if passed 1243.56. It will output the same
format bracketed if the value is negative "(£1,240.00)", and will output the
string "Nothing" if the number is zero.
date formatting
Date formats are very dependant on the culture
information passed. The examples below are shown using the UK culture.
specifier | type | output (June 8, 1970 12:30:59) |
---|---|---|
d | Short Date | 08/06/1970 |
D | Long Date | 08 June 1970 |
t | Short Time | 12:30 |
T | Long Time | 12:30:59 |
f | Full date and time | 08 June 1970 12:30 |
F | Full date and time (long) | 08 June 1970 12:30:59 |
g | Default date and time | 08/06/1970 12:30 |
G | Default date and time (long) | 08/06/1970 12:30:59 |
M | Day / Month | 8 June |
r | RFC1123 date string | Mon, 08 Jun 1970 12:30:59 GMT |
s | Sortable date/time | 1970-06-08T12:30:59 |
u | Universal time, local timezone | 1970-06-08 12:30:59Z |
Y | Month / Year | June 1970 |
custom date formatting
specifier | type | output (June 8, 1970 12:30:59) |
---|---|---|
dd | Day | 08 |
ddd | Short Day Name | Mon |
dddd | Full Day Name | Monday |
hh | 2 digit hour | 12 |
HH | 2 digit hour (24 hour) | 12 |
mm | 2 digit minute | 30 |
MM | Month | 06 |
MMM | Short Month name | Jun |
MMMM | Month name | June |
ss | seconds | 59 |
tt | AM/PM | PM |
yy | 2 digit year | 70 |
yyyy | 4 digit year | 1970 |
: | seperator, e.g. {0:hh:mm:ss} | 12:30:59 |
/ | seperator, e.g. {0:dd/MM/yyyy} | 08/06/1970 |
There are others, including time zone formatting and so on, but the ones above
are the most commonly used.
culture information
string.format also provides a method which accepts a
CultureInfo argument, as an IFormatProvider. This is important when trying
to write portable and localisable code, as, for example, month names will change
according to the local culture of the machine you are running on. Rather than
simply call the standard String.Format you should consider always calling the
overloaded culture method. If you don't need to specify a culture you can use
the System.Globalization.CultureInfo.InvariantCulture. This will then default
your formatting to English, as opposed to the culture of the current thread.
No comments:
Post a Comment
Suggestions are invited from readers