Given the importance of the string type, it should come to no surprise that the helper for this type has a rather long list of operations you can perform. And given its importance and the commonality of these operations in most applications, I think it is worth going through this list with some care.
Marco Cantù, Object Pascal Handbook
I've logically grouped the string helper operations (most of which have many over-loaded versions), shortly describing what they do, considering that quite often that their names are rather intuitive:
• Copy or partial copy operations like Copy, CopyTo, Join, and SubString
• String modification operations like Insert, Remove, and Replace
• For conversion from various data types to string, you can use Parse and Format
• Conversion to various data types, when possible can be achieved using
ToBoolean, ToInteger, ToSingle, ToDouble, and ToExtended while you can turn a string into an array of characters with ToCharArray
• Fill a string white space or specific characters with PadLeft, PadRight, and one of the overloaded versions of Create. At the opposite, you can remove white space at one end of the string or both using TrimRight, TrimLeft, and Trim
• String comparison and equality test (Compare, CompareOrdinal, CompareText, CompareTo, and Equals)—but keep in mind you can also, to some extent, use the equality operator and the comparison operators
• Changing case with LowerCase and UpperCase, ToLower and ToUpper, and ToUp-perInvariant
• Test the string content with operations like Contains, StartsWith, EndsWith. Search in the string can be done using IndexOf for finding the position of a given character (from the beginning or from a given location), the similar IndexOfAny (which looks for one of the elements of an array of characters), the LastIndexOf and LastIndexOfAny operations which work backwards from the end of the string, and the special purpose operations IsDelimiter and LastDelimiter
• Access to general information about the string with functions like Length, which returns the number of characters, CountChars, which also takes surrogate pairs into account, GetHashCode, which returns a hash of the string, and the various tests for “emptiness” which include IsEmpty, IsNullOrEmpty, and IsNullOr-WhiteSpace
• String special operations like Split, which breaks a string into multiple ones based on a specific character, and removing or adding quotes around the string with QuotedString and DeQuoted
• And, finally, access to individual characters with Chars[], which has the numeri-cal index of the element of the string among square brackets. This can be used only for reading a value (not for changing it) and uses a zero-based index like all other string helper operations.
It is important to notice, in fact, that all of the string helper methods have been build following the string convention used by many other languages, which includes the
Marco Cantù, Object Pascal Handbook
concept that string elements start with zero and go up to the length of the string minus one. In other words, all string helper operations use zero-based indexes as parameters and return values.
note The Split operation is relatively new to the Object Pascal RTL. A previously common approach was loading a string in a string list, after setting a specific line separator, and later access the indi-vidual strings, or lines. The Split operation is significantly more efficient and flexible.
Given the large amount of operations you can apply directly to strings, I could have created several projects demonstrating these capabilities. Instead, I'll stick to a few relatively simple operations, albeit very common ones.
The StringHelperTest application project has two buttons. In each of them the first part of the code builds and displays a string:
var
Str1, Str2: string;
I, NIndex: Integer;
begin
Str1 := '';
// create string for I := 1 to 10 do
Str1 := Str1 + 'Object ';
Str2:= string.Copy (Str1);
Str1 := Str2 + 'Pascal ' + Str2.Substring (10, 30);
Show(Str1);
Noticed how I used the Copy function, to create a unique copy of the data of the string, rather than an alias... even if in this particular demo it won't have made any difference. The Substring call at the end is used to extract a portion of the string.
The resulting text is:
Object Object Object Object Object Object Object Object Object Object Pascal ect Object Object Object Objec
After this initialization, the first button has code for searching for a substring and for repeating such a search, with a different initial index, to count the occurrences of a given string (in the example a single character):
// find substring Show('Pascal at: ' +
Str1.IndexOf ('Pascal').ToString);
// count occurrences I := -1;
NCount := 0;
repeat
I := Str1.IndexOf('O', I + 1); // search from next element if I >= 0 then
Marco Cantù, Object Pascal Handbook
Inc (NCount); // found one until I < 0;
Show('O found: ' +
NCount.ToString + ' times');
I know the repeat loop is not the simplest one: it starts with a negative index, as any following search begins with the index after the current one; it counts occurrences;
and its termination is based on the fact that if the element is not found it returns -1. The output of the code is:
Pascal at: 70 O found: 14 times
The second button has code to perform a search and replace one or more elements of a string with something else. In the first part, it creates a new string copying the initial and final part and adding some new text in the middle. In the second, it uses the Replace function that can operate on multiple occurrences simply by passing to it the proper flag (rfReplaceAll).
This is the code:
// single replace
nIndex := str1.IndexOf ('Pascal');
str1 := str1.Substring(0, nIndex) + 'Object' + str1.Substring(nIndex + ('Pascal').Length);
Show (str1);
// multi-replace
str1 := str1.Replace('O', 'o', [rfReplaceAll]);
Show (str1);
As the output is rather long and not easy to read, here I've listed only the central portion of each string:
...Object Pascal ect Object Object...
...Object Object ect Object Object...
...object object ect object object...
Again, this is just a minimal sampler of the rich string operations you can perform using the operations available for the string type using the string type helper.