Working with Strings - Variables and Calculations - C# 24-Hour Trainer (2015)

C# 24-Hour Trainer (2015)

Section II

Variables and Calculations

Lesson 14

Working with Strings

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.

String Methods

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.

Table 14.1

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.

NOTE

Remember that string indexing starts with 0 so the first letter has index 0, the second has index 1, and so forth.

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.

Format and ToString

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

NOTE

Because the format string is just a string, you could define it in a constant or variable and then use that variable as the first argument to the Format method. That way you are certain that all of the Format statements use the same string. This also makes it easier to change the format later if necessary.

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.

Standard Numeric Formats

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.

Table 14.2

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

NOTE

In programming, a computer’s locale defines the computer’s country, language, and formats such as how numbers and currency values should be formatted. For example, the value $1,234.56 in the United States would be written as 1 234,56 € in France and as 1.234,56 € in Germany.

Locale codes consist of a language code with an optional country code. For example, en represents English and en-GB represents English as spoken in Great Britain. The capitalization doesn’t matter but people often write the country code in all caps. For a list of locale codes, see msdn.microsoft.com/library/ee825488(v=cs.20).aspx.

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.)

NOTE

In general, you should use the standard format specifiers whenever possible so the result makes sense for the computer’s locale. For example, suppose you use the following code to display a monetary amount:

decimal garageSaleProceeds = 1234.56m;

MessageBox.Show(string.Format("${0:N}", garageSaleProceeds));

If the user’s computer is localized for the United States, then the program displays $1,234.56, which is correct. Unfortunately if the user’s computer is German, the program displays $1.234,56, which isn’t right in either the United States or Germany.

The following statement uses the standard currency formatting specifier:

MessageBox.Show(string.Format("{0:C}", garageSaleProceeds));

In the United States, the computer produces $1,234.56 as before. In Germany, it produces 1.234,56 €, which is what the user expects.

If you use standard format specifiers as much as possible, the computer will use its localization settings to display numbers, dates, and times in the appropriate formats.

Custom Numeric Formats

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.

Table 14.3

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 statement1234.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.

Table 14.4

VALUE

FORMATTED RESULT

12345.678

$12,345.68

-12345.678

($12,345.68)

0.000

— zero —

Standard Date and Time Formats

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.

Table 14.5

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

NOTE

The result given by the U format may seem a bit surprising because it gives the time as 7:23:45 PM instead of 1:23:45 PM. The reason is the U specifier automatically converts a local time into Coordinated Universal Time (UTC) before formatting. (UTC is the time at 0° longitude. It’s basically the same as Greenwich Mean Time or GMT.) On April 5, 2063, the time 1:23 PM in my time zone will be 7:23 PM in Greenwich.

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.

Table 14.6

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

NOTE

As is the case with number formats, you should use the standard specifiers or the standard methods (such as ToLongDateString)whenever possible so your computer can display dates and times in the formats used by the computer’s locale.

Custom Date and Time Formats

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.

Table 14.7

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.

NOTE

The time zone offset values depend on whether daylight savings is in effect. For example, for Pacific Standard Time the zzz specifier returns either –08:00 or –07:00 depending on whether daylight savings is in effect on that date.

NOTE

The date and time formatting methods assume that a single character is a standard format. For example, the date.ToString("d") would give you a short date format, not the day of the month.

When a single character specifier is inside a longer string, the formatting methods treat it like a custom specifier. For example, date.ToString("M/d") gets you the month and day numbers.

If you need to use a customer specifier alone, place a % symbol in front of it. For example, date.ToString("%d") returns the day number by itself.

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.

Table 14.8

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

Try It

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.

Screenshot of Current Date and Time window displaying the words “It is 1:37PM on Thu, Apr 05,2063.”

Figure 14.1

Lesson Requirements

In this lesson, you:

· Start a new project and add a Label to its form.

· Give the form a Load event handler that sets the Label’s text as shown in Figure 14.1.

NOTE

You can download the code and resources for this lesson from the website at www.wrox.com/go/csharp24hourtrainer2e.

Hints

· The DateTime.Now property returns the current date and time.

· Either use string.Format or the value’s ToString method to format the result.

Step-by-Step

· Start a new project and add a Label to its form.

1. Create the new project and its Label.

2. Set the Label’s AutoSize property to False and set its font size to 12. Then position and anchor or dock it on the form.

3. Set the Label’s TextAlign property to MiddleCenter.

· Give the form a Load event handler that sets the Label’s text as shown in Figure 14.1.

1. Use code similar to the following:

// 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");

}

Exercises

1. Exercise 13-3 reads and displays currency values, but it displays quantities without thousands separators. If you ordered 1,200 pencils, the program would display 1200.

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.

2. Make a program that displays the time every second. Hint: Use a Timer control with Enabled set to True, and Interval set to 1000. Update a Label’s Text property in the Timer’s Tick event.

3. Write a program that lets the user enter an integer value. When the user clicks the Format button, parse the value and use a standard format specifier to redisplay it with thousands separators but no digits after the decimal point.

4. Write a program that lets the user enter text in the following format:

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];

5. [Hard] Write a program that lets the user enter text in the following format:

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 TextBoxes. Hints:

· Use IndexOf to find the position of the first space (which comes after the quantity).

· Use LastIndexOf to find the delimiters “@,” “each,” and “=” in case the item’s name contains those strings.

· Calculate the length of the pieces of text between the delimiters. For example, the length of the name is [@ location] – [first space location] – 1.

· Use Substring to get the pieces. Trim the name and parse the numeric values.

6. [Hard] Copy the program that you built for Exercise 1 and modify it so the main form displays items in a 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.

7. Make a program that replaces all occurrences of the letter E (uppercase and lowercase) in a string entered by the user with the character -.

8. Make a program that lets the user enter an input string, a string to replace, and a replacement string. When the user clicks the Replace button, make the replacement and display the result in the same 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.

9. Write a program that lets the user enter a string such as, “The 6th sheik’s 6th sheep’s sick.” When the user clicks the Replace button, replace numerals with their spelled out equivalents as in, “The sixth sheik’s sixth sheep’s sick.” Don’t worry about punctuation (like capitalizing if the sentence begins with a numeral), numbers bigger than 9 (so “10” will become “onezero”), or special cases (like converting 3rd into third). (Then try to say “The sixth sheik’s sixth sheep’s sick” as quickly as you can.)

10.Write a program that lets the user enter a number. When the user clicks the Format button, use a customer format specifier with three sections to format the number. If the number is positive, display it as in +1,234.56 (two digits after the decimal point). If the number is negative, display it as in –1,234.56 (again two digits after the decimal point). If the number is zero, display ZERO.

NOTE

Please select the videos for Lesson 14 online at www.wrox.com/go/csharp24hourtrainer2evideos.