To get an idea of how efficiently the StringBuilder manipulates strings, Figure 9.1 shows an application that reverses a string. The program reverses two strings — one declared as String, and another one declared as StringBuilder. Note that neither the String nor the StringBuilder class exposes a method for reversing the order of the characters in a string. Actually, the String class exposes a Reverse method, which returns a collection of characters — the least useful implementation of a string reversal method, in my opinion. However, you can use the StrReverse() function in this project to reverse a string with a single function call. In this example, we’ll reverse the strings by swapping individual characters to time the two classes.
On my computer, it took less than a hundredth of a second to reverse a string of approximately 90,000 characters (the text of this chapter) with the StringBuilder class and nearly 15 seconds to do the same with the String class. Obviously, the StringBuilder class is optimized for manipulating strings dynamically. If you have VB 6 applications that manipulate strings extensively, port them to VB 2008, replace the string variables with instances of the StringBuilder class, and watch them run circles around the old applications written with the String class.
The StringReversal project reads the text on the TextBox control and appends it to the STR StringBuilder variable. Then it goes through the first half of the string, one character at a time, and swaps it with the matching character in the second half of the array. The first character in the string, STR.Chars(0), is swapped with the last character, STR.Chars(STR.Length-1). The second character, STR.Chars(1), is swapped with the second-to-last character, STR.Chars (STR.Length − 2), and so on. Notice that we subtract one from the indices because the indexing of the characters in both String and StringBuilder variables starts at zero, and the location of the last character is the length of the string minus one. The code stores the length of the StringBuilder to the txtLen variable to avoid calling the Length property at each iteration. Listing 9.4 shows the code that reverses a string by using a StringBuilder variable; this is the code behind the Reverse Text (StringBuilder) button. The actual implementation contains a few statements that time the operation, which are not shown in the listing.
Listing 9.4: Reversing a StringBuilder Variable
Dim STR As New StringBuilder() Dim txtLen As Integer = TextBox1.Text.Length STR.Capacity = txtLen STR.Append(TextBox1.Text) Dim ichar As Integer Dim chr As Char For ichar = 0 To Convert.ToInt32(txtLen / 2 - 1) chr = STR.Chars(ichar) STR.Chars(ichar) = STR.Chars(txtLen - ichar - 1) STR.Chars(txtLen - ichar - 1) = chr Next Dim revCrLf As String revCrLf = vbCrLf.Chars(1) & vbCrLf.Chars(0) STR.Replace(revCrLf, vbCrLf) TextBox1.Text = STR.ToStringCode language: PHP (php)
To reverse a string variable, we use the string-manipulation functions of VB, because the String class doesn’t provide any methods that act directly on the string (you cannot even manipulate a string through its Chars property, because this property is read-only). Unlike the methods of the StringBuilder class, the equivalent VB functions use the index 1 for the first character of the string. The Mid() function extracts a character from a string, and the Mid statement replaces one of the existing characters with another one. Listing 9.5 is the code of the Click event handler of the Reverse Text (String) button. The project contains a few more statements to time the operations, and they’re discussed in the following section.
Listing 9.5: Reversing a String Variable
Dim txt As String = TextBox1.Text Dim txtLen As Integer = txt.Length Dim aChar As String For iChar As Integer = 1 To _ Convert.ToInt32(txtLen / 2)) aChar = Mid(txt, iChar, 1) Mid(txt, iChar, 1) = _ Mid(txt, txtLen - iChar + 1, 1) Mid(txt, txtLen - iChar + 1) = aChar Next Dim revCrLf As String = vbCrLf.Chars(1) & _ vbCrLf.Chars(0) txt = txt.Replace(revCrLf, vbCrLf) TextBox1.Text = txtCode language: PHP (php)
Notice the statement that replaces carriage returns and line feeds. On the TextBox control, each line is terminated with the sequence Chr(10) & Chr(13) (the vbCrLf constant). When the order of these two characters is reversed, they will no longer change lines on the TextBox control. This statement restores the line-feed/carriage-return combination back to its original state.
To reverse the characters by using the String data type, I’ve used the straightforward approach that most VB developers would. The string-manipulation functions are so slow compared to the methods of the StringBuilder class, there just had to be a better way. Indeed, you can store the characters that make up the text in an array and then reverse the elements of this array.
The operation is much faster than using string-manipulation functions; it takes almost half a second to reverse a 90,000 character string. However, it takes the StringBuilder class a few milliseconds to do the same. If you’re interested in seeing an example of manipulating a string as an array of characters, see the code behind the Reverse Text (Chars) button on the application’s form. The core of the string reversal code is the following:
Dim chars() As Char = txt.ToCharArray Dim reversedChars() As Char = chars.ToArray For iChar As Integer = 0 To _ Convert.ToInt32(Math.Floor(txtLen / 2)) - 1 reversedChars.SetValue( _ chars(iChar), (txtLen - iChar - 1)) reversedChars.SetValue( _ chars(txtLen - iChar - 1), iChar) Next TextBox1.Text = reversedCharsCode language: PHP (php)