Previous lessons provided a sneak peek at some of the things that a C# program can do with strings. Lesson 11 explained how you can use a data type’s Parse
method to convert a string into a number and how to use the +
operator to concatenate two strings. Several lessons show how to use the ToString
method to convert numeric values into strings that you can then display to the user.
In this lesson, you learn a lot more about strings. You learn about string
class methods that let you search strings, replace parts of strings, and extract pieces of strings. You also learn new ways to format numeric and other kinds of data to produce strings.
The string
class provides a lot of useful methods for manipulating strings. For example, the EndsWith
method returns true
if a string ends with a particular substring. The following code determines whether a string ends with the substring dog
:
string str = "The quick brown fox jumps over the lazy dog";
MessageBox.Show("Ends with "dog.": " + str.EndsWith("dog"));
Table 14.1 summarizes the string
class’s most useful methods.
Method | Purpose |
Contains |
Returns true if the string contains a target string. |
EndsWith |
Returns true if the string ends with a target string. |
IndexOf |
Returns the index of a target character or string within the string. |
IndexOfAn y |
Returns the index of the first occurrence of any of a set of characters in the string. |
Insert |
Inserts text in the middle of the string. |
LastIndexOf |
Returns the index of the last occurrence of a target character or string within the string. |
LastIndexOfAny |
Returns the index of the last occurrence of any of a set of characters in the string. |
PadLeft |
Pads the string to a given length by adding characters on the left if necessary. |
PadRight |
Pads the string to a given length by adding characters on the right if necessary. |
Remove |
Removes a piece of the string. |
Replace |
Replaces occurrences of a string or character with new values within the string. |
Split |
Splits the string apart at a delimiter (for example, commas) and returns an array containing the pieces. |
StartsWith |
Returns true if the string starts with a target string. |
Substring |
Returns a substring. |
ToLower |
Returns the string converted to lowercase. |
ToUpper |
Returns the string converted to uppercase. |
Trim |
Removes leading and trailing characters from the string. The version that takes no parameters removes whitespace characters (space, tab, newline, and so on). |
TrimEnd |
Removes trailing characters from the string. |
TrimStart |
Removes leading characters from the string. |
In addition to all of these methods, the string
class provides a very useful Length
property. As you can probably guess, Length
returns the number of characters in the string
. (Previous lessons have used Length
to determine whether a string is empty.)
The string
class also provides the useful static (shared) methods Format
and Join
. A static method is one that is provided by the class itself rather than by an instance of the class. You invoke a static method using the class’s name instead of a variable’s name.
The Format
method formats a series of parameters according to a format string and returns a new string. For example, the following code uses the string
class’s Format
method to display the values in the variables x
and y
surrounded by parentheses and separated by a comma:
int x = 10, y = 20;
string txt = string.Format("({0}, {1})", x, y);
The following text shows the result:
(10, 20)
The next section says more about the Format
method.
The Join
method does the opposite of the Split
method: it joins a series of strings, separating them with a delimiter. Lesson 16 says more about arrays and provides some examples that use Split
and Join
.
The string
class’s Format
method builds a formatted string
. Its first parameter is a format string that tells how the method should display its other parameters. The format string can contain literal characters that are displayed as they appear. It can also contain formatting fields.
Each formatting field has the following syntax:
{index[,alignment][:formatString]}
The curly braces are required. The square brackets indicate optional pieces.
The key pieces of the field are:
index
—The zero-based index of the Format
method’s parameters that should be displayed by this field.alignment
—The minimum number of characters that the field should use. If this is negative, the field is left-justified.formatString
—The format string that indicates how the field’s value should be formatted. The following format sections describe some of the many values that you can use here in addition to literal characters.For example, the following code defines a string
and two decimal
values. It then uses Console.WriteLine
to display a string built by string.Format
in the Output window:
string itemName = "Fiendishly Difficult Puzzles";
decimal quantity = 2M;
decimal price_each = 9.99M;
Console.WriteLine(
string.Format("You just bought {1} {0} at {2:C} each.",
itemName, quantity, price_each));
The format string is "You just bought {1} {0} at {2:C} each."
The first field is {1}
. This displays parameter number 1 (the second parameter—remember they’re zero-based).
The second field is {0}
. This displays the first parameter.
The third field is {2:C}
. This displays the third parameter with the format string C
, which formats the value as currency.
The result is:
You just bought 2 Fiendishly Difficult Puzzles at $9.99 each.
The following code shows an example that uses field widths to make values line up in columns. Before the code executes, assume that itemName1
, quantity1
, and the other variables have already been initialized:
Console.WriteLine(
string.Format("{0,-20}{1,5}{2,10}{3,10}",
"Item", "Qty", "Each", "Total")
);
Console.WriteLine(
string.Format("{0,-20}{1,5}{2,10:C}{3,10:C}",
itemName1, quantity1, priceEach1, quantity1 * priceEach1)
);
Console.WriteLine(
string.Format("{0,-20}{1,5}{2,10:C}{3,10:C}",
itemName2, quantity2, priceEach2, quantity2 * priceEach2)
);
Console.WriteLine(
string.Format("{0,-20}{1,5}{2,10:C}{3,10:C}",
itemName3, quantity3, priceEach3, quantity3 * priceEach3)
);
Notice that the code begins with a line that defines the column headers. Its formatting string uses the same indexes and alignment values as the other formatting strings so the headers line up with the values below.
The following text shows the result:
Item Qty Each Total
Pretzels (dozen) 4 $5.95 $23.80
Blue laser pointer 1 $149.99 $149.99
Titanium spork 2 $8.99 $17.98
Every object provides a ToString
method that converts the object into a string. For simple data types such as numbers and dates, the result is the value in an easy-to-read string.
The ToString
method for some objects can take a format parameter that tells how you want the item formatted. For example, the following statement displays the variable cost
formatted as a currency value in the Output window:
Console.WriteLine(cost.ToString("C"));
The following sections describe standard and custom format strings for numbers, dates, and times. You can use these as arguments to the ToString
method or as the formatString
part of the string.Format
method’s format strings.
Formatting characters tell string.Format
and ToString
how to format a value. For the characters discussed in this section, you can use either an uppercase or a lowercase letter. For example, you can use C
or c
for the currency format.
Table 14.2 summarizes the standard numeric formatting characters.
CHARACTER | MEANING | EXAMPLE |
C |
Currency with a currency symbol, thousands separators, and a decimal point. | $12,345.67 |
D |
Decimal. Integer types only. | 12345 |
E |
Scientific notation. | 1.234567E+004 |
F |
Fixed-point. | 12345.670 |
G |
General. Either fixed-point or scientific notation, whichever is shorter. | 12345.67 |
N |
Similar to currency except without the currency symbol. | 12,345.67 |
P |
Percent. The number is multiplied by 100 and a percent sign is added appropriately for the computer’s locale. Includes thousands separators and a decimal point. | 123.45 % |
R |
Round trip. The number (double or float only) is formatted in a way that guarantees it can be parsed back into its original value. | 1234.567 |
X |
Hexadecimal. | 3A7 |
You can follow several of these characters with a precision specifier that affects how the value is formatted. How this value works depends on the format character that it follows.
For the D
and X
formats, the result is padded on the left with zeros to have the length given by the precision specifier. For example, the statement 123.ToString("D10")
produces the result 0000000123
. (Yes, C# is smart enough to let you call the ToString
method for the integer 123
.)
For the C
, E
, F
, N
, and P
formats, the precision specifier indicates the number of digits after the decimal point. For example, the statement 1.23.ToString("N5")
produces the result 1.23000
. (Yes, C# can handle this one, too.)
If the standard numeric formatting characters don’t do what you want, you can use a custom numeric format. Table 14.3 summarizes the custom numeric formatting characters.
CHARACTER | MEANING |
0 |
Digit or zero. A digit is displayed here or a zero if there is no corresponding digit in the value being formatted. |
# |
Digit or nothing. A digit is displayed here or nothing if there is no corresponding digit in the value being formatted. |
. |
Decimal separator. The decimal separator goes here. Note that the actual separator character may not be a period depending on the computer’s locale, although you still use the period in the format string. |
, |
Thousands separator. The thousands separator goes here. The actual separator character may not be a comma depending on the computer’s locale, although you still use the comma in the format string. |
% |
Percent. The number is multiplied by 100 and the percent sign is added at this point. For example, %0 puts the percent sign before the number and 0% puts it after. |
E+0 |
Scientific notation. The number of 0s indicates the number of digits in the exponent. If + is included, the exponent always includes a + or – sign. If + is omitted, the exponent only includes a sign if the exponent is negative. For example, the statement 1234.56.ToString("#.##E+000") produces the result 1.23E+003 . |
|
Escape character. Whatever follows the is displayed without any conversion. For example, the format 0.00\% would add a percent sign to a number without scaling it by 100 as the format 0.00% does. Note that you must escape the escape character itself in a normal (non-verbatim) string. For example, a format string might look like {0:0.00\%} in the code. |
'ABC' |
Literal string. Characters enclosed in single or double quotes are displayed without any conversion. |
; |
Section separator. See the following text. |
You can use a section separator to divide a formatting string into two or three sections. If you use two sections, the first applies to values greater than or equal to zero, and the second section applies to values less than zero. If you use three sections, they apply to values that are greater than, less than, and equal to zero.
For example, Table 14.4 shows the result produced by the three-section custom formatting string "{0:$#,##0.00;($#,##0.00);— zero —}"
for different values.
VALUE | FORMATTED RESULT |
12345.678 |
$12,345.68 |
-12345.678 |
($12,345.68) |
0.000 |
— zero — |
Just as numeric values have standard and custom formatting strings, so too do dates and times.
Table 14.5 summarizes the standard date and time formatting patterns. The examples are those produced for 1:23:45.678 PM April 5, 2063 on my computer set up for US English. Your results will depend on your computer’s locale. Note that for many of the characters in this table, the uppercase and lowercase versions have different meanings.
CHARACTER | MEANING | EXAMPLE |
d |
Short date | 4/5/2063 |
D |
Long date | Thursday, April 5, 2063 |
f |
Full date, short time | Thursday, April 5, 2063 1:23 PM |
F |
Full date, long time | Thursday, April 5, 2063 1:23:45 PM |
g |
General date/time, short time | 4/5/2063 1:23 PM |
G |
General date/time, long time | 4/5/2063 1:23:45 PM |
M or m |
Month day | April 5 |
O |
Round trip | 2063-04-05T13:23:45.6780000 |
R or r |
RFC1123 | Thu, 05 Apr 2063 13:23:45 GMT |
s |
Sortable date/time | 2063-04-05T13:23:45 |
t |
Short time | 1:23 PM |
T |
Long time | 1:23:45 PM |
u |
Universal sortable short date/time | 2063-04-05 13:23:45Z |
U |
Universal sortable full date/time | Thursday, April 5, 2063 7:23:45 PM |
Y or y |
Year month | April, 2063 |
The DateTime
class also provides several methods that return the date’s value as a string formatted in the most common date and time formats. Table 14.6 summarizes the most useful of these methods and shows the results on my computer set up for US English. Your results will depend on how your computer is configured.
METHOD | FORMAT | EXAMPLE |
ToLongDateString |
Long date (D ) |
Thursday, April 5, 2063 |
ToLongTimeString |
Long time (T ) |
1:23:45 PM |
ToShortDateString |
Short date (d ) |
4/5/2063 |
ToShortTimeString |
Short time (t ) |
1:23 PM |
ToString |
General date and time (G ) |
4/5/2063 1:23:45 PM |
If the standard date and time formatting characters don’t do the trick, you can use a custom format. Table 14.7 summarizes the custom date and time formatting strings. Note that for many of the characters in this table, the uppercase and lowercase versions have different meanings.
CHARACTER | MEANING |
d |
Day of month between 1 and 31. |
dd |
Day of month between 01 and 31. |
ddd |
Abbreviated day of week (Mon, Tue, and so on). |
dddd |
Full day of week (Monday, Tuesday, and so on). |
f |
Digits after the decimal for seconds. For example, ffff means use four digits. |
F |
Similar to f but trailing zeros are not displayed. |
g |
Era specifier. For example, A.D. |
h |
Hours between 1 and 12. |
hh |
Hours between 01 and 12. |
H |
Hours between 0 and 23. |
HH |
Hours between 00 and 23. |
m |
Minutes between 1 and 59. |
mm |
Minutes between 01 and 59. |
M |
Month between 1 and 12. |
MM |
Month between 01 and 12. |
MMM |
Month abbreviation (Jan, Feb, and so on). |
MMMM |
Month name (January, February, and so on). |
s |
Seconds between 1 and 59. |
ss |
Seconds between 01 and 59. |
t |
First character of AM/PM designator. |
tt |
AM/PM designator. |
y |
One- or two-digit year. If the year has fewer than two digits, is it not zero padded. |
yy |
Two-digit year, zero padded if necessary. |
yyy |
Three-digit year, zero padded if necessary. |
yyyy |
Four-digit year, zero padded if necessary. |
yyyyy |
Five-digit year, zero padded if necessary. |
z |
Signed time zone offset from UTC. |
zz |
Signed time zone offset from UTC in two digits. |
zzz |
Signed time zone offset from UTC in hours and minutes. |
: |
Hours, minutes, and seconds separator. |
/ |
Date separator. |
'ABC' |
Literal string. Characters enclosed in single or double quotes are displayed without any conversion. |
Table 14.8 shows some example formats and their results. The date used was 1:23:45.678 PM April 5, 2063 on my computer set up for US English. Your results will depend on how your computer is configured.
FORMAT | RESULT |
M/d/yy |
4/5/63 |
d MMM yy |
5 Apr 63 |
HH:mm 'hours' |
13:23 hours |
h:mm:ss.ff, M/d/y |
1:23:45.67, 4/5/63 |
dddd 'at' h:mmt |
Thursday at 1:23P |
ddd 'at' h:mmtt |
Thu at 1:23PM |
In this Try It, you build a program that displays the current date and time in a Label
when it starts as shown in Figure 14.1.
In this lesson, you:
Label
to its form.Load
event handler that sets the Label
’s text as shown in Figure 14.1.DateTime.Now
property returns the current date and time.string.Format
or the value’s ToString
method to format the result.Label
to its form.
Label
.Label
’s AutoSize
property to False
and set its font size to 12. Then position and anchor or dock it on the form.Label
’s TextAlign
property to MiddleCenter
.Load
event handler that sets the Label
’s text as shown in Figure 14.1.
// Display the current date and time.
private void Form1_Load(object sender, EventArgs e)
{
greetingLabel.Text = DateTime.Now.ToString(
"'It is' h:mmtt 'on' ddd, MMM dd yyyy");
}
Copy the corrected version of that program (or download it from the book’s website) and modify it so quantities are displayed with thousands separators.
Timer
control with Enabled
set to True
, and Interval
set to 1000
. Update a Label
’s Text
property in the Timer
’s Tick
event.1200/Gummy slugs/.02/24
Use string
methods to split the string apart, parse the numeric values, and then display a result similar to the following:
1,200 Gummy slugs @ $0.02 each = $24.00
Remember to allow the input to contain formatted values such as $24.00. Hint: Use string.Split
, which returns an array of values. We’ll talk more about arrays in Lesson 16. For now, just use brackets and an index to get one of the values. For example, the following statement saves the first field in a string:
string quantityString = text.Split('/')[0];
1,200 Gummy slugs @ $0.02 each = $24.00
Use the string
methods IndexOf
, LastIndexOf
, Substring
, and Trim
to parse the string into item name, quantity, price each, and total price pieces. Convert the numbers into numeric data types and display the results in TextBox
es. Hints:
IndexOf
to find the position of the first space (which comes after the quantity).LastIndexOf
to find the delimiters “@,” “each,” and “=” in case the item’s name contains those strings.Substring
to get the pieces. Trim the name and parse the numeric values.ListBox
instead of a ListView
. Make the program use string.Format
to add items to the ListBox
in a format similar to the following:
1,200 Gummy slugs at $0.02 each = $24.00
Hint: When you remove an item from the list, you need to subtract its total cost from the grand total. Use the item’s ToString
method to convert it into a string. Then use the methods you used for Exercise 5 to parse the string and find the item’s total cost.
-
.TextBox
as the original string so the user can make several replacements easily. To make using the program even easier, also make the button clear the string to replace and the replacement string and set focus to the string to replace.