2004. június 6., vasárnap

Splitting a string in a string list


Problem/Question/Abstract:

A function that splits a string in parts separated by a substring and returns the parts in a StringList

Answer:

Solve 1:

The following functions split a string in parts separated by a substring and return the parts in a string list that may be passed as third parameter or created by the function (and in this latter case it must be freed by the caller):

interface

uses classes;

function SplitStrings(const str: string;
  const separator: string = ',';
  Strings: TStrings = nil): TStrings;
function AnsiSplitStrings(const str: string;
  const separator: string = ',';
  Strings: TStrings = nil): TStrings;

implementation

uses sysutils;

function SplitStrings(const str: string; const separator: string;
  Strings: TStrings): TStrings;
// Fills a string list with the parts of "str" separated by
// "separator". If Nil is passed instead of a string list,
// the function creates a TStringList object which has to
// be freed by the caller
var
  n: integer;
  p, q, s: PChar;
  item: string;
begin
  if Strings = nil then
    Result := TStringList.Create
  else
    Result := Strings;
  try
    p := PChar(str);
    s := PChar(separator);
    n := Length(separator);
    repeat
      q := StrPos(p, s);
      if q = nil then
        q := StrScan(p, #0);
      SetString(item, p, q - p);
      Result.Add(item);
      p := q + n;
    until q^ = #0;
  except
    item := '';
    if Strings = nil then
      Result.Free;
    raise;
  end;
end;

function AnsiSplitStrings(const str: string; const separator: string;
  Strings: TStrings): TStrings;
// Fills a string list with the parts of "str" separated by
// "separator". If Nil is passed instead of a string list,
// the function creates a TStringList object which has to
// be freed by the caller
// ANSI version
var
  n: integer;
  p, q, s: PChar;
  item: string;
begin
  if Strings = nil then
    Result := TStringList.Create
  else
    Result := Strings;
  try
    p := PChar(str);
    s := PChar(separator);
    n := Length(separator);
    repeat
      q := AnsiStrPos(p, s);
      if q = nil then
        q := AnsiStrScan(p, #0);
      SetString(item, p, q - p);
      Result.Add(item);
      p := q + n;
    until q^ = #0;
  except
    item := '';
    if Strings = nil then
      Result.Free;
    raise;
  end;
end;

Examples:

procedure TForm1.Button1Click(Sender: TObject);
begin
  SplitStrings(Edit1.Text, ', ', ListBox1.Items);
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  Parts: TStrings;
begin
  Parts := nil;
  try
    Parts := SplitStrings(Edit1.Text, ', ');
    ShowMessage('First part is "' + Parts[0] + '"');
  finally
    Parts.Free;
  end;
end;

You can see an example using a dynamic array instead of a StringList in a separate article "Splitting a string in an dynamic array".


Solve 2:

Shorten way:

function SplitStrings(const str: string; const separator: string;
  Strings: TStrings): TStrings;
// Fills a string list with the parts of "str" separated by
// "separator". If Nil is passed instead of a string list,
// the function creates a TStringList object which has to
// be freed by the caller
begin
  if Strings = nil then
    Result := TStringList.Create
  else
    Result := Strings;

  //This replaces the separators in str with CRLF so as to fit the format  of a stringlist.
  Result.Text := StringReplace(str, separator, #13#10, [rfReplaceAll]);
end;

Nincsenek megjegyzések:

Megjegyzés küldése