Characters and strings are very important data types in practical programming. VB.NET provides a String type in the System namespace. As a class, String is a reference type. The VB.NET compiler provides additional support to make working with strings more concise and intuitive. In this section we will first look at characters and then outline the main features of the String class. We will look at string input, at the additional support provided by VB.NET, and at the issues of string equality. The section that follows surveys some of the useful methods of the String class. The section after that discusses the StringBuilder class. Characters VB.NET provides the primitive data type Char to represent individual characters. A character literal is represented by a character enclosed in double quotes followed by the suffix C. Dim ch1 As Char = "a"C A VB.NET Char is represented internally as an unsigned two-byte integer. You can cast back and forth between Char and integer data types. Dim ch1 As Char = "a"C ' ch1 is now 'a' Dim n As Integer = AscW(ch1) n += 1 ch1 = ChrW(n) ' ch1 is now 'b' The relational operators = , < , > , and so on apply to char . Dim ch1 As Char = "a"C Dim ch2 As Char = "b"C If ch1 < ch2 Then ' expression is True ... End If If ch1 >= ch2 Then ' expression is False ... End If ASCII and Unicode Traditionally, a one-byte character code called ASCII has been used to represent characters. ASCII code is simple and compact. But ASCII cannot be employed to represent many different alphabets used throughout the world. Modern computer systems usually use a two-byte character code called Unicode. Most modern (and several ancient) alphabets can be represented by Unicode characters. ASCII is a subset of Unicode, corresponding to the first 255 Unicode character codes. For more information on Unicode, you can visit the Web site www.unicode.org. VB.NET uses Unicode to represent characters and strings. Special Characters You can represent any Unicode character in a VB.NET program by using the CChar type conversion. You may use hexadecimal digits if it is convenient . Dim ch1 As Char = ChrW(&H41) ' 41 (hex) is 65 (dec) or 'A' A number of nonprinting characters can be handled, as well as characters like quotation marks that would be difficult to represent otherwise . A double-quote character can be represented as two double-quote characters within a literal string. For example, the code Console.WriteLine("""Hello""") will result in the output "Hello" Other difficult characters can be represented using their Unicode values. Table 4-1 shows the values for several such characters. For example, the following code will display the words "Hello" and "World" on separate output lines, since &HA represents the line feed character. Dim str As String = "Hello" + ChrW(&HA) + "World" Console.WriteLine(str) There are also a number of Visual Basic constants of the form vbXxxx that you can use. For example, you can use vbLf as an alternative in the previous example. Dim str As String = "Hello" + vbLf + "World" These constants are in the Microsoft.VisualBasic namespace, which is discussed later in this chapter. This namespace is added by default to projects created in Visual Studio. Table 4-1. Some Character Code Values Name | Value | Visual Basic Constant | Single quote | &H27 | | Double quote | &H22 | | Backslash | &H5C | | Null | &H0 | vbNullChar | Alert | &H7 | | Backspace | &H8 | vbBack | Form feed | &HC | vbFormFeed | Line feed | &HA | vbLf | Carriage return | &HD | vbCr | New Line | &HD + &HA | VbLfCr or VbNewLine | Horizontal tab | &H9 | vbTab | Vertical tab | &HB | vbVerticalTab | String Class The String class inherits directly from Object and is a NotInheritable class, which means that you cannot further inherit from String . We will discuss inheritance and NotInheritable classes in Chapter 5. When a class is NotInheritable , the compiler can perform certain optimizations to make methods in the class more efficient. Instances of String are immutable , which means that once a string object is created, it cannot be changed during its lifetime. Operations that appear to modify a string actually return a new string object. If, for the sake of efficiency, you need to modify a string-like object directly, you can make use of the StringBuilder class, which we will discuss in a later section. A string has a zero-based index accessed via its Chars indexed property, which can be used to access individual characters in a string. That means that the first character of the string str is str.Chars(0) , the second character is str.Chars(1) , and so on. By default, comparison operations on strings are case-sensitive, although there is an overloaded version of the Compare method that permits case-insensitive comparisons. The empty string (which is a string object containing no characters) is distinguished from a string reference set to Nothing . If a string has not been initialized , it will be Nothing . Any string, including the empty string, compares greater than a Nothing string reference. Two Nothing references compare equal to each other. Language Support The VB.NET language provides a number of features to make working with strings easier and more intuitive. String Literals and Initialization You can define a String literal by enclosing a string of characters in double quotes. The proper way to initialize a string variable with a literal value is to supply the literal after an equals sign. You do not need to use new as you do with other data types. Here are some examples of string literals and initializing string variables . See the program StringLiterals . Dim s1 As String = "bat" Dim path As String = "c:\OI\NetVb\Chap04\Concat\" Dim greeting As String = """Hello, world""" Console.WriteLine(s1) Console.WriteLine(path) Console.WriteLine(greeting) This produces the following output. bat c:\OI\NetVb\Chap04\Concat\ "Hello, world" Concatenation The String class provides a method Conca t for concatenating strings. In VB.NET, you can use the operators & and &= to perform concatenation. The program Concat illustrates string literals and concatenation. ' Concat.vb ' ' Demonstrates string literals and concatenation Imports System Module Concat Public Sub Main() Dim s1 As String = "bat" Console.WriteLine("s1 = {0}", s1) Dim s2 As String = "man" Console.WriteLine("s2 = {0}", s2) s1 &= s2 Console.WriteLine(s1) Dim path1 As String = "c:\OI\NetVb\Chap04\Concat" Console.WriteLine("path1 = {0}", path1) Dim path As String = "c:\OI\NetVb\Chap04\Concat\" Dim file As String = "Concat.vb" path = path + file Console.WriteLine(path) Dim greeting As String = """Hello, world""" Console.WriteLine(greeting) End Sub End Module Here is the output: s1 = bat s2 = man batman path1 = c:\OI\ NetVb\Chap04\Concat c:\OI\ NetVb\Chap04\Concat\Concat.vb "Hello, world" & and + for Concatenation The proper string concatenation operator in VB.NET is &. Often, the + operator will work too, but not always. In some contexts when using + the compiler will attempt to convert the string to a numerical data type, and you will get an illegal cast exception. Always use & for string concatenation. | Index You can extract an individual character from a string using the Chars indexed property and a zero-based index. Dim s1 As String = "bat" Dim ch As Char = s1.Chars(0) ' contains 'b' Relational Operators In general, for reference types, the = operator checks if the object references are the same, not whether the contents of the memory locations referred to are the same. However, the String class overloads these operators so that the textual content of the strings is compared. The program StringRelation illustrates using these relational operators on strings. ' StringRelation.vb Imports System Module StringRelation Public Sub Main() Dim a1 As String = "hello" Dim a2 As String = "hello" Dim b As String = "HELLO" Dim c As String = "goodbye" Console.WriteLine("{0} = {1}: {2}", a1, a2, a1=a2) Console.WriteLine("{0} = {1}: {2}", a1, b, a1=b) Console.WriteLine("{0} <> {1}: {2}", a1, c, a1<>c) Console.WriteLine("{0} < {1}: {2}", a1, c, a1<c) End Sub End Module The output of this program follows. hello = hello: True hello = HELLO: False hello <> goodbye: True hello < goodbye: False String Equality To fully understand issues of string equality, you should be aware of how the compiler stores strings. When string literals are encountered, they are entered into an internal table of string identities. If a second literal is encountered with the same string data, an object reference will be returned to the existing string in the table; no second copy will be made. As a result of this compiler optimization, the two object references will be the same, as represented in Figure 4-1. Figure 4-1. Object references to a string literal refer to the same storage. You should not be misled by this fact to conclude that two object references to the same string data will always be coalesced into the same object. If the contents of the strings get determined at runtime, for example, by the user inputting the data, the compiler has no way of knowing that the second string should have an identical object reference. Hence you will have two distinct object references, which happen to refer to the same data, as illustrated in Figure 4-2. Figure 4-2. Two distinct object references, which happen to refer to the same data. When strings are checked for equality, either through the relational operator = or through the Equals method, a comparison is made of the contents of the strings, not of the object references. So in both the previous cases the strings a and b will check out as equal if they contain the same data, even if they are distinct objects. You have to be more careful with other reference types, where reference equality is not the same as content equality. String Comparison The fundamental way to compare strings for equality is to use the Equals method of the String class. There are several overloaded versions of this function, including a shared version that takes two String parameters and a non-shared version that takes one String parameter that is compared with the current instance. These methods perform a case-sensitive comparison of the contents of the strings. A Boolean value of True or False is returned. If you wish to perform a case-insensitive comparison, you may use the Compare method. This method has several overloaded versions, all of them shared. Two strings, s1 and s2, are compared. An integer is returned expressing the lexical relationship between the two strings, as shown in Table 4-2. Table 4-2. Return Values of the Compare Method Relationship | Return Value | s1 less than s2 | negative integer | s1 equal to s2 | | s1 greater than s2 | positive integer | A third parameter allows you to control the case sensitivity of the comparison. If you use only two parameters, a case-sensitive comparison is performed. The optional third parameter is a Boolean . A value of False calls for a case-sensitive comparison, and a value of True calls for ignoring case. See the program StringCompare for an illustration of a number of comparisons, using both the Equal and Compare methods. ' StringCompare.vb Imports System Module StringCompare Public Sub Main() Dim a1 As String = "hello" Dim a2 As String = "hello" Dim b As String = "HELLO" Dim c As String = "goodbye" Console.WriteLine("{0}.Equals({1}): {2}", _ a1, a2, a1.Equals(a2)) Console.WriteLine("String.Equals({0},{1}): {2}", _ a1, a2, String.Equals(a1, a2)) Console.WriteLine("Case sensitive...") Console.WriteLine("String.Compare({0},{1}): {2}", _ a1, b, String.Compare(a1, b)) Console.WriteLine("Case insensitive...") Console.WriteLine(_ "String.Compare({0},{1},true): {2}", _ a1, b, String.Compare(a1, b, True)) Console.WriteLine("Order relation...") Console.WriteLine("String.Compare({0},{1}): {2}", _ a1, c, String.Compare(a1, c)) Console.WriteLine("String.Compare({0},{1}): {2}", _ c, a1, String.Compare(c, a1)) End Sub End Module Here is the output: hello.Equals(hello): True String.Equals(hello,hello): True Case sensitive... String.Compare(hello,HELLO): -1 Case insensitive... String.Compare(hello,HELLO,true): 0 Order relation... String.Compare(hello,goodbye): 1 String.Compare(goodbye,hello): -1 String Input The Console class has methods for inputting characters and strings. The Read method reads in a single character (as an Integer ). The ReadLine method reads in a line of input, terminated by a carriage return, line feed, or combination, and will return a String . In general, the ReadLine method is the easier to use and synchronizes nicely with Write and WriteLine . The program ReadStrings illustrates reading in a first name, middle initial, and a last name. All input is done via ReadLine . The middle initial as a character is determined by extracting the character at position 0. Imports System Module ReadStrings Public Sub Main() Console.Write("First name: ") Dim first As String = Console.ReadLine() Console.Write("Initial: ") Dim initial As String = Console.ReadLine() Dim ch As Char = initial.Chars(0) Console.Write("Last name: ") Dim last As String = Console.ReadLine() Dim name As String = first + " " + ch + ". " + last Console.WriteLine("name = {0}", name) End Sub End Module Our InputWrapper class (introduced in Chapter 3) has a method getString , which provides a prompt and reads in a string. String Methods and Properties In this section we will survey a few useful methods and properties of the String class. Many of the methods have various overloaded versions. We show representative versions. Consult the online documentation for details on these and other methods. The program StringMethods demonstrates all the examples that follow. String.Length Public ReadOnly Property Length As Integer This property returns the length of a string. Notice the convenient shorthand notation that is used for declaring a property. Dim str As String = "hello" Dim n As Integer = str.Length ' 5 String.ToUpper Overloads Public Function ToUpper() As String This method returns a new string in which all characters of the original string have been converted to uppercase. str = "goodbye" str = str.ToUpper() ' GOODBYE String.ToLower Overloads Public Function ToLower() As String This method returns a new string in which all characters of the original string have been converted to lowercase. str = str.ToLower() ' goodbye String.Substring Overloads Public Function Substring(_ ByVal startIndex As Integer, _ ByVal length As Integer _) As String This method returns a substring that starts from a specified index position in the value and continues for a specified length. Remember that the index of the first character in a string is 0. Dim substring As String = str.Substring(4, 3) ' bye String.IndexOf Overloads Public Function IndexOf(_ ByVal value As String _) As Integer This method returns the index of the first occurrence of the specified string. If the string is not found, -1 is returned. str = "goodbye" Dim n1 As Integer = str.IndexOf("bye") ' 4 Dim n2 As Integer = str.IndexOf("boo") ' -1 StringBuilder Class As we have discussed, instances of the String class are immutable. As a result, when you manipulate an instance of String , you are actually obtaining a new String instance. Depending on your applications, creating all these instances may be taxing on performance. The .NET library provides a special class StringBuilder (located in the System.Text namespace) in which you may directly manipulate the underlying string without creating a new instance. When you are done, you can create a String instance out of an instance of StringBuilder by using the ToString method. A StringBuilder instance has a capacity and a maximum capacity. These capacities can be specified in a constructor when the instance is created. By default, an empty StringBuilder instance starts out with a capacity of 16. As the stored string expands, the capacity will be increased automatically. The program StringBuilderDemo provides a simple demonstration of using the StringBuilder class. It shows the starting capacity and the capacity after strings are appended. At the end, a String is returned. ' StringBuilderDemo.vb Imports System Imports System.Text Module StringBuilderDemo Public Sub Main() Dim build As StringBuilder = New StringBuilder() Console.WriteLine("capacity = {0}", build.Capacity) build.Append("This is the first sentence." + vbLf) Console.WriteLine("capacity = {0}", build.Capacity) build.Append("This is the second sentence." + vbLf) Console.WriteLine("capacity = {0}", build.Capacity) build.Append("This is the last sentence." + vbLf) Console.WriteLine("capacity = {0}", build.Capacity) Dim str As String = build.ToString() Console.Write(str) End Sub End Module Here is the output: capacity = 16 capacity = 34 capacity = 70 capacity = 142 This is the first sentence. This is the second sentence. This is the last sentence. |