Apr 21

Разбиение строки на подстроки

Когда я начинал изучение PHP, мне, после Delphi, понравилась одна функция - explode. Ее работа очень проста - разбить строку на подстроки. В Delphi, до этого, я делал примерно следующее:

var

  sl: TStringList;

begin

  sl := TStringList.Create;

  try

    sl.Text := 'str1, str2, str3, str4, str5';

    sl.Delimiter := ',';

    // тут обрабатываем sl.Items

  finally

    sl.Free;

  end;

end;

Все бы хорошо, но... Что делать, если разделителей несколько? Например, как разбить такую строку:

language: russian; delphi, php, c++; Ivanov

и получить следующее:

language: russian

delphi

php

c++

Ivanov

Да, можно, конечно, разбить строку, а потом разбивать подстроки. Можно использовать регулярки. Но, как я уже писал - я противник использования, для таких случаев, регулярных выражений. Да и рекурсию/множество циклов использовать не люблю. И, как оказалось, не только я. В Delphi есть стандартная функция для разбиения строки на подстроки, совсем как в PHP :).

var

  sl: TStringList;

begin

  sl := TStringList.Create;

  try

    ExtractStrings([';', ','], [' '], 'language: russian; delphi, php, c++; Ivanov', sl);

    // тут обрабатываем sl.Items

  finally

    sl.Free;

  end;

end;

 

Данная функция описана в Classes (странно, что я не встречал упонимания о ней ни в форумах, ни в блогах, ни в статьях, кроме как тут):

type TSysCharSet = set of Char;
function ExtractStrings(Separators, WhiteSpace: TSysCharSet; Content: PChar; Strings: TStrings): Integer;


  1. AMIGO
     Add karma Subtract karma  --1
    Цитировать.

    Спасибо! Супер статья! Блог в ридер однозначно

    1
  2. Volniy_Strelok
     Add karma Subtract karma  --5
    Цитировать.

    Век живи век учись.
    Очень палезная функция надо запомнить.

    2
  3. Виктор
     Add karma Subtract karma  --2
    Цитировать.

    Всё прекрасно, но…
    … эта функция игнорирует пустые подстроки.

    Пример:

    Str := '8|f33||||12-12-1999|preved!|||0'.
    ExtractStrings(['|'], [], PChar(Str), StringList);

    К сожалению StringList.Strings[2] будет равен ’12-12-1999′,
    а не ” как того хотелось бы.

    3
  4. FelixTP
     Add karma Subtract karma  --3
    Цитировать.

    Спасибо огромное за шикарную информацию, я об этом и не догадывался

    4
  5. Селеван
     Add karma Subtract karma  --4
    Цитировать.

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

    5
  6. Gerasimov
     Add karma Subtract karma  --5
    Цитировать.

    Об этом правда не первоначальный раз уже слыхал, но все-таки.Говнокомментов бы было поменьше, было бы вообще очень хорошо.

    6
  7. Михаил
     Add karma Subtract karma  +0
    Цитировать.

    Респект за информацию! Всего 6 строк в процедуре вместо 10-20 если использовать StrPos, StrCopy и т.п. функции!

    7
  8. dark
     Add karma Subtract karma  +0
    Цитировать.

    Всё прекрасно, но…
    … эта функция игнорирует пустые подстроки.
    Пример:

    Str := '8|f33||||12-12-1999|preved!|||0'.
    ExtractStrings(['|'], [], PChar(Str), StringList);

    К сожалению StringList.Strings[2] будет равен ’12-12-1999′,
    а не ” как того хотелось бы.

    Сначала применя к строке функцию replase(‘где менять’, ‘что менять’, ‘на что менять’). Допустим так:
    Str := '8|f33||||12-12-1999|preved!|||0';
    replace (str, '||', '|.|');

    Далее: ExtractStrings(['|'], [ ], PChar(Str), StringList);
    И, затем, ко всей строке Str снова replace (str, ‘.’, ”);

    Только вроде должно быть так:
    str:= str.string[0]+...+str.string[i];
    replace (str, '.', '');

    Где i – количество твоих подстрок…
    На большом количестве строку будет оч. медленно работать.

    8

Поделитесь вашими мыслями



Ссылки в комментариях будут свободны от nofollow.

Поддерживаемые теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> 

Ссылки в комментариях будут свободны от nofollow.