Professional Documents
Culture Documents
Author links // Utility to find the next occurence of the FindFirst substring
// If not found, -1 is returned
// If no FindFirst performed before this call, -2 is returned
// This utility is CASE SENSITIVE
function FindNext : Integer;
This is quite long, but a lot of it is commentary. Click on the highlighted keywords to learn more. The new
TStringy class is a type - not a variable. We are defining a class - it must be built (instantiated) into an object to
be used.
The definition is split into sections - private for private, internal fields (data) and methods (routines), and
published for externally visible fields and methods (see also Protected and Public).
The class is built into an object by calling the constructor Create method. This takes a string called Text. As a
user of the class, we do not care what it does with this string, just so long as it remembers it. Objects are very
good at that - a feature of object orientation.
Our class has published functions to perform the replace and find operations that we want. And it has a
property to retrieve the word count. Again, we just use the property, not caring how the object calculated tha
value.
There is also a property for reading changing the original construction string. When writing a new value, the
property calls a private method SetText. This allows us to do more than just store the new string value.
In the private section, we hold the string, and other bits and pieces, along with internal methods. These are not
visible to users of the object.
implementation
uses
// Units used only internally by this class
SysUtils, StrUtils;
The constructor stores the passed string, prepares for the Find processing, and
calculates the number of words in the string. Well not exactly - it calls a private
method to do this (shown a bit further on).
When we change the string, we must of course recalculate the word count. The
WordCount write property calls SetText does just this:
procedure TStringy.GetWordCount;
const
// Define word separator types that we will recognise
LF = #10;
TAB = #9;
CR = #13;
BLANK = #32;
var
WordSeparatorSet : Set of Char; // We will set on only the above characters
index : Integer; // Used to scan along the string
inWord : Boolean; // Indicates whether we are in the middle of a word
begin
// Turn on the TAB, CR, LF and BLANK characters in our word separator set
WordSeparatorSet := [LF, TAB, CR, BLANK];
We'll cover this bit by bit. You can read further by clicking on the links in the
code.
First, we define character constants for the characters that we will recognise as
word separators. Then a Set variable WordSeperatorSet is defined. We set on
just the word separator characters in this set of all characters. We can then use
In to check if a character in the string is one of these types. This is very elegant
and makes for very readable code. A nice feature of Delphi.
We do this in a For loop, scanning the whole length of the string. We use a
Boolean flag to remember whether the last character we looked at was a
character. This is quite compact code, and runs efficiently. Note that we could
have done withouth the inner begin..end statements. We use them for code
clarity.
Result := FindNext;
end;
Note that we store the return value from a function in a pseudo variable called
Result. We do not have to set the value at the end of the routine. We can read
from it as well.
// Position the next search from where the above leaves off
// Notice that index gets incremented even with a successful match
stFindPosition := index
end;
// This subroutine will now exit with the established Result value
end;
We use a While loop to scan along the string. We avoid using a For loop because
we need to abandon the string scan at any time if we find the substring in it.
We use AnsiMidStr to extract a section of the current string at the current index
position for comparing with the find string.
// If no character match :
if not matched then
begin
// Store the current character in the target string, and
// then skip to the next source string character
newText := newText + stText[index];
Inc(index);
end;
end;
// Copy the newly built string back to stText - as long as we made changes
if count > 0 then stText := newText;
The whole of the Stringy is shown on the next page, along with sample code that
illustrates use of it.