The .NET Framework Overview: Object Formatting

1. Numeric Formatting

You format numeric types through the Format() member function of that data type. You can call this directly through String.Format(), which calls the Format () function of each data type, or through Console.WriteLine(), which calls String.Format().

The “Custom Object Formatting” section later in this chapter covers how to add formatting to a user-defined object. The following sections discuss how you do formatting with the built-in types.

You have two methods of specifying numeric formatting. You can use a standard format string to convert a numeric type to a specific string representation. If you need further control over the output, you can use a custom format string.

1.1. Standard Format Strings

A standard format string consists of a character that specifies the format, followed by a sequence of digits that specifies the precision. The formats listed in Table 34-1 are supported.

Currency

The currency format string converts the numerical value to a string containing a locale-specific currency amount. By default, the current locale determines the format information, but you can change this by passing a NumberFormatInfo object. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:C}”, 33345.8977);

Console.WriteLine(“{0:C}”, -33345.8977);

}

}

gives the following output:

$33,345.90

($33,345.90)

An integer following the c specifies the number of decimal places to use; two places are used if the integer is omitted.

Decimal

The decimal format string converts the numerical value to an integer. The precision specifier determines the minimum number of digits. The result is left-padded with zeroes to obtain the required number of digits. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:D}”, 33345);

Console.WriteLine(“{0:D7}”, 33345);

}

}

gives the following output:

33345

0033345

Scientific (Exponential)

The scientific (exponential) format string converts the value to a string in the following form:

m.dddE+xxx

One digit always precedes the decimal point, and you specify the number of decimal places with the precision specifier, with six places used as the default. The format specifier controls whether E or e appears in the output. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:E}”, 33345.8977);

Console.WriteLine(“{0:E10}”, 33345.8977);

Console.WriteLine(“{0:e4}”, 33345.8977);

}

}

gives the following output:

3.334590E+004

3.3345897700E+004

3.3346e+004

Fixed-Point

The fixed-point format string converts the value to a string, with the number of places after the decimal point specified by the precision specifier. Use two places if the precision specifier is omitted. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:F}”, 33345.8977);

Console.WriteLine(“{0:F0}”, 33345.8977);

Console.WriteLine(“{0:F5}”, 33345.8977);

}

}

gives the following output:

33345.90

33346

33345.89770

General

The general format string converts the value to either a fixed-point format or a scientific format, whichever one gives a more compact format. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:G}”, 33345.8977);

Console.WriteLine(“{0:G7}”, 33345.8977);

Console.WriteLine(“{0:G4}”, 33345.8977);

}

}

gives the following output:

33345.8977

33345.9

3.335E4

Number

The number format string converts the value to a number that has embedded commas:

12,345.11

By default, the number is formatted with two digits to the right of the decimal point. You can control this by specifying the number of digits after the format specifier. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:N}”, 33345.8977);

Console.WriteLine(“{0:N4}”, 33345.8977);

}

}

gives the following output:

33,345.90

33,345.8977

It’s possible to control the character used for the decimal point by passing a NumberFormatInfo object to the Format() function.

Round-Trip

Using the round-trip format ensures that a value represented as a string can be parsed back into the same value. This is especially useful for floating-point types, where extra digits are sometimes required to read a number back in with the identical value.

Hexadecimal

The hexadecimal format string converts the value to hexadecimal format. You set the minimum number of digits with the precision specifier; the number will be zero-padded to that width.

Using X will result in uppercase letters in the converted value; x will result in lowercase letters. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:X}”, 255);

Console.WriteLine(“{0:x8}”, 1456);

}

}

gives the following output:

FF

000005b0

NumberFormatInfo

The NumberFormatInfo class controls the formatting of numbers. By setting the properties in this class, you can control the currency symbol, decimal separator, and other formatting properties.

1.2. Custom Format Strings

