Delphi Strings undercon1.gif (4551 bytes)
A.  Primer B. Routines C.  Packages/Libraries D.  Tips E.  Miscellaneous

AmazonTechnical.gif (2495 bytes)  in   look for   Delphi

(bookmark.gif (183 bytes) Bookmark)

A. Primer

Very Rough Draft

CHAR, #13 vs. #$0D

ASCII Codes
http://astronomy.swin.edu.au/~pbourke/dataformats/ascii.html 
H. Debs' UseNet Post with ASCII Codes
Appendix C, ASCII Character Set, Tomes Graphical, pp. 857-860

bookmark.gif (183 bytes) Terminal Font
(Example, #$32 = #50 = '2')
TerminalFont.jpg (41610 bytes)

 

bookmark.gif (183 bytes) Arrial Narrow Font
ArialNarrowFont.jpg (48162 bytes)

bookmark.gif (183 bytes) Symbol Font
SymbolFont.jpg (30046 bytes)

bookmark.gif (183 bytes)  ShowFont program (including D5 code).

ScreenShowFont.jpg (56527 bytes)

Appendix D, Virtual Key Code Chart, Tomes Graphical, pp. 861-863
Online Virtual Key Code List:   www.drdelphi.com/delphi/right/tips/vkcodes.htm

Common "Special" Characters

Decimal Hexadecimal Virtual Key Code Description
  0 00 - Null
  7 07 - Bell
  8 08 VK_BACK Backspace
  9 09 VK_TAB Horizontal Tab
10 0A - Line Feed
11 0B - Vertical Tab
12 0C - Form Feed
13 0D VK_RETURN Carriage Return
27 1B VK_ESCAPE Escape

Example of using "Special" characters in a string:

   CONST   // best to use mnemonics whenever possible
     CR  = #$0D;
     TAB = #$09;

ShowMessage('Line One' + #$0D + 'Line Two' + #13 + 'Line Three' + CR + 'Line Four');

ShowMessage('Column One' + TAB + 'Column Two' + TAB + 'Column Three');

The concatenation operator is not necessary if constants are coded inline:

ShowMessage('This string displays'#13#10'on two lines');

Each line of an ASCII file in a DOS/Windows environment is terminated with the pair:  Carriage Return (13 or $0D), Line Feed (10 or $0A).  In many Unix files, a line in an ASCII file is terminated only with a Line Feed ($0A).

ANSIChar:  one byte per character.  Some day WideChars (two bytes per charcter) may become the default.

pChar (allocate with strNew or strAlloc)
ARRAY[0..Length-1] OF CHAR is automatically treated as a pChar

String Types

Version Type Maximum Length Memory Required Used for Notes
D1 String
String[n]
255 characters 2 to 256 bytes   n IN 0..255
D2-D5 String[n]
(n IN 0..255)
ShortString
backward compatibility n IN 0..255
D2-D5 String,
AnsiString
~231 characters 4 bytes to 2 GB 8-bit ANSI characters Sometimes called "long string."  Preferred type for most purposes.
D2-D5 WideString ~230 characters 4 bytes to 2 GB Unicode characters; COM servers and interfaces  

Notes (D2 or later):

Dynamic String Length

String Comparison

Delphi 5 Developer's Guide  Information

ShortString pp. 54-56
AnsiString pp. 48-54
WideString pp. 56-57
Null-Terminated Strings pp. 57-59
String Resources p. 83

String:  "Old" (TP and D1) and "New" Strings (D2 and later)

ShortString (D2) maintains 255-character limitation for compatibility with "old" strings (and sometimes for storage efficiency).  There are two ways to declare short string even when the "Hugh String" {$H+} compiler option is turned on.  Declare a ShortString or define the length of less than 256 characters:   MyString:  STRING[255];

A ShortString is really just an array that has a few additonal properties.   A long string is a pointer to a null-terminated string.  It is an unusual pointer in that it has data at a negative offset.

ANSIString  (Default in D2) or "long strings."   ANSIStrings act very much like ShortStrings except when you try to tream them as an array.

Delphi's string functions are highly optimized and, in general, they're easier to use and more reliable -- even if you're familiar with C/C++ null-terminated strings and string pointers.

The Windows API uses C-style strings.  If you call Windows API routines in Delphi you must use C-style strings.  In D1, if you need strings larger than 255 characters (and less than 65,526 bytes including the terminator) you might use a null-terminated string.

The first character in a null-terminated string is s[0].  The first character in a Pascal string is s[1].

Pascal strings can be compared using the usual logical operators <, > , <=, >=, and -.  Use the StrComp function to compare null-terminated strings.

Use the Pascal Chr function to assign ASCII values as characters to a string element:  s[5] := Chr(65);

The type pChar is a pointer to a CHAR.  Use this type for a null-terminated string.

You can directly assign a pChar to a long string.

WideChars:  In Delphi you can access WideChars (since they are accessible from the Windows API) but you cannot dipslay Unicode strings in Delphi controls.  A WideChar has two bytes per character.

efg's Unicode Lab Report 

Reference Counting is automatically performed on long strings.   If you assign one AnsiString to another, Delphi does not necessarily copy the string into a new place in memory.  Delphi increments a variable that keeps track of the number of references to the string.  If a reference to the string goes out of scope, the memory may not be deallocated but the reference count is decremented.   When the reference count becomes zero, the memory is deallocated.  See "Reference Counting," Delphi in a Nutshell, pp. 58-61 for additional details.

First character of array element:  Code := StringList[j][1];

Delphi in a Nutshell, pp. 15-16, various parts of Chapter 5, "Language Reference;" Appendix B, "The SysUtils Unit" explains String Management, pp. 503-515

According to Bob Lee in a UseNet Post:  "D5, and presumably all future versions, convert short strings to longstrings before doing anything with them.  The end result is that you are seriously penalized for using short strings."


B. Routines

1A.  "Standard" Pascal/Delphi Strings and Character Routines

AdjustLineBreaks Function AdjustLineBreaks(const S: string):   string;

AdjustLineBreaks adjusts all line breaks in the given string S to be true CR/LF sequences. The function changes any CR characters not followed by a LF and any LF characters not preceded by a CR into CR/LF pairs. It also converts LF/CR pairs to CR/LF pairs. The LF/CR pair is common in Unix text files. (SysUtils)

AnsiCompareStr
AnsiCompareText
AnsiExtractQuotedStr
AnsiLowerCase
AnsiPos
AnsiQuotedStr
AnsiSameStr
AnsiSameText
AnsiUpperCase
(SysUtils)
AppendStr PROCEDURE  AppendStr(VAR Dest:  STRING; CONST s:  STRING);

AppendStr appends s to the end of DestAppendStr corresponds to the statement
     Dest := Dest + S;
but is more efficient.  (D1 only; in later versions use Dest := Dest + S instead.)

AssignStr
Chr FUNCTION Chr(x:  BYTE):  CHAR;

Returns a character of the specified ordinal number.  (TP = Turbo Pascal)
CompareMem In Sysutils:
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean;
CompareStr function CompareStr(const S1, S2: string): Integer;

CompareStr compares S1 to S2, with case-sensitivity. The return value is less than 0 if S1 is less than S2, 0 if S1 equals S2, or greater than 0 if S1 is greater than S2. The compare operation is based on the 8-bit ordinal value of each character and is not affected by the current Windows locale.

CompareText  
Concat FUNCTION Concat(s1 [, s2, ..., sn]:  STRING):   STRING;

Concatenates a sequence of strings.  (TP)

Copy FUNCTION Copy(s:  STRING; index:  INTEGER; count:   INTEGER):  STRING;

Returns a substring of a string.  (TP)
Delete PROCEDURE Delete(VAR s:  STRING; index:  INTEGER; count:  INTEGER);
DisposeStr  
Insert PROCEDURE Insert(source:  STRING; VAR s:  STRING; index:  INTEGER);
IsDelimiter function IsDelimiter(const Delimiters, S: string; Index: Integer): Boolean;

Call IsDelimiter to determine whether the character at byte offset Index in the string S is one of the delimiters in the string Delimiters. Index is the 0-based index of the byte in question, where 0 is the first byte of the string, 1 is the second byte, and so on.

When working with a multi-byte character system (MBCS), IsDelimiter checks to make sure the indicated byte is not part of a double byte character. The delimiters in the Delimiters parameter must all be single byte characters.   (SysUtils)

LastDelimiter function LastDelimiter(const Delimiters, S: string): Integer;

Call LastDelimiter to locate the last delimiter in S. For example, the line

MyIndex := LastDelimiter('\.:','c:\filename.ext');

sets MyIndex to 12.

When working with multi-byte character sets (MBCS), S may contain double byte characters, but the delimiters listed in the Delimeters parameter must all be single byte non-null characters.

Length FUNCTION Length(s:  STRING):  INTEGER;

Returns the dynamic length of a string (TP). 

LowerCase  
NewStr  
NullStr const NullStr: PString = @EmptyStr;

NullStr is the return value for many string-handling routines when the string is empty.

operator: + concatenation operator
Breaking up a long string, ZD Tip
opertors:
<, <=,
>, >=,
=, <>
comparison operators
Ord FUNCTION Ord(x):  LongInt;

Returns the ordinal number of an ordinal-type value. (TP)
ParamStr  
Pos FUNCTION Pos(substr, s:  STRING):  BYTE;

Searches for a substring in a string (TP)

Julian Bucknall discusses text searching using the Boyer-Moore algorithm, showing how it is so much faster than Delphi's built-in Pos function.   Delphi Magazine, Issue 36, August 1998.

QuotedStr (SysUtils)
SameText (SysUtils)
SetLength
(D2)
In D2 or later (not for use with ShortStrings or Strings in D1):
  SetLength(s, 35);
In D1:
  s[0] := #35;

ZD Tip:  Cast Strings as PChar

See GetEnvironmentVariable example in Windows API section below.

StringOfChar (D2) FUNCTION StringOfChar(Ch: CHAR; Count: INTEGER): STRING;

StringOfChar returns a string containing Count characters with the character value given by Ch.

StringOfChar('A', 10) =  'AAAAAAAAAA'

StringReplace
(D4)
type TReplaceFlags = set of (rfReplaceAll, rfIgnoreCase);

function StringReplace(const S, OldPattern, NewPattern: string; Flags:    TReplaceFlags): string;

Example:  Remove commas from number
StringReplace( '999,999,999', ',', '', [ rfReplaceAll ] );

Ralph's (Team B) Example:
s := StringReplace(s, '-', '/', [rfReplaceAll]);

Philippe Ranger's UseNet post with StringReplace examples

Arjang's Example from UseNet Post: 

StringReplace('T e x t W i t h S pa c e s,' ','',[rfreplaceAll]);

gives you 'TextWithSpaces', without any space characters.

They Were There All Along:  Fun with SysUtils, Delphi Informant, Feb 1999

Optimizing String Searches in Delphi in Delphi Developer

Trim (D2) function Trim(const S: string): string;
TrimLeft (D2)  
TrimRight (D2)  
UpCase FUNCTION UpCase(c:  CHAR):  CHAR;

Converts a character to upper case.  Charcter values not in the range a..z are not affected.  (TP)
UpperCase function UpperCase(const S: string): string;
WrapText function WrapText(const Line, BreakStr: string; nBreakChars: TSysCharSet; MaxCol: Integer):string; overload;

function WrapText(const Line, MaxCol: Integer = 45):string; overload;

WrapText scans a string for occurrences of any of the characters specified by nBreakChars and inserts a line-break, specified by BreakStr, at the last occurrence of a character in nBreakChars before MaxCol. Line is the text WrapText scans. MaxCol is the maximum line length.

If the BreakStr and nBreakChars parameters are omitted, WrapText searches for space, hyphen, or tab characters on which to break the line and inserts a carriage return/line feed pair at the break points.

WrapText does not insert a break into an embedded quoted string (both single quotes and double quotes are supported).

For example, the following call wraps the text into two lines at the last space character:

WrapText('The rain in Spain falls mainly on the plain.', #13#10, ['.',' ',#9,'-'], 42);

The result:

The rain in Spain falls mainly on the
plain.


1B.  Conversion/Formating

"Numeric Conversion" in Delphi in a Nutshell,  pp. 515-523;
"Conversions and Formatting" in efg's General Math Functions

Format Left and right justification of strings:
  Format('<%-10.10s> <%10.10s>', ['Left', 'Right'])
  Result:  <Left      > <     Right>

Padding or chopping a string to given length:
  Format('%-10.10s', [s])

%2.2d results in zero fill for single-digit months and days
  RESULT := Format('%4.4d%2.2d%2.2d', [year, month, day]) ;

Convert '24' to '0024':
  Format('%.4d', [24])

Concatenating strings:
  Format('%s%s%s', [a, b, c])

Index Specifiers (0-origin):
Format('%2:s %1:s %0:s',  ['First', 'Second', 'Third'])
  Result:  Third Second First

Variable width and precision specifiers:
  Format('<%*.*f>', [12, 4, 100*PI])
  Result:  <    314.1593>  

Use Variable Width to Center String:
VAR
    pad : INTEGER;
    s : STRING;
    width: INTEGER;
  ...
  s := 'Center';
  width := 16;
  pad := (width - LENGTH(s)) DIV 2;
  Format('<%*s%s%*s>', [pad, ' ', s, pad, ' '])

  Result:  <     Center      >

FormatBuf  
FormatStr  
HexDisplayPrefix
(D4)
Normally '$' (SysUtils)
IntToHex  
IntToStr  
IsValidIdent  
Str PROCEDURE Str(x [:width  [:decimals] ];  VAR s:   STRING);

Converts a numeric value to its string representation (TP)
StrFmt  
StrPas  
StrToColor  
StrToDateTime  
StrToInt
StrToInt64
 
StrToIntDef
StrToIntDef64
 
Val PROCEDURE  VAL(s:  STRING;  VAR v; VAR code:   INTEGER);

Converts the string value to is numeric representation.  (TP)

2A.  "C"-like Routines:  pChars (null-terminated strings)
Strings Unit
(Descriptions from Delphi 2 Unleashed)

AnsiLastChar
AnsiStrComp
AnsiStrIComp
AnsiStrLComp
AnsiStrLIComp
AnsiStrLastChar
AnsiStrLower
AnsiStrUpper
(SysUtils)
sscanf Translation of sscanf C Utility Library.  Project JEDI Converted Tool by Clinton Johnson.
www.delphi-jedi.org/Jedi:API_TOOLS:236830434 
ftp://delphi-jedi.org//tools/sscanf.zip 
StrAlloc Allocates a buffer for null-terminated string with specified maximum length
StrBufSize Returns the maximun number of characters that can be stored in a buffer allocated by StrAlloc
StrCat Appends a copy of one string to the end of another and returns the concatenated string
StrComp Compares two strings
StrCopy Copies one string to another
StrDispose Disposes a string on the heap
StrECopy Copies one string to another and returns a pointer to the end of the resulting string
StrEnd Returns a pointer to the end of a string
StrFmt Formats a series of arguments
StrLFmt Formats a series of arguments; the result contains a pointer to the destination buffer
StrLCat Appends characters from one string to the end of another and returns the concatenated string
StrIComp Compares two strings without case sensitivity
StrLComp Compares two strings, up to a maximum length
StrLCopy Copies characters from one string to another
StrLen Returns the number of characters in Str
StrLIComp Compares two strings, up to a maximum length, without case sensitivity
StrLower Converts a string to lowercase
StrMove Copies characters from one string to another
StrNew Allocates a string on the heap
StrPas Converts a null-terminated string to a Pascal-style string
StrPCopy Copies a Pascal-style string to a null-terminated string
StrPLCopy Copies a maximum of MaxLen characters from the Pascal-style string Source into the null-terminated string Dest
StrPos Returns a pointer to the first occurence of a string in another string
StrScan Returns a pointer to the first occurence of a character in a string
StrRScan Returns a pointer to the last occurence of a character in a string
StrUpper Converts a string to uppercase

2B.  Windows API Calls (Windows Unit)

AnsiCompareStr  
AnsiCompareText  
AnsiLowerCase  
AnsiToNative  
AnsiUpperCase  
CharToOEM charToOem(pchar(myString), pChar(myString));
Converts myString from Ansi to Dos.
CopyMemory procedure ZeroMemory(Destination: Pointer; Length: DWORD); 
FillChar PROCEDURE FillChar(VAR x; Count:  WORD; Value:  Byte);

Example:   FillChar(x, SizeOf(x), #0);

FillMemory and ZeroMemory are calls to FillChar.

VAR s:  STRING;
. . .
SetLength(s, N);
FillChar(s[1], N, ' ');

FillMemory
procedure FillMemory(Destination: Pointer; Length: DWORD; Fill: Byte);  (D5)
GetEnvironmentVariable
// Example of fetching PATH envionrment variable:
VAR
  EnvVarLength:   INTEGER;
  EnvVarString:   STRING;
...
EnvVarString := '';

// Determine size of buffer needed (including NULL terminator)
EnvVarLength := GetEnvironmentVariable('PATH', NIL, 0);

IF   EnvVarLength > 0
THEN BEGIN
  // Set dynamic length of string to needed buffer size
  SetLength(EnvVarString, EnvVarLength);

  // Get PATH environment variable
  GetEnvironmentVariable('PATH', pChar(EnvVarString), EnvVarLength);

  // Get rid of NULL Terminator
  SetLength(EnvVarString, EnvVarLength-1);
END;
GetWindowsDirectory VAR
  Path: STRING;
  PathLength: DWORD;
...
PathLength := GetWindowsDirectory(NIL,0);
SetLength(Path, PathLength);
GetWindowsDirectory(pChar(Path), PathLength);
SetLength(Path, PathLength-1); // get rid of null terminator
ShowMessage(Path)
Move PROCEDURE Move(VAR Source, Dest; Count:  WORD);

Example:  Move(s1[16], s2[1], 8);

MoveMemory and CopyMemory are calls to Move.

MoveMemory procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: DWORD); 
MultiByteToWideChar  
WideCharToMultiByte  
ZeroMemory procedure ZeroMemory(Destination: Pointer; Length: DWORD);  (D5)

3.  Visual Component Library (VCL)

Strings property  
TLabel See Neil Rubenking's WrapLabel function in the AllFuncs.pas unit in his ColorClue PC Magazine utility.  WrapLabel sets the label's caption to the specified string with sensible word-wrap even if the string contains no spaces.
TMemo Windows 95/98 imposes a size limit of about 32 KB on what can be put in a TMemo.   This size limit does not affect Windows NT.  One way arround this problem is to use a TRichEdit object with PlainText := TRUE since it does not have this size limitation.

According to Guido Festraets in a 27 Aug 99 UseNet Post:
"In D4 ... [the size limit] ... is 64K, but this strangely seems to depend [on] ... the MaxLength setting. If you leave it at 0, which should mean "no limit", the limit is in fact 32K (under Win95). Set it to a higher level, and you can go up to 64K."

While Borland cannot be faulted for this limitation (blame Microsoft), they can be faulted for not mentioning this limitation in any online or printed documentation. 

To avoid size limit of TMemo, use the TRichEdit control.

TRichEdit To use TRichEdit as a replacment for a TMemo, just set the PlainText property to TRUE.

efg's RichEditResourceInit example for initializing TRichEdit from .RTF in resource file.

Unlike the TMemo, the TRichEdit does not automatically scroll down.  Here are two alternatives to make the control scroll:

1. RichEdit.Perform(EM_SCROLL,SB_LINEDOWN,0);

2.  To view the last line after adding a line:

RichEdit.SelStart := -1;
RichEdit.Perform(EM_SCROLLCARET, 0, 0);

or

// Set the caret to the last character
RichEdit1.SelStart := RichEdit1.GetTextLen;
// Scroll the caret into view
RichEdit1.Perform(EM_SCROLLCARET, 0, 0);

Example that implements Find and Replace capabilities with a TRichEdit
www.ecnet.net/users/gsmpati/delphi

TStringGrid object TI 1045D, Different colored characters in a string grid
FAQ 2068D, Resizing StringGrid Columns
FAQ 2434D, Custom InPlace Editor in StringGrid
FAQ 2681D, How do I Print a TStringGrid/TDBGrid?
FAQ 1337D, Controlling shortcut keys in a string grid

TStringGrid Example
www.govst.edu/users/gsmpati/delphi 

Advanced string grid techniques
www.bridgespublishing.com/articles/issues/0011/Advanced_string_grid_techniques.htm 

Peter Below's UseNet Post about Word Wrap in TStringGrid

A Generic Way to Print a String Grid
www.undu.com/Articles/990618c.html

Printing a StringGrid
www.gw.ro/pascal/PrintStringGrid.html 

Example of how to use a string grid to display a matrix of ICOs, and optionally, the name of the ICO
IconMapDemo.ZIP

Bitmaps in String Grids
www.undu.com/DN970601/00000013.htm

Bitmaps on String Grids?
www.undu.com/DN970501/00000027.htm

Displaying Multi-Colored Text in a String Grid
www.undu.com/DN970301/00000066.htm

Mauro Patińo's UseNet Post explaining how to use an OnDrawCell to make the fixed row font and text centering different than the remainder of the rows in a TStringGrid component

Text Alignment in StringGrid
 USES
    Classes;    // TAlignment
// Use half-width of 'X' as left margin
FUNCTION XLeft   (rect:  TRect; canvas:  TCanvas; s:  STRING):  INTEGER;
BEGIN
  RESULT := rect.Left + canvas.TextWidth('X') DIV 2
END {XRight};
FUNCTION XCenter (rect:  TRect; canvas:  TCanvas; s:  STRING):  INTEGER;
BEGIN
  RESULT := ((rect.Left + rect.Right) - canvas.TextWidth(s)) DIV 2
END {XCenter};
// Use half-width of 'X' as right margin
FUNCTION XRight (rect:  TRect; canvas:  TCanvas; s:  STRING):  INTEGER;
BEGIN
  RESULT := rect.Right - canvas.TextWidth(s) - canvas.TextWidth('X') DIV 2
END {XRight};
// Top of text is its origin, so adjust by half-height of text to center
FUNCTION YCenter (rect:  TRect; canvas:  TCanvas; s:  STRING):  INTEGER;
BEGIN
  RESULT := ((rect.Top + rect.Bottom) - canvas.TextHeight(s)) DIV 2
END {YCenter};
PROCEDURE AlignText(CONST Canvas:  TCanvas; CONST Rect:  TRect;
                    CONST alignment:  TAlignment; CONST s:  STRING);
BEGIN
  CASE alignment OF
    taLeftJustify:    Canvas.TextRect(Rect,
                               XLeft(Rect, Canvas, s),
                               YCenter(Rect, Canvas, s),
                               s);
    taCenter:         Canvas.TextRect(Rect,
                               XCenter(Rect, Canvas, s),
                               YCenter(Rect, Canvas, s),
                               s);
    taRightJustify:   Canvas.TextRect(Rect,
                               XRight(Rect, Canvas, s),
                               YCenter(Rect, Canvas, s),
                               s);
  END
END {AlignText};
...
CONST 
  ColumnAlignment: ARRAY[0..7] OF TAlignment = 
    (taLeftJustify, taLeftJustify, taLeftJustify, taLeftJustify, 
     taLeftJustify, taCenter, taCenter, taCenter);
...
procedure TFormList.StringGridListDrawCell(Sender: TObject;
  Col, Row: Longint; Rect: TRect; State: TGridDrawState);
  VAR
    s   :  STRING;
begin
  s := StringGridList.Cells[Col, Row];
  StringGridList.Canvas.Font.Color := clBlack;
  IF   Col < StringGridList.FixedCols
  THEN StringGridList.Canvas.Brush.Color := clBtnFace
  ELSE
    IF   Row < StringGridList.FixedRows
    THEN StringGridPatientList.Canvas.Brush.Color := clBtnFace
    ELSE
      IF   (Row >= StringGridList.Selection.Top) AND
           (Row <= StringGridList.Selection.Bottom)
      THEN StringGridList.Canvas.Brush.Color := clYellow
      ELSE StringGridList.Canvas.Brush.Color := clWindow;
  StringGridList.Canvas.FillRect(Rect);
  IF   Row = 0
  THEN AlignText(StringGridList.Canvas, Rect, taCenter, s)
  ELSE AlignText(StringGridList.Canvas, Rect, ColumnAlignment[Col], s)
end;
TStringList object Converting Label Collections to String Lists
www.undu.com/Articles/991117b.html
TStrings object  

4. Specialty

Abbrev FUNCTION Abbrev(CONST information,info: STRING; CONST nMatch: TStrIndex): BOOLEAN;
efg's
REXX-like function
AddBackSlash Delphi Developer's Guide, p. 775
AllSame
FUNCTION AllSame(CONST s: STRING; CONST c: CHAR): BOOLEAN;
  VAR i: INTEGER;
BEGIN
  RESULT := TRUE;
  i := 1;
  WHILE RESULT AND (i <= LENGTH(s))
  DO BEGIN
    RESULT := RESULT AND (s[i] = c);
    INC (i)
  END
END {AllSame};
BinStringToLongInt FAQ 2834D, Covert (sic) string of (zeros and ones) to binary
Capitalize
(also see Proper)
Capitalizing first characters of every word
http://members.xoom.com/_XOOM/jescott/DelphiCodeTips1.html#Capitalize

FUNCTION Capitalize (CONST s: STRING): STRING;
efg's REXX-like function

Center FUNCTION Center(CONST s: STRING; CONST sLength: TStrIndex): STRING;
efg's
REXX-like function
CharEntity Neil Rubenking's CharEntity in the AllFuncs.pas unit of his ColorClue utility.
For example, given  #034, returns 'quot', or #060, returns 'lt'.
ClearString
// Possibly FillChar could be used here if speed were more important.
PROCEDURE ClearString (VAR s: STRING);
  VAR i: INTEGER;
BEGIN
  IF   LENGTH(s) > 0
  THEN BEGIN
    FOR i := 1 TO LENGTH(s) DO
      s[i] := #$00
  END
END {ClearString};
Clipboard Copying large amounts of Text to the Clipboard
www.innotts.co.uk/~zephyr/copyclip.html 
Copies FUNCTION Copies(CONST s: STRING; CONST n: TStrIndex): STRING;
efg's REXX-like function
CountChar FUNCTION CountChar(CONST s: STRING; CONST c: CHAR): TStrIndex;
efg's REXX-like function

Also see CharCnt utility to form frequency distribution of characters in a file.

CRC efg's CRC Lab Report
Also see CheckDigit below
Cross Reference Cross Reference Tool.  Marco Cantł describes a clever utility which cross-references the variables, functions, procedures and more from all your source code files, then presents the results as HTML files; he also shows how the same techniques can be used to publish databases on the web.  Delphi Magazine, Issue 30, February 1998
ExcludeTrailingBackslash (D5) FUNCTION ExcludeTrailingBackslash(CONST S: STRING): STRING;

Use ExcludeTrailingBackslash to modify a path name (specified by the S parameter) so that it does not end with a backslash character (‘\’). If S does not end in a backslash character, ExcludeTrailingBackslash returns a copy of S.

ExpandEnvironment
Strings
Neil Rubenking's EE function in the AllFuncs.pas unit of his ColorClue utility is a wrapper for ExpandEnviornmentStrings so it works properly in both WinNTx and Win9x.
Filters (TEdit)
// Hex digit filter
procedure TFormSample.EditKeyKeyPress(Sender: TObject; var Key: Char);
  CONST BackSpace = #$08;
begin
  IF   NOT (Key IN ['0'..'9', 'a'..'f', 'A'..'F', BackSpace])
  THEN Key := #$00
end;
IsBlankField
FUNCTION IsBlankField(CONST s: STRING): BOOLEAN;
BEGIN
  RESULT := (LENGTH(s) = 0) OR (AllSame(s, ' '))
END {BlankField};
IsNumValue How to Program Delphi 3, pp. 317-318
IsPrintable FUNCTION IsPrintable(CONST c:  CHAR):   BOOLEAN;
BEGIN
  RESULT := (c IN [#$20 .. #$7E])
END {IsPrintable};
IncludeTrailingBackSlash (D5) FUNCTION IncludeTrailingBackslash(CONST S: STRING): STRING;

Use IncludeTrailingBackslash to modify a path name (specified by the S parameter) so that it ends with a backslash character (‘\’). If S already ends in a backslash character, IncludeTrailingBackslash returns a copy of S.

IsWhiteSpace Ray Lischner's String Unit to help write portable code for Delphi 1.0 & 2.0.
Secrets of Delphi 2, p. 11
LeftJustify FUNCTION Left(CONST s: STRING; CONST sLength: TStrIndex): STRING;
efg's REXX-like function (note:  rename LeftJustify to avoid Delphi name conflicts)
LTrim UDDF Strings Item 1
MatchesMask
(Masks unit)
function MatchesMask(const Filename, Mask: string): Boolean;

Call MatchesMask to check the Filename parameter using the Mask parameter to describe valid values. A valid mask consists of literal characters, sets, and wildcards.

Each literal character must match a single character in the string. The comparison to literal characters is case-insensitive.

Each set begins with an opening bracket ([) and ends with a closing bracket (]). Between the brackets are the elements of the set. Each element is a literal character or a range. Ranges are specified by an initial value, a dash (-), and a final value. Do not use spaces or commas to separate the elements of the set. A set must match a single character in the string. The character matches the set if it is the same as one of the literal characters in the set, or if it is in one of the ranges in the set. A character is in a range if it matches the initial value, the final value, or falls between the two values. All comparisons are case-insensitive. If the first character after the opening bracket of a set is an exclamation point (!), then the set matches any character that is not in the set.

Wildcards are asterisks (*) or question marks (?). An asterisk matches any number of characters. A question mark matches a single arbitrary character.

MatchesMask returns True if the string matches the mask. MatchesMask returns false if the string does not match the mask. MatchesMask raises an exception if the mask is syntactically invalid.

Note:  The Filename parameter does not need to be a file name. MatchesMask can be used to check strings against any syntactically correct mask.

MatchStrings UDDF Strings Item 2
Overlay FUNCTION Overlay(CONST ovly,target: STRING; CONST n: TStrIndex): STRING;
efg's REXX-like function
Parsers UDDF Strings Item 10

Peter Below's UseNet Post with SplitString Example

Also see Tokens (below)

Plural FUNCTION Plural(CONST n: LongInt; CONST singularform,pluralform: STRING): STRING;
efg's REXX-like function
Proper
(also see Capitalize)
Capitalize the first letter of each word
UDDF Item 5
Regular Expressions UDDF Strings Item 11

This unit implements searching strings for UNIX-style regular expressions, as supported by the vi and grep tools.  http://ourworld.compuserve.com/homepages/neil_butterworth/delphiunits.htm 

RemoveChar
// Used mostly to get rid of '&' in user interface strings
FUNCTION RemoveChar(CONST s: STRING; CONST c: CHAR): STRING;
  VAR i: INTEGER;
BEGIN
  RESULT := '';
  FOR i := 1 TO LENGTH(s) DO
  BEGIN
    IF   s[i] <> c
    THEN RESULT := RESULT + s[i]
  END
END {RemoveChar};
RemoveCommas Volker W. Walter's UseNet Post
ReplaceInFile Peter Below's UseNet Post
RemoveInvalid UDDF Strings Item 9
ReplaceSub UDDF Strings Item 4
Reverse FUNCTION Reverse(CONST s: STRING): STRING;
efg's REXX-like function
ReverseString How to reverse a string
www.preview.org/q/q1003.shtml
Right FUNCTION Right(CONST s: STRING; CONST sLength: TStrIndex): STRING;
efg's
REXX-like function (note:  rename RightJustify to avoid Delphi name conflicts)
ScanFile Peter Below's UseNet Post  to search file for a specified text.
Search Threaded text search example, Delphi in a Nutshell, pp. 123-126

Fastest way to search a string in a file
www.preview.org/q/q1024.shtml

SearchAndReplace www.chami.com/tips/delphi/010197D.html
Space FUNCTION Space(CONST s: STRING; CONST n: TStrIndex): STRING;
efg's REXX-like function
Spelling A Simple Spelling Checker.  Bob Swart describes the implementation of a spelling checker using minimal resources: ideal for when the Full Monty would be over the top!  Delphi Magazine, Issue 31, March 1998
StripBackSlash Delphi Developer's Guide, p. 775
Strip FUNCTION Strip(CONST s: STRING; CONST option: STRING): STRING;
efg's REXX-like function
StripChar Philippe Ranger's UseNet Post
StrCenter How to Program Delphi 3, pp. 318-319
StrDeleteAll How to Program Delphi 3, pp. 320-321
StrExtractCmd How to Program Delphi 3, pp. 321-322
StrLen Finding the length of a PChar string (StrLen) [optimized code example]
www.optimalcode.com/exstrlen.htm 
StrReplaceAll How to Program Delphi 3, pp. 324-325
StrReverse How to Program Delphi 3, pp. 325-326
TestString FUNCTION TestString(CONST sLength: TStrIndex): STRING;
efg's REXX-like function (actually not a REXX function but put in this library)
Create "random" character string of specified length.
TextToDOS Deepak Shenoy's UseNet Post with file stream example
Tokens GetToken, UDDF Strings Item 3
efg's TToken class  uses a finite state machine to recognize tokens delimited with specified "markers" and "separators."  Can be used to tokenize multi-word tokens enclosed in quotes, e.g., <This is "a very long" line> could be tokenized into four tokens:  1.  This, 2. is, 3. a very long, 4. line.
(updated Sept 2000)

Finite State Machine to Recognize Tokens

TokensFiniteStateMachine.gif (5574 bytes)
*Multiple separators can be treated as a single separator (e.g., space or tab white space), or treated as multiple null tokens (e.g., comma delimited data).
   How to create a Bitmap from numeric data? (D5)
Shows how to read a TXT file into a TStringList.  Parses each line in TStringList and forms a dynamic matrix of real values to be displayed in a bitmap.

Also see Parsers (above)

Translate FUNCTION Translate(CONST s,OutTable,InTable: STRING): STRING;
efg's REXX-like function

Also see XLate utility for translating entire file.

TrimRight
TrimLeft
Trim
Ray Lischner's String Unit to help write portable code for Delphi 1.0 & 2.0.
Secrets of Delphi 2, pp. 10-12
TString Class www.howtodothings.com/showarticle.asp?article=436 
WildComp Compare two strings with wildcards (*, ?)
www.preview.org/q/q1015.shtml
WordCount David Christiansen's UseNet Post with CountWords function
Grega's UseNet Post with sample code

www.chami.com/tips/delphi/122296D.html

// Finite-state machine to count words in a string
FUNCTION Words(s: STRING): INTEGER;

efg's
Words (REXX-like) function

XRange FUNCTION XRange (CONST start,stop: BYTE): STRING;
efg's REXX-like function

C. Packages/Libraries

ADQStrings Quick string manipulation library -- mainly assembly code.
http://delphi.icm.edu.pl/ftp/d40free/ADQStrings.zip 
Clipper Clipper Functions  contains more than 140 xBASE-syntax compatible functions for working with strings and dates, as well as many functions for converting numbers into various formats and low-level drive and disk functions. These functions will be very familiar to anyone who's done any xBASE (dBASE, FoxPro, or Clipper) work - many will be familiar to those who've worked with other development tools (such as Visual Basic) as well.  http://members.aol.com/clipfunc
Codebox Charlie Calvert's StrBox
http://homepages.borland.com/ccalvert/Downloads/StrBox.pas

32-bit replacement for MathBox and StrBox
http://homepages.borland.com/ccalvert/Downloads/CodeBox1.pas

Concordance Component www.rjcw.freeserve.co.uk
CStrings Complete collection of string functions to complement Delphi's built-in functions. Optimized for speed some using assembly).  Includes Bayer-Moore searching, splitting, padding, copying,  trimming, duplicating, counting and packing.    http://delphi.icm.edu.pl/ftp/d40free/cstrings.zip
EDSSpell Spell Checker www.onedomain.com/edsspell.htm 
ESBRoutines ESBRoutines™ v1.4.  Miscellaneous Routines to supplement SysUtils for Delphi™ 3 and Delphi™ 4 - though it should work well in Delphi™ 2. Including 32-bit and 16-bit Bit Lists, Block Operations, String Manipulation, Conversions and Environment Routines. Includes Help File & Full Source. Freeware. 
www.esbconsult.com.au/esbrtns.zip
Hyperstring HyperString offers over 300 high performance string management routines designed specifically for the versatile new 32-bit long dynamic string type. Extensive documentation in WinHelp format can be seamlessly integrated into the Delphi on-line help by following the simple instructions provided.
EFD Systems  Hyperstring Library
http://efd.home.mindspring.com/tools.htm
Password Generator Use this component in applications where you want to generate a password. You can decide the passwords'  characteristic at design time, or leave it up to the user by setting them at run time. http://delphi.icm.edu.pl/ftp/d30free/bkpwdgen.zip
PatternMatch PatternMatch Library to compare strings with a pattern in Dos or   Unix Style.
http://delphi.icm.edu.pl/ftp/d30free/pmatch.zip
StrCon Large collection of string functions by Eric Grobler. Makes use of default parameters and function overloading.
http://delphi.icm.edu.pl/ftp/d40free/strcon.zip
StringL StringL offers some means to process strings. A collection of procedures and functions provide several often used string formatting functions. In addition, STRINGL contains the class TGrep which offers a versatile string search utility using the wide-spread definition of regular expressions as e.g. in the Unix command "grep".
www.lohninger.com/stringl.html
SWAG Strings SWAG (Software Archive Group):  138 examples
www.gdsoft.com/swag/strings.zip      (Requires Reader)
zl21 Utility to quickly locate compressed source files. Quickly scans through zip files searching for specific text string -- like a  Grep for Zip files.
http://delphi.icm.edu.pl/ftp/tools/zl21.zip

D. Tips

Arrays of Strings  
Ascii2Ebcdic Steve Agnew's E-Mail with Ebcdic2Ascii and Ascii2Ebcdic assembly routines.

Xlate utility.   See Item B-3 on efg's Other Projects page.

Also see:  ASCII/EBCDIC Chart
http://www.natural-innovations.com/boo/asciiebcdic.html 

C Conversion C "char**" versus Delphi Strings in Delphi-JEDI Digest 74 (10 Sep 99), Danny Thorpe suggests:  An array of Pchar is an array of 4 byte pointers to string data.  Andre's description refers to the last string having a double-null terminator.  That's most commonly used when you're dealing with a buffer containing multiple embedded null-terminated strings.  It is not an array of pointers.

If passing this data to a function, you can construct the string like this:

   PChar(string1 + #0 + string2 + #0 + string3 + #0 + #0)

If receiving the data from the function, you can peel off each string in the buffer in sequence using StrEnd + 1:


var
  P: PChar;
  Strings: TStringList;
begin
  Strings := TStringList.Create;
  P := buffer;
  while P^ <> #0 do
  begin
     Strings.Add(P);   // implicitly converted to String
     P := StrEnd(P);
     Inc(P);
  end;

...
Check Digits

Validate ISBN codes  
www.q3.nu/trucomania/truco.cgi?148&ing

Non:   Delphi:
Credit Cards Validation -- Check Digits
www.beachnet.com/~hstiles/cardtype.html

2 of 5 bar code check digit
http://www2.control.com/alist/archive.old/msg02157.html

How to Calculate a Modulo 10 Check Character
www.csensors.com/modulo.html

Command-Line A Reusable Command-Line Parser
High Performance Delphi 3 Programming, pp. 13-22
Compiler options Default:  {$H+}
All strings not explicitly declared as ShortStrings will be considered long strings.
DLLs In Chapter 14 of Mastering Delphi 5 (pp. 660-662), Marco Cantł explains "Exporting Strings from a DLL."
Ebcdic2Ascii Steve Agnew's E-Mail with Ebcdic2Ascii and Ascii2Ebcdic assembly routines.

Xlate utility.   See Item B-3 on efg's Other Projects page.

Encryption/Decryption Simple Encryption/Decryption for short strings
www.preview.org/q/q1041.shtml
Optimization String Optimization Guidelines
www.optimalcode.com/string.htm 
Parameters Peter Below's UseNet Post about passing Strings as parameters
Parsing

See "Tokens" in Section B above.

Pattern Match Boyer-Moore-Horspool Pattern Match (Optimized code example)
www.optimalcode.com/exbmh.zip 
Phonetic Match Match words that sound alike

See Soundex Algorithm on efg's Delphi Algorithms page

RECORDs Strings in Records
www.209software.com/books/p4dp/StrInRec.html
Resource Files

Be Resourceful (how to use ResourceString)
www.delphiinformant.com/Opinion/2000/07/di200007BP_o/di200007BP_o.asp 

"Using String Table Resources" in Chapter 19 of Mastering Delphi 5 (pp. 855-856) by Marco Cantł.

Putting Error Strings in String Resources
p. 232, Delphi 4 Unleashed

Strings in Resource Files
www.gnomehome.demon.nl/uddf/pages/resource.htm#resource0

Search Algorithms See Searching on Delphi Algorithms page
Search/Replace Sub-String Replacement [optimized code example]
www.optimalcode.com/exstrrep.zip 
Sets "Sets to Strings, And Back" by Ray Lischner
www.delphizine.com/features/2000/04/di200004rl_f/di200004rl_f.asp
Sorting See Sorting on efg's Delphi Algorithms page
Special Characters Windows 95/98 Utility:  Start | Programs | Accessories | System Tools | Character Map
Tabbed Columns TabbedTextOut API Call, Tomes Graphical, p. 555-558
Threads Starting in D5 referring to strings and dynamic arrays will be thread-safe.

Reference counting for Long Strings is not thread safe on multi-processor machines.
Bug fixed in Delphi 5.

Ray Lischner's UseNet Post about thread-safe strings in D5.  Follow other posts in this tread about the  performance penalty this introduces, especially posts by Robert Lee, who is an optimization expert.

Yorai Aminov's (Team B) UseNet Post about whether Delphi Strings are Thread Safe

Validation Validate a 'Seguridad Social' number (Only for Spain)  
www.q3.nu/trucomania/truco.cgi?357&ing
ValidFilename Test if a string is a valid file name
www.preview.org/q/q2129.shtml
Wrapping Text Wrapping Text and Printing a ListBox
www.undu.com/Articles/990901d.html

E.  Miscellaneous

ASCII Codes http://astronomy.swin.edu.au/~pbourke/dataformats/ascii.html 
ASCII ISO 8859 ASCII - ISO 8859-1 (Latin-1) Table with HTML Entity Names
www.bbsinc.com/iso8859.html
CharMap Run C:\WINDOWS\CHARMAP.EXE (Start | Run | Charmap) to see special characters.  For example, the copyright symbol, © , is Alt-0169 in the IDE.
Internationalization; Localization Chapter 10, Creating international applications, Borland's Delphi 5 Developer's Guide.

"Localization" in Delphi in a Nutshell,  pp. 532-538

Peter Below's UseNet Post with advice on DecimalSeparator

ListSeparator new in D4.

Speaking in Charsets -- Building a Multilingual Web Site
www.webtechniques.com/archives/2000/09/yunker 

Plurals Non-Delphi:  An Algorithmic Approach to English Pluralization
www.cs.monash.edu.au/~damian/papers/HTML/Plurals.html

Links Verified 21 Aug 1999
Updated 07 Jan 2005


since 21 Aug 1999