User Tools

Site Tools


it:strings

strings and string lists in Delphi

introduction

  • in the beginning, a string in Turbo Pascal and in Delphi was 8-bit and thus limited to 255 characters (char) and is semantically equivalent to an array 0..255 of char - this string type is now known as a short string
    • the zero position was reserved to store the actual string length used
    • one could define a shorter string by using string[x] where x is the maximum length to be available
    • one could determine the actual length used by accessing the str[0] value
  • Delphi 1 being 16 bit, introduced the PChar which was equivalent to the char pointer in the C language and in 16-bit Windows could be up to 16-bits long.
    • a PChar is very different to a short string in that it is a pointer and not just memory allocated on a memory stack.
    • one cannot just assign a string value to a PChar, the programmer needs to allocate and deallocate memory as needed by using various functions such as StrAlloc(), StrDispose() and use functions such as StrCopy(p, str) to assign a string to a pchar.
    • determining length of a pchar uses much more resources than to do so for a string.
  • when 32 bit Windows arrived, Delphi introduced a 32bit string Long String (now called AnsiString) to provide more efficient processing than resorting to pchars.
    • each character holds only one byte (hence the AnsiString terminology when Unicode two-byte strings were later introduced)
    • the length was again stored in the zero byte and the string could be up to 2Gb in length
    • BUT unlike short string:
      • it is reference counted and automatically managed
      • an AnsiString variable is actually a pointer to the first character of the string in memory. Thus if s = empty string then s is actually a nil pointer value.
        • hence trying to reference str[5] when str = empty string will result in an access violation!
      • it is null terminated just like a pchar and the C language null-terminated strings used by Windows, and thus plays with pchars very nicely
  • from Windows 2000 onwards, it was important to support Unicode WideStrings, particularly as this became the main internal Windows API string and was also used by OLE functions
    • the Delphi WideString is similar to an AnsiString except it uses WideChar instead of Char and these have 2 bytes per WideChar
  • then came immutable strings in .NET
    • all .NET strings are immutable ie. once a value is set, it cannot be simply changed but a new string must be made and the old one discarded
    • hence the introduction of the TStringBuilder class in Delphi 2009 (see below) which uses a buffer to handle this
  • then along came cross-platform zero-based strings

string routines

formatting strings

other routines

TStringList and TStrings

  • TStringlist class allows storage of a number of strings, similar to lines of a memo
  • whilst TStringList is derived from TStrings, you should use TStringlist rather than TStrings as TStrings have some methods that are abstract and not implemented (eg. clear, delete, insert) - an exception is perhaps when you are passing as a parameter in a procedure or function as this would allow passing any descendant including Memo.lines, Listbox.items, etc.
  • you must create an instance then free it when you are finished with it
  • it allows you to sort the strings
  • it allows you to limit the list to only unique strings
  • you can get the text of all strings as a single string using the Text property
  • you can store an object or other data next to the string
  • to add more strings, use append
  • you can use commatext, delimitedtext, or just text to get or set the text
  • you can access a string by its index value
  • there are many methods one can use including LoadFromFile and SaveToFile and sort
  • see:
var
  slist: TStringList; 
begin
 
slist := TStringList.Create;
try
  ...
  // do things with your stringlist  
  ...
finally
  if Assigned(slist) then
    FreeAndNil(slist);
end;
end;

TStringBuilder

procedure TMainForm.Button1Click(Sender: TObject);
var
  SB: TStringBuilder;
begin
  { Increase the click count for the button. }
  Inc(FClickCount);
 
  { Create a new instance of TStringBuilder. }
  SB := TStringBuilder.Create();
  try
  { Append the message to the string builder. }
  SB.Append('This button was pressed ').
    AppendFormat('%d times', [FClickCount]);
 
  { Show a message; use ToString to access the built string. }
  MessageDlg(SB.ToString(), mtInformation, [mbOK], 0);
 
  { Clear the string builder to allow building another string. }
  SB.Clear();
 
  if SB.Length <> 0 then
    MessageDlg('This cannot happen! Length must be 0 after clear!', mtError, [mbOK], 0);
 
  { Build another string with 2 lines. }
  SB.Append('The name of the button was:').
    AppendLine().
      Append((Sender as TButton).Name);
 
  { Show another message and free the string builder instance. }
  MessageDlg(SB.ToString(), mtInformation, [mbOK], 0);
  finally
  SB.Free;
  end;
end;
it/strings.txt · Last modified: 2014/07/18 01:29 by gary1