You can use custom format strings to obtain more control over the conversion than is available through the standard format strings. In custom format strings, special characters form a template into which the number is formatted. Any characters that don’t have a special meaning in the format string are copied verbatim to the output. Table 34-2 describes the custom strings available.

Digit or Zero Placeholder

You can use the zero (0) character as a digit or as a zero placeholder. If the numeric value has a digit in the position at which the 0 appears in the format string, the digit will appear in the result. If not, a zero appears in that position. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:000}”, 55);

Console.WriteLine(“{0:000}”, 1456);

}

}

gives the following output:

055

1456

Digit or Space Placeholder

You can use the pound (#) character as the digit or space placeholder. It works the same as the 0 placeholder, except that the character is omitted if there’s no digit in that position. This example:

using System;

class Test {

public static void Main()

{

Console.WriteLine(“{0:#####}”, 255);

Console.WriteLine(“{0:#####}”, 1456);

Console.WriteLine(“{0:###}”, 32767);

}

}

gives the following output:

255

1456

32767

Decimal Point

The first period (.) character that appears in the format string determines the location of the decimal separator in the result. A NumberFormatInfo instance controls the character used as the decimal separator in the formatted string. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:#####.000}”, 75928.3);

Console.WriteLine(“{0:##.000}”, 1456.456456);

}

}

gives the following output:

75928.300

1456.456

Group Separator

You can use the comma (, ) character as a group separator. If a comma appears in the middle of a display digit placeholder and to the left of the decimal point (if present), a group separator will be inserted in the string. A NumberFormatInfo instance controls the character used in the formatted string and the number of numbers to group. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:##,###}”, 2555634323);

Console.WriteLine(“{0:##,000.000}”, 14563553.593993);

Console.WriteLine(“{0:#,#.000}”, 14563553.593993);

}

}

gives the following output:

2,555,634,323

14.563.553.594

14.563.553.594

Number Prescaler

You can also use the comma (,) character to indicate that the number should be prescaled. In this usage, the comma must come directly before the decimal point or at the end of the format string.

For each comma present in this location, the number is divided by 1,000 before it’s formatted. This example:

using System;

class Test {

public static void Main()

{

Console.WriteLine(“{0:000,.##}”, 158847);

Console.WriteLine(“{0:000,,,.###}”, 1593833);

}

}

gives the following output:

158.85

000.002

Percent Notation

You can use the percent (%) character to indicate that the number to be displayed should be displayed as a percentage. The number is multiplied by 100 before it’s formatted. This example:

using System;

class Test {

public static void Main()

{

Console.WriteLine(“{0:##.000%}”, 0.89144);

Console.WriteLine(“{0:00%}”, 0.01285);

}

}

gives the following output:

89.144%

01%

Exponential Notation

When E+0, E-0, e+0, or e-0 appear in the format string directly after a # or 0 placeholder, the number will be formatted in exponential notation. The number of digits in the exponent is controlled by the number of 0 placeholders that appear in the exponent specifier. The E or e is copied directly into the formatted string, and a plus (+) sign means there will be a plus or minus sign in that position, while a minus (-) sign means there’s a character there only if the number is negative. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:###.000E-00}”, 3.1415533E+04);

Console.WriteLine(“{0:#.0000000E+000}”, 2.553939939E+101);

}

}

gives the following output:

314.155E-02

2.5539399E+101

Section Separator

You can use the semicolon (;) character to specify different format strings for a number, depending on whether the number is positive, negative, or zero. If there are only two sections, the first section applies to positive and zero values and the second applies to negative values. If there are three sections, they apply to positive values, negative values, and the zero value. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:###.00;0;(###.00)}”, -456.55);

Console.WriteLine(“{0:###.00;0;(###.00)}”, 0);

Console.WriteLine(“{0:###.00;0;(###.00)}”, 456.55);

}

}

gives the following output:

457

(.00)

456.55

Escapes and Literals

You can use the backslash (\) character to escape characters so they aren’t interpreted as formatting characters. Because the backslash already has meaning within C# literals, it will be easier to specify the string using the verbatim literal syntax; otherwise, a double backslash (\\) is required to generate a single slash in the output string.

You can specify a string of uninterpreted characters by enclosing them in single quotes; this may be more convenient than using the backslash character. This example:

using System; class Test {

public static void Main()

{

Console.WriteLine(“{0:###\\#}”, 255);

Console.WriteLine(@”{0:###\#}”, 255);

Console.WriteLine(“{0:###’#0%;’}”, 1456);

}

}

gives the following output:

255#

255#

1456#0%;

1.3. Numeric Parsing

If there’s a reasonable chance that the input string contains invalid characters, which means that Parse will be unable to convert to the appropriate type and throw an exception, you should use the TryParse method instead. Rather than throwing an exception if the input can’t be successfully converted, TryParse instead returns a Boolean that indicates the success of the conversion, with the result of the conversion returned as an out parameter:

Console.WriteLine(“Please enter an integer and press Enter”);

int numberEntered;

while(!int.TryParse(Console.ReadLine(), out numberEntered))

{

Console.WriteLine(“Please try again”);

}

Console.WriteLine(“You entered ” + numberEntered.ToString());

In the .NET Framework versions 1.0 and 1.1, double was the only type that had a TryParse method. For 2.0, the number of types that offer a TryParse method has been expanded and now includes all numeric types, char, DateTime, and TimeSpan.

2. Date and Time Formatting

The DateT ime class provides flexible formatting options. You can specify several single-character formats; the class also supports custom formatting. Table 34-3 indicates the standard DateTime formats.

2.1. Custom DateTime Format

You can use the patterns listed in Table 34-4 to build a custom format.

The day and month names are determined by the appropriate field in the DateTimeFormatInfo class.

3. Custom Object Formatting

Earlier examples have overridden the ToString() function to provide a string representation of a function. An object can supply different formats by defining the IFormattable interface and then changing the representation based upon the string of the function.

For example, an Employee class could add information with a different format string.

This example:

using System;

class Employee: IFormattable {

public Employee(int id, string firstName, string lastName)

{

this.id = id;

this.firstName = firstName;

this.lastName = lastName;

}

public string ToString (string format, IFormatProvider fp)

{

if ((format != null) && (format.Equals(“F”)))

return(String.Format(“{0}: {1}, {2}”,

id, lastName, firstName));

else

return(id.ToString(format, fp));

}

int id;

string          firstName;

string          lastName;

}

class Test {

public static void Main()

{

Employee fred = new Employee(123, “Fred”, “Morthwaite”);

Console.WriteLine(“No format: {0}”, fred);

Console.WriteLine(“Full format: {0:F}”, fred);

}

}

produces the following output:

No format: 123

Full format: 123: Morthwaite, Fred

The Format() function looks for the F format. If it finds it, it writes the full information. If it doesn’t find it, it uses the default format for the object.

The Main() function passes the format flag in the second WriteLine() call.

4. Numeric Parsing

Numbers are parsed using the Parse() method provided by the numeric data types. You can pass flags from the NumberStyles class to specify which styles are allowed, and you can pass a NumberFormatInfo instance to control parsing.

A numeric string produced by any of the standard format specifiers (excluding hexadecimal) is guaranteed to be correctly parsed if the NumberStyles.Any style is specified. This example:

using System; class Test {

public static void Main()

{

int value = Int32.Parse(“99953”);

double dval = Double.Parse(“1.3433E+35”);

Console.WriteLine(“{0}”, value);

Console.WriteLine(“{0}”, dval);

}

}

produces the following output.

Source: Gunnerson Eric, Wienholt Nick (2005), A Programmer’s Introduction to C# 2.0, Apress; 3rd edition.

Leave a Reply

Your email address will not be published. Required fields are marked *