На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Как правильно парсить строку?
    Есть константа(текстовые смайлы):
    ExpandedWrap disabled
      Const
        Smiles:array[1..7] of string = ('*^_^*','*8)*','*8(*','*-_-*','*^0^*','*^p^*','*8p*');


    Есть абстрактный тест, который может содержать произвольное количество вхождений смайлов из константы.
    Пример текста:
    ExpandedWrap disabled
      message *^0^**8)* message2 *^0^* message3 message4 message5


    Как мне разбить текст на составляющие:
    ExpandedWrap disabled
      message
      *^0^*
      *8)*
      message2
      *^0^*
      message3 message4 message5

    при этом если это смайл, то вернуть номер смайла в константе. текст и смайлы могут быть и не разделены пробелом. Смайлы имеют разную длину.
    В лоб не получается сделать.
      Чтоб текст разбивать, определись, что есть лексемы, а что - разделители.
        min@y™
        разделители константы. все остальное лексемы
          Простой конечный автомат. Вход в состояние "внутри смайла" - когда встретил звездочку, штатный выход по второй звездочке, нештатный - если не совпадает с одной из констант.

          В общем случае - алгоритм Ахо-Корасик, но для этой задачи он излишне сложен.
            Цитата MBo @
            Вход в состояние "внутри смайла" - когда встретил звездочку

            Да, так получилось:
            ExpandedWrap disabled
              Const
                MaxSmiles=7;
                Smiles:array[1..7] of string = ('*^_^*','*8)*','*8(*','*-_-*','*^0^*','*^p^*','*8p*');
              Var
              sIn,sOut,Smile:string;
              i,i2,slength,CharNum:integer;
               
              begin
               
                Sin:='message *^0^* *8)* message2 *^0^* message3 message4 message5';
               
                CharNum:=0;
               
                For i:=1 to length(SIn) do
                begin
                  inc(CharNum);
               
                    If SIn[CharNum]='*' then
                    Begin
                      For i2:=1 to MaxSmiles do
                        Begin
                          SLength:=length(Smiles[i2]);//длина смайла
                          Smile:=copy(SIn,CharNum,SLength);//смайл в тексте
                            If Smile=Smiles[i2] then
                              begin
                                CharNum:=CharNum+SLength-1;
                                 If (SOut<>'')and(SOut<>' ') then ShowMessage(SOut);
                                SOut:='';
                                ShowMessage(Smile);
                                break;
                              end;
                        End;
                    End
                      else
                        begin
                          SOut:=SOut+SIn[charnum];
                            If(Length(SIn)=CharNum)then ShowMessage(sOut);
                        end;
               
               
                end;
              end;
              Эх, это совсем не конечный автомат, а каждый раз копирование всех образцов и сравнение с ними. В таком случае можно было обойтись PosEx для поиска начальной/конечной звездочек и Pos для поиска кусочка в строке-объединении всех смайлов.
                MBo
                разделители могут идти не в том порядке, которые представлены в константе, значит придется определять какой стоит первым, какой вторым и т.д. если вы видите что код может быть существенно сокращен, буду благодарен за новый.
                  Быстродействие важно? Текущая скорость устраивает?
                  Сообщение отредактировано: MBo -
                    Цитата MBo @
                    Быстродействие важно? Текущая скорость устраивает?

                    нет, не важно

                    Скорость значения не имеет
                      Тогда не стоит заморачиваться, код будет объёмнее.
                        Кстати вопрос к знатокам, через stringlist можно сделать подобное? Передать в качестве разделителя массив разделителей?
                          Массив нельзя. Есть какие-то функции, принимающие набор разделителей, но зачем? У тебя один разделитель, внутри смайлов он не содержится, поэтому делай PosEx начала, проверяй, смайл ли идет следующим, если нет - переходи на следующий разделитель, повторить до окончания строки.
                            ^D^ima
                            Можно вот так вот. Главное правильно за эскейпить смайлы в регулярке.
                            ExpandedWrap disabled
                              function TForm1.ReplaceCC(const Match: TMatch): string;
                              const NL=#$000D#$000A;
                              begin
                                Result := NL+Match.Value+NL;
                              end;
                               
                              procedure TForm1.Button2Click(Sender: TObject);
                              var
                                regex: TRegEx;
                                input: string;
                                myEval: TMatchEvaluator;
                              begin
                                input := 'message *^0^* *8)* message2 *^0^* message3 message4 message5.';;
                                regex.Create('(\*\^_\^\*)|(\*8\)\*)|(\*\^0\^\*)');
                                myEval := ReplaceCC;
                                Memo1.Text := regex.Replace(input, myEval);
                              end;


                            ExpandedWrap disabled
                              message
                              *^0^*
                               
                              *8)*
                               message2
                              *^0^*
                               message3 message4 message5.


                            Добавлено
                            '\*\^0\^\*' - правильное экранирование
                            '\*\^\0\^\*' - неправильное экранирование
                              Pavia
                              Спасибо, любая библиотека для регулярки скушает это?
                              ExpandedWrap disabled
                                '(\*\^_\^\*)|(\*8\)\*)|(\*\^0\^\*)'


                              Добавлено
                              У тебя регулярка учитывает 2 смайла всего? У меня их уже 17
                                Цитата ^D^ima @
                                Спасибо, любая библиотека для регулярки скушает это?

                                Я не такой большой знаток регулярок. Но тут используется стандартные операторы \ | (). Полагаю проглотит любая перловская библиотека. Если не пойдёт попробуйте без скобок.

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


                                Добавлено
                                Цитата ^D^ima @
                                У тебя регулярка учитывает 2 смайла всего? У меня их уже 17

                                3 но можно написать сколько хочешь (смайл1)|(смайл2)|(смайл3)|(смайл4)|(смайл5)|(смайл6) и так далее.
                                Только XE требует правильного экранирования.
                                http://docwiki.embarcadero.com/RADStudio/S...lar_Expressions
                                Сообщение отредактировано: Pavia -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0415 ]   [ 17 queries used ]   [ Generated: 25.04.24, 16:13 GMT ]