Delphi как в строке найти цифру

EDIT 1.: The function below will read the first floating point number after the position Start in the String S and register its end position as Last. This function does NOT work for different cases of float numbers, such as:

  • 3.1415926535897932384d0; A double-format approximation to Pi

  • 3.010299957f-1; Log2, in single format

  • -0.000000001s9 e^(i*Pi), in short format

  • 0.0s0; A floating-point zero in short format

  • 0s0; Also a floating-point zero in short format

https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node19.html

function ExtractFloatStr(Start : integer; S : string; var Last : integer) : string;
var
  i, Lstr : integer;
  chln : char;
  str_acm : string;
  Numeric, Sign, DeciSep, Exponent : boolean;
begin
  Numeric := False;  Sign := False;  DeciSep := False;  Exponent := False;
  Lstr := length(S);

  If (Start > 0) and (Start <= Lstr) then
    i := Start-1
  Else i := 0;

  Last := -1;  chln := #0;
  str_acm := '';
  repeat
  begin
    i := i + 1;
    chln := S[i];
    //ShowMessage('str_acm['+IntToStr(i)+'] = '+str_acm+'P');
    If Last = -1 then
    begin

      If chln = '-' then
      begin
        { Signs will only count if they are the first element }
        If (str_acm = '') then    { Signs can only be added at the leftmost position }
        begin
          Sign := True;
          str_acm := str_acm + chln;
        end
        { If there's something already registered as number, a right-side Sign will mean two things }
        Else begin
          { Signs cannot be added at the right side of any number or Decimal Separator }
          If Numeric = True then   { End of the reading, in case there's already a valid series of digits }
          begin
            {Last := i-1;}              { ex.: -1.20----; -.20--- }
            If i > 1 then
            begin
              If (S[i-1] = 'E') or (S[i-1] = 'e') then
                str_acm := str_acm + chln
              Else begin
                Last := i-1;
              end;
            end;
          end
          Else begin               { A mixture of various characters without numeric logic}
            str_acm := '';         { So start over the reading }
            Sign := False;         { ex.: -.--- }
          end;
        end;
      end;
      If (chln in ['.',',']) then
      begin
        If (DeciSep = False) then        { Decimal Separators can only be added once }
        begin
          str_acm := str_acm + DecimalSeparator;
          DeciSep := True;
        end
        { If a Decimal Separator was already accounted, a second one will mean two things }
        Else begin
          If Numeric = True then   { End of the reading, in case there's already a valid series of digits }
            Last := i-1              { ex.: -1.20...; -0.20. }
          Else begin               { A mixture of various characters without numeric logic }
            str_acm := '';         { So start over the reading }
            DeciSep := False;      { ex.: -... }
          end;
        end;
      end;

      If (chln in ['0'..'9']) then
      begin
        Numeric := True;            { Numbers can be added after any other characters, be it Sign and/or Decimal Separator }
        str_acm := str_acm + chln;  { Ex.: -1; -2.1; -.1; -1. }
      end;

      If (chln = 'E') or (chln = 'e') then
      begin
        If Exponent = False then
        begin
          If Numeric = True then    { E for the power of 10 can only be added once and after a series of digits }
          begin                     { Ex.: 1.0E10; -.0E2; -4.E3 }
            str_acm := str_acm + chln;
            Exponent := True;
          end
          Else begin                { The abscense of a previous series of digits does not allow the insertion of E }
            str_acm := '';          { E cannot start a floating point number and cannot succeed a sign or }
          end;                      { decimal separator if there isn't any previous number }
        end                         { Ex.: -.E; .E; -E; E }
        Else begin
          Last := i-1;              { E cannot appear twice. A second one means the end of the reading }
        end;
      end;

      If chln = '+' then            { Plus (+) sign will only be registered after a valid exponential E character }
      begin
        If (i > 1) and (Exponent = True) then
        begin
          If (S[i-1] = 'E') or (S[i-1] = 'e') then
            str_acm := str_acm + chln
          Else begin                
            Last := i-1;            { If it's added after anything other than E, the reading ends }
          end;
        end;
        If Exponent = False then
        begin
          If (Numeric = True) then
          begin
            Last := i-1;            { If it's added after anything other than E, the reading ends }
          end
          Else begin
            str_acm := '';          { If it's added after anything other than E, and if there isn't any }
            Exponent := False;      { valid series of digits, the reading restarts }
          end;
        end;
      end;

      { If any character except the ones from the Floating Point System are added }
      If not (chln in ['0'..'9','-','+',',','.','E','e']) then
      begin
        { After an already accounted valid series of digits }
        If (str_acm <> '') then
        begin
          If (Numeric = True) then
            Last := i-1             { End of the reading. Ex.: -1.20A; -.20%; 120# }
          Else begin
            str_acm := '';
            Sign := False;  DeciSep := False;  Exponent := False;
          end;
        end;
      end;
    end;
    //ShowMessage('i = '+IntToStr(i)+#13+str_acm+'P');
  end;
  until((Last <> -1) or (i = Lstr));

  If (i = Lstr) and (Numeric = True) then
    Last := i;

  { The Loop does not filter the case when no number is inserted after E, E- or E+ }
  { So it's necessary to check and remove if E,E-,E+,e,e-,e+ are the last characters }
  If Last <> -1 then
  begin
    Lstr := length(str_acm);
    If (str_acm[Lstr] = '+') or (str_acm[Lstr] = '-') then
    begin
      SetLength(str_acm,Lstr-1);
      Last := Last - 1;
    end;

    Lstr := length(str_acm);
    If (str_acm[Lstr] = 'E') or (str_acm[Lstr] = 'e') then
    begin
      SetLength(str_acm,Lstr-1);
      Last := Last - 1;
    end;

    Result := str_acm;
  end
  Else Result := '';
end;  { ExtractFloatStr }

EDIT 2.: Another function using the previous one to read a series of numbers in the same string.

var
  TFloatType = real;
  TVetorN = array of TFloatType;

procedure ExtractFloatVectorStr(Str : string; var N : integer; var FloatVector : TVetorN);
var                                     { Extract floating point numbers from string reading from left to right }
  i, j, k, Lstr, Lstr1 : integer;       { Register the numbers in FloatVector as the type TVetorN }
  char1 : char;                         { Register the amount of numbers found as the integer N }
  str_acm : string;
begin
  Str := AdjustLineBreaks(Str,tlbsCRLF);
  Lstr := length(Str);
  Lstr1 := 0;
  char1 := #0;

  i := 1; j := 0; k := 0; str_acm := '';
  SetLength(FloatVector,j+1);
  repeat
  begin
    If (i <= Lstr) then
    begin
      str_acm := ExtractFloatStr(i, Str, k);
      Lstr1 := length(str_acm);
      If (Lstr1 > 0) and (str_acm <> '') then
      begin
        j := j + 1;
        SetLength(FloatVector,j+1);
        FloatVector[j] := StrToFloat(str_acm);
        i := k + 1;
      end
      Else i := i + 1;
    end;
  end;
  until(i > Lstr);
  N := j;
end;  { ExtractFloatVectorStr }

Лучший ответ

Сергей Барановский

Мудрец

(13991)


14 лет назад

var
i : integer;
s, n : string;
begin
s := ‘http://otvet.mail.ru/question/23628746/’;
n := ”;
for i := 1 to Length(s) do if s[ i ] in [‘0’..’9′] then n := n + s[ i ];
end;
——————————-
Вышеприведенный код фильтрует строку, оставляя только цифры.
Если цифровых последовательностей несколько или нужно цифры подряд, то нужно парсить.

Остальные ответы

Новоясеневский Маньяк

Мудрец

(14903)


14 лет назад

Согласен.

ПсевдонимМыслитель (7836)

14 лет назад

))) скажи как это сделать?

Максим Мальков

Просветленный

(49111)


14 лет назад

StrToInt

Infernal Rain

Гений

(65997)


14 лет назад

Если у Вас число представленно в виде строки и имеет тип строки, то перевести в число можно командой StrToInt.

Если же Вам из всей строки необходимо выцепить лишь числовое значение, то в голову приходит мысль о посимвольном сравнении каждого элемента строки с числовым рядом и ели совпадение найдено, то брать этот элемент как число.

Богомолов Олег

Мыслитель

(5009)


14 лет назад

Ключевое слово: парсер.

 
guest
 
(2003-02-06 11:27)
[0]

Есть, допустим, Edi1. Нужно, чтобы пользователь вводил только цифры. Я пробовал так:

function isDigit:boolean;

var

i:integer;

a:array [0..9] of integer;

begin

result:=false;

for i:=1 to length(Edit1.Text) do

begin

if Edit1.Text[i] in a then result:=true;

end;

end;

но компилятор ругается, что делать?


 
Reindeer Moss Eater
 
(2003-02-06 11:30)
[1]

if Edit1.Text[i] in [“0”..”9″] then …


 
Наталия
 
(2003-02-06 11:30)
[2]

procedure TfMain.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

case ord(key) of

44,48..57,7,127,8: ;

13: SelectNext(Sender as TWincontrol,true,true);

else

key:=chr(7);

end;

end;


 
Anatoly Podgoretsky
 
(2003-02-06 11:36)
[3]

Потому ругается что оператор in не применим к массивам.


 
Романов Р.В.
 
(2003-02-06 11:46)
[4]

procedure TForm1.FormCreate(Sender: TObject);

begin

SetWindowLong(Edit1.Handle, GWL_STYLE, GetWindowLong(Edit1.Handle, GWL_STYLE) or ES_NUMBER);

end;


 
Андрей Сенченко
 
(2003-02-06 11:48)
[5]

TMaskEdit для ввода не подойдет ?


 
Юрий Зотов
 
(2003-02-06 11:54)
[6]

А еще лучше один раз выставить Edit”у стиль ES_NUMBER и более ни о чем не беспокоиться и ничего не проверять.

См. Get/SetWindowLong и список стилей в CreateWindow.


 
Reindeer Moss Eater
 
(2003-02-06 12:04)
[7]

Причины для беспокойства все равно будут.

SetLength(MyString,2000000000000);

FillChar(MyString[1],2000000000000,39); //В строке одни “девятки”

StrToInt(MyString);


 
Юрий Зотов
 
(2003-02-06 12:11)
[8]

> Reindeer Moss Eater (06.02.03 12:04)

1. 39 – это не девятка, а апостроф. Именно поэтому StrToInt даст ошибку, а вовсе не из-за сумасшедщей длины (если Вы это имели в виду).

2. Какое отношение все это имеет к юзерскому вводу в Edit?


 
Nikolai_S
 
(2003-02-06 12:15)
[9]

Лучше комбинировать 2 варианта:

1. Сначала на событие OnKeyPress вставить запрет ввода ненужных символов:

procedure GetIntChar(var Key: char; AllowNegative: boolean);

var

Digits: set of char;

begin

Digits := [#8, “0”..”9″];

if AllowNegative then Digits := Digits + [“-“];

if not (Key in Digits) then Key := #0;

end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);

begin

GetIntChar(Key, False);

end;

Здесь #8 включен для того, чтобы разрешалось нажатие клавиши BackSpace.

2. Затем нужно все равно проверить значение, т.к. в Edit могут вставить текст из буфера обмена или ввести слишком много цифр и т.д.:

function CheckInt(s: string): boolean;

begin

try

StrToInt(s);

Result := True;

except

Result := False;

end;

end;

——————-

Все это приведено для целых чисел (с учетом положительных, отрицательных). Можно усложнить под конкрентую задачу. Например допускать ввод вещественных чисел и т.д.


 
Vovchik_A
 
(2003-02-06 12:34)
[10]



var

i, code : integer

begin

Val(edit1.text,i, code);

if Code<>0 then ShowMessage("Ошибка в позиции "+IntToStr(Code));

end;



 
Vovchik_A
 
(2003-02-06 12:36)
[11]

Вдогонку… Пардоне, не внимательно прочитал условие. Так можно проверить есть ли не цифры в строке


 
Sha
 
(2003-02-06 12:45)
[12]

Попробую тоже предложить свой вариант, на мой взгляд достаточно универсальный.

Позволяем пользователю вводить все, что угодно.

Но по OnChange каждый раз проверяем, допустимо ли значение Text. Если нет – подсвечиваем его красным.

В OnKeyPress и OnKeyDown кроме цифр и BkSp, для чисел я обычно разрешаю точку и запятую, для дат точку, минус и слеш, подменяя их на установленные в системе разделители.

Минус и плюс для чисел стараюсь не разрешать – источник ошибок пользователя.


 
Nikolai_S
 
(2003-02-06 12:56)
[13]

2 Sha © (06.02.03 12:45)

А как подсветить в TEdit отдельные символы красным. Или подсвечивается весь текст?


 
Sha
 
(2003-02-06 13:30)
[14]

2 Nikolai_S © (06.02.03 12:56)

Весь. Но он подсветится в момент ввода пользователем неверного символа, и благодаря такой моментальной обратной связи, пользователь сразу в процессе ввода исправляет ВСЕ возможные ошибки.


 
Nikolai_S
 
(2003-02-06 14:29)
[15]

Пожалуй, это неплохая идея…


 
Roma
 
(2003-02-06 15:28)
[16]

Вот еще один вариант проверки:



function StrIsNumber(const S: string): Boolean;

{ Функция проверки, является ли строковый параметр S числом. }

var

Code: Integer;

V: Double; // или Integer, если нужно пропускать только целые

begin

{$rangechecks on}

Val(S, V, Code);

{$rangechecks off}

Result := Code = 0;

end; // function StrIsNumber(const S: string): Boolean;


 
Roma
 
(2003-02-06 15:31)
[17]

Ах да, это ж уже было – Vovchik_A (06.02.03 12:34)

Сорри…


 
Vovchik_A
 
(2003-02-06 16:31)
[18]

Ничего-ничего, я и не претендовал 🙂


 
Вованчик
 
(2003-02-06 16:58)
[19]

советую вставить в обработчик OnKeyPress

if not (key in ["0".."9", #8]) then key := #27;

#8 – чтобы можно было стирать символы

и все работает просто замечательно


30 января 2017

Для работы со строками в последних версиях Delphi разработчикам доступно большое количество функций, помимо которых ещё есть помощники для работы со строками, такие как TStringHelper, TStringBuilder и TRegEx. Во всём этом разнообразии бывает сложно найти нужную функцию. Я попытался разобраться, что есть в Delphi 10.1 Berlin для работы со строками и как этим всем пользоваться.

Итак, прежде чем начнём разбираться с функциями, замечу, что начиная с Delphi XE3, появился помощник TStringHelper, и теперь работать со строками можно как с записями. Т.е., если вы определили переменную со строкой (на картинке снизу – это myStr), то вы можете поставить точку и посмотреть, какие функции доступны. Это очень удобно.

Кстати аналогичные помощники появились и для работы с типами Single, Double и Extended: TSingleHelper, TDoubleHelper и TExtendedHelper.

Ну и конечно, помимо помощника TStringHelper, никуда не делся класс TStringBuilder, который используется для работы со строкой как с массивом, и который является полностью совместимым с .NET классом StringBuilder.

А для работы с текстовыми документами незаменимым окажется класс TRegEx, который является обёрткой над библиотекой PCRE, позволяющий использовать регулярные выражения для поиска, замены подстрок и расщепления текста на части.

Все приведённые в статье примеры сделаны с помощью Delphi 10.1 Berlin, поэтому в других версиях Delphi их работа не гарантируется.

Вот основные моменты, которые мы рассмотрим в статье:

  • Инициализация строк
  • Изменение регистра
  • Конкатенация строк
  • Вставка подстроки в строку
  • Удаление части строки
  • Копирование части строки
  • Сравнение строк
  • Поиск подстроки в строке
  • Поиск символов в строке
  • Замена подстроки в строке
  • Обрезка пробелов и управляющих символов
  • Выравнивание текста за счёт установки пробелов

Содержимое

  • 1 Строки в Delphi
  • 2 Инициализация строк
  • 3 Изменение регистра
  • 4 Конкатенация строк
  • 5 Вставка подстроки в строку
  • 6 Удаление части строки
  • 7 Копирование части строки
  • 8 Сравнение строк
  • 9 Поиск подстроки в строке
  • 10 Поиск символов в строке
  • 11 Замена подстроки в строке
  • 12 Обрезка пробелов и управляющих символов
  • 13 Выравнивание текста за счёт установки пробелов
  • 14 Вместо заключения

Строки в Delphi

В последних версиях Delphi тип string, обозначающий строку, является псевдонимом встроенного типа System.UnicodeString. Т.е. когда вы объявляете переменную str: string, то автоматически вы объявляете переменную типа UnicodeString.

Кстати, на платформе Win32 вы можете использовать директиву «{$H-}», которая превратит тип string в ShortString. С помощью этого способа вы можете использовать старый 16-битный код Delphi или Turbo Pascal в ваших проектах.

Обратите внимание, что кроме типа UnicodeString и ShortString в Delphi есть и другие типы строк, такие как AnsiString и WideString, однако дальше в статье мы будем рассматривать только работу со строками типа string.

Более глубокое изучение строк в Delphi вы можете начать с прочтения документации здесь.

Инициализация строк

Конечно, начнём мы с инициализации строк. Итак, рассмотрим объявление переменной с типом string.

В этой строчке кода мы объявляем переменную s с типом string, т.е., как было написано выше, по умолчанию с типом UnicodeString. Объявленные переменные с типом UnicodeString, в которые не присвоено значение, всегда гарантированно содержат строку нулевой длины. Чтобы теперь в переменной s была нужная нам строка, нужно просто присвоить переменной другое значение, например:

Это самый простой и часто используемый способ инициализации. Кроме этого есть ряд полезных функций, которые пригодятся вам для инициализации строк в некоторых ситуациях (здесь и далее я буду давать полный код проекта консольного Win32 приложения):

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils;

var

    str1, str2, str3, str4, str5, str6: string;

    arr4: array of char;

begin

    try

        //Способ 1: инициализируем строку повторяющимися символами.

        //В результате в str1 будет строка “ААААА”.

        str1 := StringOfChar(‘А’, 5);

        //Способ 2: инициализируем строку повторяющимися символами.

        //В результате в str2 будет строка “ААААА”.

        str2 := string.Create(‘А’, 5);

        //Способ 3: инициализируем строку повторяющимися подстроками.

        //В результате в str3 будет строка “ХаХаХаХаХа”.

        str3 := DupeString(‘Ха’, 5);

        //Способ 4: инициализируем строку символами из массива.

        //В результате в str4 будет строка “Абвгд”

        arr4 := [‘А’, ‘б’, ‘в’, ‘г’, ‘д’];

        str4 := string(arr4);

        //Способ 5: инициализируем строку символами из массива.

        //В результате в str5 будет строка “Абвгд”

        str5 := string.Create([‘А’, ‘б’, ‘в’, ‘г’, ‘д’]);

        //Способ 6: инициализируем строку символами из массива (берём только часть символов).

        //В результате в str6 будет строка “бвг”

        str6 := string.Create([‘А’, ‘б’, ‘в’, ‘г’, ‘д’], 1, 3);

        //Отображаем результат.

        Writeln(str1);

        Writeln(str2);

        Writeln(str3);

        Writeln(str4);

        Writeln(str5);

        Writeln(str6);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Изменение регистра

Для изменения регистра строк в Delphi есть функции LowerCaseUpperCaseTStringHelper.ToLowerTStringHelper.ToUpper, TStringHelper.ToLowerInvariant и TStringHelper.ToUpperInvariant. В нижний регистр строки меняют функции LowerCase, TStringHelper.ToLower и TStringHelper.ToLowerInvariant, остальные – в верхний. Обратите внимание, что функции LowerCase и UpperCase не работают с кириллицей. Функции TStringHelper.ToUpperInvariant и TStringHelper.ToLowerInvariant всегда работают независимо от текущей пользовательской локали. Вот примеры использования функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

begin

    try

        //В нижний регистр меняются только латинские буквы. Результат будет ‘АбВгД – abcde’.

        Writeln(LowerCase(‘АбВгД – AbCdE’));

        //В верхний регистр меняются только латинские буквы. Результат будет ‘АбВгД – ABCDE’.

        Writeln(UpperCase(‘АбВгД – AbCdE’));

        //В нижний регистр меняются и русские и латинские буквы. Результат будет ‘абвгд – abcde’.

        Writeln(‘АбВгД – AbCdE’.ToLower);

        //В верхний регистр меняются и русские и латинские буквы. Результат будет ‘АБВГД – ABCDE’.

        Writeln(‘АбВгД – AbCdE’.ToUpper);

        //Указываем локаль при изменении регистра. Результат будет ‘АБВГД – ABCDE’.

        Writeln(‘АбВгД – AbCdE’.ToUpper(TLanguages.GetLocaleIDFromLocaleName(‘ru-RU’)));

        //В нижний регистр меняются и русские и латинские буквы. Результат будет ‘абвгд – abcde’.

        Writeln(‘АбВгД – AbCdE’.ToLowerInvariant);

        //В верхний регистр меняются и русские и латинские буквы. Результат будет ‘АБВГД – ABCDE’.

        Writeln(‘АбВгД – AbCdE’.ToUpperInvariant);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Конкатенация строк

Здесь конечно самый простой вариант – это использование оператора +. Но есть и другие варианты, например, функция Concat. А если вам нужно в цикле добавлять в конец одной строки большое количество других строк, то здесь пригодится метод Append класса TStringBuilder. Вот пример использования перечисленных способов:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

var

    str1, str2, str3, str4: string;

    stringBuilder: TStringBuilder;

begin

    try

        //Способ 1: используем оператор +.

        str1 := ‘Абвг’ + ‘деёжз’ + ‘иклмн’ + ‘опрст’;

        // Способ 2: используем функцию Concat.

        str2 := Concat(‘Абвг’, ‘деёжз’, ‘иклмн’, ‘опрст’);

        // Способ 3: используем функцию TStringHelper.Join.

        str3 := String.Join(, [‘Абвг’, ‘деёжз’, ‘иклмн’, ‘опрст’]);

        // Способ 4: используем TStringBuilder.

        // Способ 4: используем TStringBuilder.

        stringBuilder := TStringBuilder.Create;

        try

            stringBuilder

                .Append(‘Абвг’)

                .Append(‘деёжз’)

                .Append(‘иклмн’)

                .Append(‘опрст’);

            str4 := stringBuilder.ToString;

        finally

            stringBuilder.Free;

        end;

        //Отображаем результат.

        Writeln(str1);

        Writeln(str2);

        Writeln(str3);

        Writeln(str4);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Во всех четырёх переменных, после выполнения нашей программы, будет следующая строка: «Абвгдеёжзиклмнопрст». Четвёртый способ выглядит более громоздким, но у такого способа есть три преимущества. Во-первых, при большом количестве конкатенаций этот способ даст выигрыш по времени по сравнению с первыми тремя способами. Во-вторых, при создании объекта TStringBuilder вы сразу можете задать нужный размер массива для хранения строки, если он конечно известен. Это тоже даст выигрыш по времени. В-третьих, функция Append принимает на вход не только строки, но и другие типы, такие как Integer и Single, автоматически преобразуя их в строку.

Третий способ удобно использовать, если нужно сложить строки, находящиеся в массиве или списке. К тому же здесь первым параметром можно задать строку-разделитель, которая будет вставлена между строками, взятыми из массива. Вот пример, в котором формируется строка со списком городов, разделённых запятыми:

str3 := String.Join(‘, ‘, [‘Москва’, ‘Санкт-Петербург’, ‘Севастополь’]);

В результате выполнения этой функции получится строка «Москва, Санкт-Петербург, Севастополь».

Вставка подстроки в строку

Для того чтобы вставить внутрь строки подстроку вы можете использовать процедуру Insert или функцию TStringHelper.Insert. У класса TStringBuilder тоже есть аналогичная функция. Кстати, функция TStringBuilder.Insert, кроме строк умеет вставлять и другие типы, такие как Integer и Single, автоматически преобразуя их в строку. Вот пример использования:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

var

    str1, str2: string;

    stringBuilder: TStringBuilder;

begin

    try

        //В результате вставки получится строка ‘Абв–гд’

        str1 := ‘Абвгд’;

        Insert(‘–‘, str1, 4);

        Writeln(str1);

        //В результате вставки получится строка ‘Абв–гд’

        str2 := ‘Абвгд’;

        Writeln(str2.Insert(3, ‘–‘)); //Будет отображено ‘Абв–гд’.

        Writeln(str2); //Здесь тоже будет отображено ‘Абв–гд’.

        //В результате вставки получится строка ‘Абв–гд’

        stringBuilder := TStringBuilder.Create(‘Абвгд’);

        try

            stringBuilder.Insert(3, ‘–‘);

            Writeln(stringBuilder.ToString);

        finally

            stringBuilder.Free;

        end;

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Обратите внимание, в процедуре Insert нумерация символов начинается с 1, а в функциях TStringHelper.Insert и TStringBuilder.Insert – с 0. Все приведённые способы меняют строку, хранящуюся в переменной.

Удаление части строки

Допустим, вам нужно удалить из строки часть символов. Здесь нам помогут процедура Delete и функция TStringHelper.Remove. У класса TStringBuilder тоже есть функция Remove. Вот примеры использования:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

var

    str1, str2, str3: string;

    stringBuilder: TStringBuilder;

begin

    try

        //Способ 1: используем функцию Delete.

        str1 := ‘Абвгд’;

        Delete(str1, 2, 2);

        //Способ 2: используем функцию TStringHelper.Remove.

        str2 := ‘Абвгд’;

        str2 := str2.Remove(1, 2);

        //Способ 3: удаляем символы внутри TStringBuilder.

        stringBuilder := TStringBuilder.Create(‘Абвгд’);

        try

            stringBuilder.Remove(1, 2);

            str3 := stringBuilder.ToString;

        finally

            stringBuilder.Free;

        end;

        //Отображаем результат.

        Writeln(str1);

        Writeln(str2);

        Writeln(str3);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Во всех трёх способах из строки «Абвгд» получится строка «Агд». Обратите внимание, что в процедуре Delete нумерация символов начинается с 1, а в функциях Remove – с 0.

Также интересно, что функция TStringHelper.Remove не трогает исходную строку. Вместо этого она возвращает новую строку с удалёнными символами. Именно поэтому мы присваиваем результат обратно в переменную. Процедура Delete работает по-другому: она меняет исходную строку.

Помимо приведённых здесь вариантов, для удаления части строки можно использовать функции замены подстроки, просто для этого искомая подстрока заменяется на пустую, например, StringReplace(str1, substr1, »).

Копирование части строки

Здесь идёт речь о том, что часть длиной строки нужно скопировать в новую строку или массив символов. Для этого в Delphi есть функции LeftStrRightStrCopyTStringHelper.Substring и TStringHelper.CopyTo. А в классе TStringBuilder – только функция CopyTo. Есть также функция MidStr в юните System.StrUtils, которая работает аналогично функции Copy, поэтому в примере её не будет.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils;

var

    str1, str2, str3, str4: string;

    arr5: array of char;

    arr6: TCharArray;

    stringBuilder: TStringBuilder;

begin

    try

        //Способ 1: копируем три символа слева.

        //В результате в строке str2 будет “Абв”.

        str1 := LeftStr(‘Абвгдеёжз’, 3);

        //Способ 2: копируем три символа справа.

        //В результате в строке str3 будет “ёжз”.

        str2 := RightStr(‘Абвгдеёжз’, 3);

        //Способ 3: копируем символы из середины.

        //В результате в строке str1 будет “вгд”.

        str3 := Copy(‘Абвгдеёжз’, 3, 3);

        //Способ 4: копируем символы из середины.

        //В результате в строке str4 будет “вгд”.

        str4 := ‘Абвгдеёжз’.Substring(2, 3);

        //Способ 5: копируем часть строки в массив символов.

        //В результате в массиве arr5 будет [‘в’, ‘г’, ‘д’].

        SetLength(arr5, 3);

        ‘Абвгдеёжз’.CopyTo(2, arr5, 0, 3);

        //Способ 6: копируем часть символов из TStringBuilder в массив символов.

        //В результате в массиве arr6 будет [‘в’, ‘г’, ‘д’].

        stringBuilder := TStringBuilder.Create(‘Абвгдеёжз’);

        try

            SetLength(arr6, 3);

            stringBuilder.CopyTo(2, arr6, 0, 3);

        finally

            stringBuilder.Free;

        end;

        //Отображаем результат.

        Writeln(str1);

        Writeln(str2);

        Writeln(str3);

        Writeln(str4);

        Writeln(string(arr5));

        Writeln(string(arr6));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Первые два способа копируют часть строки слева (функция LeftStr) или справа (RightStr). Остальные четыре способа подходят, как для копирования части строки слева или справа, так и из середины.

В способах 3-6 из примера мы получим сроку «вгд» или массив [‘в’, ‘г’, ‘д’]. Обратите внимание, что в функциях Copy и MidStr нумерация символов начинается с 1, а во всех остальных с 0. Исходная строка или массив символов во всех четырёх способах не меняется.

Сравнение строк

Конечно, сравнивать строки можно с помощью операторов =<<=>>= и <>. Но кроме этого существуют ещё много функций: StrCompStrIComp, StrLComp, StrLIComp, CompareStr, CompareText, TStringHelper.CompareTStringHelper.CompareOrdinalTStringHelper.CompareToTStringHelper.CompareTextSameStr, SameText, TStringHelper.Equals и TStringBuilder.Equals. Функции SameText, StrIComp, CompareText, TStringHelper.CompareText и TStringHelper.Compare умеют производить регистронезависимое сравнение строк, остальные функции и операторы — регистрозависимое.

Третьим параметром в функциях CompareText и SameText можно указать, что нужно использовать для сравнения строк пользовательскую локаль. В этом случае вы сможете сравнивать строки с русскими буквами независимо от регистра, если конечно в ОС используется русский язык.

Самая продвинутая здесь функция – это TStringHelper.Compare. С помощью неё можно сравнивать не только целые строки, но и части строк. Здесь можно настроить зависимость от регистра, включить игнорирование символов и знаков препинания или сравнение цифр как чисел и т.д.

Операторы, а также функции TStringHelper.Equals и TStringBuilder.Equals, в результате сравнения, отдадут вам True, если условие верно, и False, если условие не верно. Функции CompareStr, CompareText, TStringHelper.Compare, TStringHelper.CompareTo, TStringHelper.CompareOrdinal и TStringHelper.CompareText работают по-другому. Они сравнивают строки с точки зрения сортировки. Функции возвращают отрицательное число, если строка, указанная в первом параметре, сортируется до строки, указанной во втором параметре, положительное число — если первая строка сортируется после второй и 0 – если строки равны.

Функции SameStr, SameText, TStringHelper.Equals и TStringBuilder.Equals сравнивают строки на соответствие.

Итак, вот примеры использования вышеперечисленных функций и операторов:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils, Winapi.Windows;

var

    stringBuilder1, stringBuilder2: TStringBuilder;

begin

    try

        //Сравнение строк с помощью операторов (регистрозависимое).

        //В результате будет TRUE (т.е. строка 1 сортируется до строки 2).

        Writeln(‘Арбуз’ < ‘Банан’);

        //В результате будет TRUE (т.е. строка 1 сортируется после строки 2).

        Writeln(‘Арбуз’ > ‘Арбалет’);

        //В результате будет TRUE (т.е. строка 1 сортируется до строки 2 или строки равны).

        Writeln(‘Арбуз’ <= ‘арбуз’);

        //В результате будет FALSE (т.е. строки не равны).

        Writeln(‘Арбуз’ = ‘арбуз’);

        //Сравнение с помощью регистрозависимых функций.

        //Результат будет FALSE.

        Writeln(‘Арбуз’.Equals(‘арбуз’));

        //Результат будет TRUE.

        Writeln(‘Банан’.Equals(‘Банан’));

        //Результат будет FALSE.

        Writeln(SameStr(‘Арбуз’, ‘арбуз’));

        //Результат будет TRUE.

        Writeln(SameStr(‘Банан’, ‘Банан’));

        //Результат будет -1 (т.е. строка 1 сортируется до строки 2).

        Writeln(string.CompareOrdinal(‘Арбуз’, ‘Банан’));

        //Результат будет -1 (т.е. строка 1 сортируется до строки 2).

        Writeln(StrComp(‘Арбуз’, ‘Банан’));

        //Сравниваем только первые 2 символа. Результат будет -1 (т.е. строка 1 сортируется до строки 2).

        Writeln(StrLComp(‘Арбуз’, ‘Банан’, 2));

        //Результат будет -1 (т.е. строка 1 сортируется до строки 2).

        Writeln(‘Арбуз’.CompareTo(‘Банан’));

        //Результат будет 19 (т.е. строка 1 сортируется после строки 2).

        Writeln(‘Арбуз’.CompareTo(‘Арбалет’));

        //Результат будет -1 (т.е. строка 1 сортируется до строки 2).

        Writeln(CompareStr(‘Арбуз’, ‘Банан’));

        //Результат будет 19 (т.е. строка 1 сортируется после строки 2).

        Writeln(CompareStr(‘Арбуз’, ‘Арбалет’));

        //Сравнение с помощью регистроНЕзависимых функций (работает только для латинских букв).

        //Результат будет FALSE.

        Writeln(SameText(‘Арбуз’, ‘арбуз’));

        //Результат будет -32 (т.е. строка 1 сортируется до строки 2).

        Writeln(StrIComp(‘Арбуз’, ‘арбуз’));

        //Сравниваем только первые 2 символа. Результат будет -32 (т.е. строка 1 сортируется до строки 2).

        Writeln(StrLIComp(‘Арбуз’, ‘арбуз’, 2));

        //Результат будет -32 (т.е. строка 1 сортируется до строки 2).

        Writeln(CompareText(‘Арбуз’, ‘арбуз’));

        //Результат будет -32 (т.е. строка 1 сортируется до строки 2).

        Writeln(string.CompareText(‘Арбуз’, ‘арбуз’));

        //Результат будет 0 (т.е. строки 1 и 2 равны).

        Writeln(string.CompareText(‘Watermelon’, ‘watermelon’));

        //Результат будет 0 (т.е. строки 1 и 2 равны).

        Writeln(StrIComp(‘Watermelon’, ‘watermelon’));

        //Сравниваем только первые 2 символа. Результат будет 0 (т.е. строки 1 и 2 равны).

        Writeln(StrLIComp(‘Watermelon’, ‘watermelon’, 2));

        //Результат будет 0 (т.е. строки 1 и 2 равны).

        Writeln(CompareText(‘Watermelon’, ‘watermelon’));

        //Сравнение с помощью регистроНЕзависимых функций (использование пользовательской локали).

        //Результат будет TRUE.

        Writeln(SameText(‘Арбуз’, ‘арбуз’, TLocaleOptions.loUserLocale));

        //Результат будет 0 (т.е. строки 1 и 2 равны).

        Writeln(CompareText(‘Арбуз’, ‘арбуз’, TLocaleOptions.loUserLocale));

        //Сравнение с помощью функции TStringHelper.Compare.

        //Регистрозависимое сравнение. В результате будет 1 (т.е. строка 1 сортируется после строки 2).

        Writeln(string.Compare(‘Арбуз’, ‘арбуз’));

        //РегистроНЕзависимое сравнение. В результате будет 0 (т.е. строки 1 и 2 одинаковые).

        Writeln(string.Compare(‘Арбуз’, ‘арбуз’, true));

        //РегистроНЕзависимое сравнение с игнорированием символов и знаков препинания.

        //В результате будет 0 (т.е. строки 1 и 2 одинаковые).

        Writeln(string.Compare(‘Арбуз!’, ‘-арбуз’,

                [TCompareOption.coIgnoreSymbols, TCompareOption.coIgnoreCase]));

        //Сравнение цифр как чисел, а не как строки.

        //В результате будет -1 (т.е. первое число меньше чем второе).

        Writeln(string.Compare(‘2’, ’10’, [TCompareOption.coDigitAsNumbers]));

        //Сравнение цифр как строки.

        //В результате будет 1 (т.е. строка 1 сортируется после строки 2).

        Writeln(string.Compare(‘2’, ’10’));

        //РегистроНЕзависимое сравнение с определённым языком и регионом. В результате будет 0 (т.е. строки 1 и 2 одинаковые).

        Writeln(string.Compare(‘Арбуз’, ‘арбуз’, true, TLanguages.GetLocaleIDFromLocaleName(‘ru-RU’)));

        //Сравнение двух строк в двух экземплярах класса TStringBuilder (регистрозависимое).

        stringBuilder1 := TStringBuilder.Create(‘Арбуз’);

        try

            stringBuilder2 := TStringBuilder.Create(‘арбуз’);

            try

                //Результат будет FALSE.

                Writeln(stringBuilder1.Equals(stringBuilder2));

                //Результат будет TRUE.

                stringBuilder2.Clear;

                stringBuilder2.Append(‘Арбуз’);

                Writeln(stringBuilder1.Equals(stringBuilder2));

            finally

                stringBuilder2.Free;

            end;

        finally

            stringBuilder1.Free;

        end;

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Поиск подстроки в строке

Теперь давайте посмотрим, как можно найти подстроку (определённую последовательность символов) в строке. Здесь у вас есть большой выбор функций, которые возвращают либо индекс найденной подстроки, либо true или false в зависимости от того, найдена подстрока в строке или нет. Итак, давайте перечислим все функции для поиска подстроки:

В первую очередь – это функция Pos, которая ищет подстроку, начиная с указанного номера символа. Функция осуществляет регистрозависимый поиск. Здесь нумерация символов начинается с 1. Если подстрока найдена, то возвращается номер первого символа найденной подстроки, иначе – 0. Есть также функция PosEx (в юните System.StrUtils), которая работает абсолютно также. Вот пример использования функции Pos:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

begin

    try

        //Поиск с первого символа. В результате отобразится 8.

        Writeln(Pos(‘строка’, ‘Первая строка, вторая строка’, 1));

        //Поиск с десятого символа. В результате отобразится 23.

        Writeln(Pos(‘строка’, ‘Первая строка, вторая строка’, 10));

        //Поиск несуществующей подстроки. В результате отобразится 0.

        Writeln(Pos(‘третья’, ‘Первая строка, вторая строка’, 1));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Аналогично функции Pos работают и функции IndexOf и LastIndexOf помощника TStringHelper. Они также осуществляют регистрозависимый поиск. Функция IndexOf ищет подстроку (или символ) с начала и до конца строки, а функция LasIndexOf – наоборот, т.е. с конца и до начала. Если подстрока найдена, то функции возвращают индекс первого символа найденной подстроки в строке. Здесь нумерация символов начинается с 0. Если подстрока не найдена, то функции возвращают -1. Также при поиске вы можете задать начало и интервал поиска. Вот примеры использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

begin

    try

        //Поиск с начала строки. В результате отобразится 7.

        Writeln(‘Первая строка, вторая строка’.IndexOf(‘строка’));

        //Поиск с десятого символа до конца. В результате отобразится 22.

        Writeln(‘Первая строка, вторая строка’.IndexOf(‘строка’, 9));

        //Поиск несуществующей подстроки. В результате отобразится -1.

        Writeln(‘Первая строка, вторая строка’.IndexOf(‘третья’));

        //Поиск с начала только среди первых 10-ти символов. В результате отобразится -1.

        Writeln(‘Первая строка, вторая строка’.IndexOf(‘строка’, 0, 10));

        //Поиск с начала только среди первых 20-ти символов. В результате отобразится 7.

        Writeln(‘Первая строка, вторая строка’.IndexOf(‘строка’, 0, 20));

        //Поиск с конца строки. В результате отобразится 22.

        Writeln(‘Первая строка, вторая строка’.LastIndexOf(‘строка’));

        //Поиск с двадцать третьего символа и до начала. В результате отобразится 7.

        Writeln(‘Первая строка, вторая строка’.LastIndexOf(‘строка’, 22));

        //Поиск с конца только среди последних 10 символов. В результате отобразится -1.

        Writeln(‘Первая строка, вторая строка, третья’.LastIndexOf(‘строка’, 36, 10));

        //Поиск с конца только среди последних 20 символов. В результате отобразится 22.

        Writeln(‘Первая строка, вторая строка, третья’.LastIndexOf(‘строка’, 36, 20));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Теперь рассмотрим функции для проверки, есть ли подстрока в строке, и не важно, в каком месте. Для этого есть функции ContainsStr и ContainsText в юните System.StrUtils, а также функция Contains в помощнике TStringHelper.Contains. Функции ContainsStr и TStringHelper.Contains – регистрозависимые, а функция ContainsText – нет. Вот примеры использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils;

begin

    try

        //В результате отобразится TRUE.

        Writeln(ContainsStr(‘Раз, два, три, четыре, пять’, ‘Раз’));

        //В результате отобразится FALSE.

        Writeln(ContainsStr(‘Раз, два, три, четыре, пять’, ‘Два’));

        //В результате отобразится TRUE.

        Writeln(ContainsText(‘Раз, два, три, четыре, пять’, ‘Три’));

        //В результате отобразится TRUE.

        Writeln(‘Раз, два, три, четыре, пять’.Contains(‘четыре’));

        //В результате отобразится FALSE.

        Writeln(‘Раз, два, три, четыре, пять’.Contains(‘Пять’));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Дополнительно есть функции проверяющие, наличие определённой подстроки в начале или в конце текста. Это функции StartsStr, StartsText, EndsStr и EndsText в юните System.StrUtils, а также функции StartsWith, EndsWith и EndsText у помощника TStringHelper. Функции StartsStr и EndsStr регистрозависимые, функции StartsText, EndsText и TStringHelper.EndsText регистронезависимые, а у функций TStringHelper.StartsWith и TStringHelper.EndsWith есть второй параметр для выбора режима поиска. Учтите, что регистронезависимый поиск в функции TStringHelper.StartsWith работает только с буквами латинского алфавита. По умолчанию поиск в функциях TStringHelper.StartsWith и TStringHelper.EndsWith регистрозависимый.

Обратите внимание, что регистронезависимый поиск в функциях StartsText, EndsText и TStringHelper.EndsText и TStringHelper.EndsWith ведётся для текущей локали. Т.е. если на компьютере будет установлена английская локаль, то регистронезависимый поиск по русскому тексту работать не будет.

Вот примеры использования функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils;

begin

    try

        //Ищем подстроку в начале строки. Результат будет TRUE.

        Writeln(StartsStr(‘Раз’, ‘Раз, два, три’));

        //Ищем подстроку в начале строки. Результат будет FALSE.

        Writeln(StartsStr(‘раз’, ‘Раз, два, три’));

        //Ищем подстроку в начале строки. Результат будет FALSE.

        Writeln(StartsStr(‘два’, ‘Раз, два, три’));

        //Ищем подстроку в начале строки. Результат будет TRUE.

        Writeln(StartsText(‘Раз’, ‘Раз, два, три’));

        //Ищем подстроку в начале строки. Результат будет TRUE.

        Writeln(StartsText(‘раз’, ‘Раз, два, три’));

        //Ищем подстроку в начале строки. Результат будет FALSE.

        Writeln(StartsText(‘два’, ‘Раз, два, три’));

        //Ищем подстроку в начале строки. Результат будет TRUE.

        Writeln(‘Раз, два, три’.StartsWith(‘Раз’));

        //Ищем подстроку в начале строки. Результат будет FALSE.

        Writeln(‘Раз, два, три’.StartsWith(‘раз’));

        //Ищем подстроку в начале строки. Результат будет FALSE (для кириллицы).

        Writeln(‘Раз, два, три’.StartsWith(‘раз’, true));

        //Ищем подстроку в начале строки. Результат будет TRUE (для латиницы).

        Writeln(‘One, two, three’.StartsWith(‘one’, true));

        //Ищем подстроку в начале строки. Результат будет FALSE.

        Writeln(‘Раз, два, три’.StartsWith(‘два’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(EndsStr(‘три’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет FALSE.

        Writeln(EndsStr(‘Три’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет FALSE.

        Writeln(EndsStr(‘два’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(EndsText(‘три’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(EndsText(‘Три’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет FALSE.

        Writeln(EndsText(‘два’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(string.EndsText(‘три’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(string.EndsText(‘Три’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет FALSE.

        Writeln(string.EndsText(‘два’, ‘Раз, два, три’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(‘Раз, два, три’.EndsWith(‘три’));

        //Ищем подстроку в конце строки. Результат будет FALSE.

        Writeln(‘Раз, два, три’.EndsWith(‘Три’));

        //Ищем подстроку в конце строки. Результат будет TRUE.

        Writeln(‘Раз, два, три’.EndsWith(‘Три’, true));

        //Ищем подстроку в конце строки. Результат будет FALSE.

        Writeln(‘Раз, два, три’.EndsWith(‘два’));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

И конечно самые продвинутые условия для поиска подстрок можно задавать при помощи регулярных выражений. Для этого есть функции TRegEx.Match и TRegEx.Matches. Вот несколько примеров использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.RegularExpressions;

var

    regEx: TRegEx;

    match: TMatch;

    matches: TMatchCollection;

begin

    try

        //Ищем в строке любой IP-адрес, с начала строки.

        regEx := TRegEx.Create(‘bd{1,3}.d{1,3}.d{1,3}.d{1,3}b’);

        match := regEx.Match(‘В этой строке два IP-адреса 192.168.1.1 и 192.168.1.15’);

        //Найдена ли подстрока. Результат будет TRUE.

        Writeln(match.Success);

        //Номер первого символа найденной подстроки. Результат будет 29.

        Writeln(match.Index);

        //Длина найденной подстроки. Результат будет 11.

        Writeln(match.Length);

        //Найденная подстрока. Результат будет 192.168.1.1.

        Writeln(match.Value);

        //Ищем следующий IP-адрес в этой же строке.

        match := match.NextMatch;

        //Найдена ли следующая подстрока. Результат будет TRUE.

        Writeln(match.Success);

        //Номер первого символа найденной подстроки. Результат будет 43.

        Writeln(match.Index);

        //Длина найденной подстроки. Результат будет 12.

        Writeln(match.Length);

        //Найденная подстрока. Результат будет 192.168.1.15.

        Writeln(match.Value);

        //Ищем следующий IP-адрес в этой же строке.

        match := match.NextMatch;

        //Найдена ли следующая подстрока. Результат будет FALSE.

        Writeln(match.Success);

        //Ищем адреса почтовых ящиков в тексте, игнорируя регистр.

        regEx := TRegEx.Create(‘b[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,}b’, [roIgnoreCase]);

        matches := regEx.Matches(‘В этой test@example.com строке a.b-93@example.com содержатся три Proghouse@example.com почтовых адреса.’);

        //В результате будет выдано три адреса:

        //test@example.com

        //a.b-93@example.com

        //Proghouse@example.com

        for match in matches do

            Writeln(match.Value);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Примеры и описание регулярных выражений смотрите на сайте библиотеки PCRE.

Поиск символов в строке

Случается, что нужно найти определённые символы в строке. Конечно, для этого вы можете воспользоваться функциями для поиска подстроки, о которых было написано выше, но есть и специальные функции, позволяющие найти первый попавшийся в строке символ из нескольких искомых. Это функции помощника TStringHelper: IndexOfAny, IndexOfAnyUnquoted и LastIndexOfAny. Функции IndexOfAny и IndexOfAnyUnquoted ищут, перебирая символы сначала до конца строки, а функция LastIndexOfAny – наоборот. Во всех функциях можно указать интервал поиска. Функция IndexOfAnyUnquoted умеет игнорировать символы, заключенные в кавычки, скобки и т.п. Вот пример использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils, Winapi.Windows;

begin

    try

        //Ищем символ ‘р’ или ‘о’. В результате будет 2.

        Writeln(‘Это строка!’.IndexOfAny([‘р’, ‘о’]));

        //Ищем символ ‘р’ или ‘о’ начиная с пятого символа. В результате будет 6.

        Writeln(‘Это строка!’.IndexOfAny([‘р’, ‘о’], 4));

        //Ищем символ ‘р’ или ‘о’ с пятого по шестой символ. В результате будет -1.

        Writeln(‘Это строка!’.IndexOfAny([‘р’, ‘о’], 4, 2));

        //Ищем символ ‘р’ или ‘о’ с конца строки. В результате будет 7.

        Writeln(‘Это строка!’.LastIndexOfAny([‘р’, ‘о’]));

        //Ищем символ ‘р’ или ‘о’ начиная с пятого символа и до начала. В результате будет 2.

        Writeln(‘Это строка!’.LastIndexOfAny([‘р’, ‘о’], 4));

        //Ищем символ ‘р’ или ‘о’ с пятого по третий символ. В результате будет 2.

        Writeln(‘Это строка!’.LastIndexOfAny([‘р’, ‘о’], 4, 3));

        //Ищем символ ‘р’ или ‘о’, но не среди символов заключенных в кавычки. В результате будет 8.

        Writeln(‘”Это” строка!’.IndexOfAnyUnquoted([‘р’, ‘о’], ‘”‘, ‘”‘));

        //Ищем символ ‘р’ или ‘о’, но не среди символов заключенных в скобки, в том числе вложенных. В результате будет 17.

        Writeln(‘(Это (вторая)) строка!’.IndexOfAnyUnquoted([‘р’, ‘о’], ‘(‘, ‘)’));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Замена подстроки в строке

Для поиска и замены подстроки (или символа) в строке можно использовать функции StringReplace, ReplaceStr и ReplaceText, TStringHelper.ReplaceTStringBuilder.Replace и TRegEx.Replace. Функции ReplaceStr и TStringBuilder.Replace – регистрозависимые, функция ReplaceText – регистронезависимая, в функциях StringReplace, TStringHelper.Replace и TRegEx.Replace зависимость от регистра настраивается флажком rfIgnoreCase. Функции TRegEx.Replace ищут подстроку, используя регулярные выражения. В функции TStringBuilder.Replace можно задать диапазон поиска подстроки. Вот примеры использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils, System.StrUtils, System.RegularExpressions;

var

    stringBuilder: TStringBuilder;

    regEx: TRegEx;

begin

    try

        //Ищет все подстроки в строке и заменяет их на новые (регистрозависимый поиск).

        //В результате будет ‘Раз, два, три, два’.

        Writeln(ReplaceStr(‘Раз, четыре, три, четыре’, ‘четыре’, ‘два’));

        //Ищет все подстроки в строке и заменяет их на новые (регистрозависимый поиск).

        //В результате будет ‘Раз, Четыре, три, два’.

        Writeln(ReplaceStr(‘Раз, Четыре, три, четыре’, ‘четыре’, ‘два’));

        //Ищет все подстроки в строке и заменяет их на новые (регистронезависимый поиск).

        //В результате будет ‘Раз, два, три, два’.

        Writeln(ReplaceText(‘Раз, четыре, три, четыре’, ‘четыре’, ‘два’));

        //Ищет все подстроки в строке и заменяет их на новые (регистронезависимый поиск).

        //В результате будет ‘Раз, два, три, два’.

        Writeln(ReplaceText(‘Раз, Четыре, три, четыре’, ‘четыре’, ‘два’));

        //Ищет только первую подстроку в строке и заменяет её на новую.

        //В результате будет ‘Раз, два, три, четыре’.

        Writeln(StringReplace(‘Раз, четыре, три, четыре’, ‘четыре’, ‘два’, []));

        //Ищет все подстроки в строке и заменяет их на новые.

        //В результате будет ‘Раз, два, три, два’.

        Writeln(StringReplace(‘Раз, четыре, три, четыре’, ‘четыре’, ‘два’, [rfReplaceAll]));

        //Пример регистрозависимого поиска и замены подстрок.

        //В результате будет ‘Раз, Четыре, три, два’.

        Writeln(StringReplace(‘Раз, Четыре, три, четыре’, ‘четыре’, ‘два’, [rfReplaceAll]));

        //Пример регистронезависимого поиска и замены подстрок.

        //В результате будет ‘Раз, два, три, два’.

        Writeln(StringReplace(‘Раз, Четыре, три, четыре’, ‘четыре’, ‘два’, [rfReplaceAll, rfIgnoreCase]));

        //Ищет все подстроки в строке и заменяет их на новые

        //(т.к. по умолчанию установлен флаг rfReplaceAll).

        //В результате будет ‘Раз, два, три, два’.

        Writeln(‘Раз, четыре, три, четыре’.Replace(‘четыре’, ‘два’));

        //Ищет только первую подстроку в строке и заменяет её на новую

        //(т.к нет флага rfReplaceAll).

        //В результате будет ‘Раз, два, три, четыре’.

        Writeln(‘Раз, четыре, три, четыре’.Replace(‘четыре’, ‘два’, []));

        //Пример регистрозависимого поиска и замены подстрок

        //(т.к. по умолчанию не установлен флаг rfIgnoreCase).

        //В результате будет ‘Раз, Четыре, три, два’.

        Writeln(‘Раз, Четыре, три, четыре’.Replace(‘четыре’, ‘два’));

        //Пример регистронезависимого поиска и замены подстрок

        //(т.к. установлен флаг rfIgnoreCase).

        //В результате будет ‘Раз, два, три, четыре’.

        Writeln(‘Раз, Четыре, три, четыре’.Replace(‘четыре’, ‘два’, [rfIgnoreCase]));

        stringBuilder := TStringBuilder.Create;

        try

            //Ищет все подстроки в строке и заменяет их на новые.

            //Результат будет ‘Раз, два, три, два’.

            stringBuilder.Append(‘Раз, четыре, три, четыре’);

            Writeln(stringBuilder.Replace(‘четыре’, ‘два’).ToString);

            //Ищет все подстроки в строке и заменяет их на новые.

            //Результат будет ‘Раз, Четыре, три, два’.

            stringBuilder.Clear;

            stringBuilder.Append(‘Раз, Четыре, три, четыре’);

            Writeln(stringBuilder.Replace(‘четыре’, ‘два’).ToString);

            //Ищет все подстроки начиная с 4-го символа в пределах 10-ти символов и заменяет их на новые.

            //Результат будет ‘Раз, два, три, четыре’.

            stringBuilder.Clear;

            stringBuilder.Append(‘Раз, четыре, три, четыре’);

            Writeln(stringBuilder.Replace(‘четыре’, ‘два’, 3, 10).ToString);

        finally

            stringBuilder.Free;

        end;

        //Ищем и убираем HTML тэги из строки.

        //В результате получится: Здесь содержатся выделенное и подчёркнутое слова и ссылка.

        regEx := TRegEx.Create(‘<([A-Z][A-Z0-9]*)b[^>]*>(.*?)</1>’, [roIgnoreCase]);

        Writeln(regEx.Replace(‘Здесь содержатся <b>выделенное</b> и <u>подчёркнутое</u> слова и <a href=”http://www.proghouse.ru”>ссылка</a>.’, ‘2’));

        //Ищем определённое слово и заменяем его звёздочками.

        //В результате получится: Закрываем *** слова звёздами. *** слов не будет! *** слово – это ***!

        regEx := TRegEx.Create(‘плох[ио][емх]?’, [roIgnoreCase]);

        Writeln(regEx.Replace(‘Закрываем плохие слова звёздами. Плохих слов не будет! Плохое слово – это плохо!’, ‘***’));

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Обрезка пробелов и управляющих символов

Для такой часто встречающейся операции, как удаление пробелов и управляющих символов в начале и в конце строки, есть несколько функций: Trim, TrimLeft, TrimRight, TStringHelper.TrimTStringHelper.TrimLeft и TStringHelper.TrimRight. При вызове функций TStringHelper.Trim, TStringHelper.TrimLeft и TStringHelper.TrimRight вы можете перечислить, какие символы нужно удалять. Вот пример использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

begin

    try

        //Удаляем пробелы и управляющие символы в начале и конце строки.

        //Результат будет ‘Строка без лишних пробелов и управляющих символов!’.

        Writeln(Trim(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10));

        //Удаляем пробелы и управляющие символы в начале и конце строки.

        //Результат будет ‘Строка без лишних пробелов и управляющих символов!’.

        Writeln(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10.Trim);

        //Удаляем только символы #13 и #10 в начале и конце строки.

        //Результат будет ‘ Строка без лишних пробелов и управляющих символов! ‘.

        Writeln(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10.Trim([#13, #10]));

        //Удаляем пробелы и управляющие символы только в начале строки.

        //Результат будет ‘Строка без лишних пробелов и управляющих символов! ‘#13#10.

        Writeln(TrimLeft(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10));

        //Удаляем пробелы и управляющие символы только в начале строки.

        //Результат будет ‘Строка без лишних пробелов и управляющих символов! ‘#13#10.

        Writeln(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10.TrimLeft);

        //Удаляем пробелы и управляющие символы только в конце строки.

        //Результат будет #13#10′ Строка без лишних пробелов и управляющих символов!’.

        Writeln(TrimRight(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10));

        //Удаляем пробелы и управляющие символы только в конце строки.

        //Результат будет #13#10′ Строка без лишних пробелов и управляющих символов!’.

        Writeln(#13#10′ Строка без лишних пробелов и управляющих символов! ‘#13#10.TrimRight);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Выравнивание текста за счёт установки пробелов

И напоследок ещё пара интересных функций, которые умеют дополнять строку пробелами или другими символами, пока она не станет нужной длины. Это функции TStringHelper.PadLeft и TStringHelper.PadRight. С помощью этих функций, например, для лучшего восприятия можно добавить пробелы в начало чисел, которые вы выдаёте столбиком в консоли или дополнить числа ведущими нулями. Вот пример использования этих функций:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

    System.SysUtils;

begin

    try

        //Дополняем числа пробелами. В результате получится:

        //’  123′

        //’12345′

        //’ 1234′

        Writeln(‘123’.PadLeft(5));

        Writeln(‘12345’.PadLeft(5));

        Writeln(‘1234’.PadLeft(5));

        //Дополняем числа нулями. В результате получится.

        //’00123′

        //’12345′

        //’01234′

        Writeln(‘123’.PadLeft(5, ‘0’));

        Writeln(‘12345’.PadLeft(5, ‘0’));

        Writeln(‘1234’.PadLeft(5, ‘0’));

        //Дополняем строки чёрточками, чтобы сделать красивое содержание.

        //В результате получится:

        //’Вступление ——— стр. 1′

        //’Доклад ————- стр. 2′

        //’Выводы ————- стр. 7′

        //’Заключение ——— стр. 9′

        Writeln(‘Вступление ‘.PadRight(20, ‘-‘) + ‘ стр. 1’);

        Writeln(‘Доклад ‘.PadRight(20, ‘-‘) + ‘ стр. 2’);

        Writeln(‘Выводы ‘.PadRight(20, ‘-‘) + ‘ стр. 7’);

        Writeln(‘Заключение ‘.PadRight(20, ‘-‘) + ‘ стр. 9’);

        Readln;

    except

        on E: Exception do

            Writeln(E.ClassName, ‘: ‘, E.Message);

    end;

end.

Вместо заключения

Итак, в статье я постарался собрать все возможные функции Delphi, которые постоянно нужны при работе со строками. Надеюсь, вы найдёте в этой статье что-то новое и интересное для себя. Если я упустил что-то важное на ваш взгляд, просьба не держать это в себе, а написать об этом в комментариях.

Метки: Delphi, striing

Опубликовано 30.01.2017 от evgeniyalf в категории “Delphi

I was developing a program that validate a CPF, a type of document of my country. I already did all the math. But in the input Edit1, the user will insert like:

123.456.789-00

I have to get only the numbers, without the hyphen and the dots, to my calcs worth.

I’m newbie with Delphi, but I think that’s simple. How can I do that? Thanks for all

MartynA's user avatar

MartynA

30.4k4 gold badges31 silver badges72 bronze badges

asked Nov 6, 2015 at 21:20

Victor Melo's user avatar

2

You can use

text := '123.456.789-00'
text := TRegEx.Replace(text, 'D', '')

Here, D matches any non-digit symbol that is replaced with an empty string.

Result is 12345678900 (see regex demo).

answered Nov 6, 2015 at 21:27

Wiktor Stribiżew's user avatar

Wiktor StribiżewWiktor Stribiżew

603k37 gold badges435 silver badges547 bronze badges

0

Using David’s suggestion, iterate your input string and remove characters that aren’t numbers.

{$APPTYPE CONSOLE}

function GetNumbers(const Value: string): string;
var
  ch: char;
  Index, Count: integer;
begin
  SetLength(Result, Length(Value));
  Count := 0;      
  for Index := 1 to length(Value) do
  begin
    ch := Value[Index];
    if (ch >= '0') and (ch <='9') then
    begin
      inc(Count);
      Result[Count] := ch;
    end;
  end;
  SetLength(Result, Count);
end;

begin
  Writeln(GetNumbers('123.456.789-00'));
  Readln;
end.

David Heffernan's user avatar

answered Nov 6, 2015 at 22:13

John Easley's user avatar

John EasleyJohn Easley

1,5491 gold badge13 silver badges23 bronze badges

6

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