Простой текстовый итератор. Пример использования record в Delphi

Spread the love

Задача: осуществить перебор строковых значений в исходной строке, разделённых символом-разделителем, с учётом символа-кавычки.
Решение:

unit dnStringIterator;

interface

type
  TStringValuesIterator = record
  type
    TCallBack = reference to procedure (const AValue: string);
    TOptions = set of (ioTrimValues, ioDequoteValues);
  private
    FSourceString: string;
    FDelimiter, FQuoteChar: Char;
    FCheckQuotes: Boolean;
    FOptions: TOptions;
    FOffset, FLength: Integer;
    FCurrent: string;
  public
    constructor Init(const ASourceString: string; ADelimiter: Char; AQuoteChar: Char = #0; AOptions: TOptions = []);
    function GetEnumerator: TStringValuesIterator;
    function MoveNext: Boolean;
    procedure Run(ACallBack: TCallBack); inline;
    property Current: string read FCurrent;
  end;

implementation

uses
  SysUtils;

{ TStringValuesIterator }

constructor TStringValuesIterator.Init(const ASourceString: string; ADelimiter, AQuoteChar: Char; AOptions: TOptions);
begin
  FSourceString := ASourceString;
  FDelimiter := ADelimiter;
  FQuoteChar := AQuoteChar;
  FOffset := 1;
  FLength := Length(FSourceString);
  FOptions := AOptions;
  FCurrent := '';

  FCheckQuotes := FQuoteChar <> #0;

  // нельзя, чтобы символ разделитель совпадал с символом-кавычкой:
  Assert(not FCheckQuotes or (FDelimiter <> FQuoteChar));
  // нельзя использовать ioDeqouteValues, если не указан QuoteChar
  Assert(FCheckQuotes or not (ioDequoteValues in FOptions));
end;

function TStringValuesIterator.GetEnumerator: TStringValuesIterator;
begin
  Result := Self;
end;

function TStringValuesIterator.MoveNext: Boolean;
var
  IsInQuote: Boolean;
  CurPos: Integer;
  Ch: Char;
begin
  Result := (FLength > 0) and (FOffset 

Примеры использования

С явным объявлением дополнительной переменной:
var
  svi: TStringValuesIterator;
begin
  svi.Init(TestString, ',');
  while svi.MoveNext do
    Memo1.Lines.Add(svi.Current);
end;

Без явного объявления дополнительной переменной, используя with:

begin
  with TStringValuesIterator.Init(TestString, ',') do
    while MoveNext do
      Memo1.Lines.Add(Current);
end;

Используя анонимную процедуру:

begin
  TStringValuesIterator.Init(TestString, ',').Run(
    procedure (const AValue: string)
    begin
      Memo1.Lines.Add(AValue);
    end
  );
end;

Используя for-in синтаксис:

var
  Tmp: string;
begin
  for Tmp in TStringValuesIterator.Init(TestString, ',') do
    Memo1.Lines.Add(Tmp);
end;

Читать на сайте автора.

0 ответы

Ответить

Хотите присоединиться к обсуждению?
Не стесняйтесь вносить свой вклад!

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *