Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.10.2014, 12:32   #1
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию Поиск слов со служебными символами (типа * и ?)

Сижу, ломаю голову как это организовать.
Есть список слов.
Есть Edit1 с запросом типа *зво??ть
Нужно организовать поиск по списку и вывод в ListBox всех слов, подходящих к запросу по принципу вместо * может быть несколько символов, вместо ? - только один символ.
Пока у меня лично вот такой код на поиск:
Код:
var i,j:integer;
	PosW:integer; //минимальная позиция, с которой должна начинаться часть слова в "просматриваемом" слове
	PosP:integer; //позиция "просмотра" в запросе
    Dlina_Chasti, Dlina_v_Slove:Integer;//длина в слове - длина, которую занимает часть слова от первого символа до последнего символа "текущей части"
    FSZ:String; // сам запрос, переведённый в нижний регистр
    ThW:boolean; // правильное/неправильное слово
    ChastSlov:TStringList; //список из частей слов между служебными символами
begin    
  FSZ:=AnsiLowerCase(Edit1.Text);
  ListBox1.Clear;
  ChastSlov:=TStringList.Create;
  While (pos('?',FSZ)>0) or (pos('*',FSZ)>0) do //составляем список из частей слов, например, для приводимого мной выше случая: '', 'зво', '', 'ть'.
  begin
    if pos('?',FSZ)>0 then
    begin
      ChastSlov.Add(Copy(FSZ,1,pos('?',FSZ)-1));
      delete(FSZ,1,pos('?',FSZ));
    end;
    if pos('*',FSZ)>0 then
    begin
      ChastSlov.Add(Copy(FSZ,1,pos('*',FSZ)-1));
      delete(FSZ,1,pos('*',FSZ));
    end;
  end;
  ChastSlov.Add(FSZ);  // конец составления списка
  For i:=0 to Spisok.Count-1 do // начало поиска подходящих слов по списку
  begin
    ThW:=true;
    If ChastSlov.Strings[0]<>'' then // присваиваем начальные значения позициям в зависимости от того, "служебный" или нет первый символ запроса
    begin
      j:=0;
      PosW:=1;
      PosP:=1;
    end
    else
    begin
      j:=1;
      PosW:=2;
      PosP:=2;
    end;
    while (ThW) and (j<ChastSlov.Count) do // начало поиска совпадений по частям слова-запроса
    begin
      Dlina_Chasti:=Length(ChastSlov.Strings[j]);
      if pos(ChastSlov.Strings[j],Spisok.Strings[i])>=PosW then
      begin
        Dlina_v_Slove:=pos(ChastSlov.Strings[j],Spisok.Strings[i])+Dlina_Chasti-1;
        If (PosW+Dlina_Chasti-1<>Dlina_v_Slove) and ((Edit1.Text[PosP+Dlina_Chasti]='?') or (PosP+Dlina_Chasti=length(Edit1.Text))) then ThW:=false;
        If (length(Spisok.Strings[i])<>Dlina_v_Slove) and (j=ChastSlov.Count-1) then ThW:=false;
        If (Dlina_Chasti<>Dlina_v_Slove) and (j=0) then ThW:=false;
        If (Dlina_Chasti+1<>Dlina_v_Slove) and (j=1) and (Edit1.Text[1]='?') then ThW:=false;
        PosW:=Dlina_v_Slove+2;
        PosP:=PosP+Dlina_Chasti+1;
        inc(j);
      end else ThW:=false;
    end;
    if ThW then
    begin
      ListBox1.Items.Add(StringGrid1.Cols[0].Strings[i]);
    end
  end;
  ChastSlov.Free;
end;
Но нормально работать так и не стал. Может, кто лучше сможет собрать логические условия в единое целое? А то у меня скоро голова взорвётся.
А, может, у кого-то уже есть готовая функция... Поделитесь, если не сложно...

А, может, в Дельфи уже есть готовая функция поиска, учитывающая подобные символы? (всё-таки это "общие принципы", в виде звёздочки работающие, например, при поиске файлов в винде)
Ship_1 вне форума Ответить с цитированием
Старый 10.10.2014, 13:02   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Можно конечно и свой велосипед придумать, а можно и TRegExpr присобачить для поиска по маске
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 10.10.2014, 14:10   #3
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от Аватар Посмотреть сообщение
...а можно и TRegExpr присобачить для поиска по маске
Я правильно понял, что это он - отдельный модуль, весьма многофункциональный и обширный в возможностях?
Возьму на заметку, спасибо. Но в данном случае его использование - как использовать фотошоп только для просмотра картинок. Ну или можно и по-другому посмотреть на это: для меня не проще будет разобраться во всём синтаксисе этой утилиты, чем "допилить" процедуру стандартными средствами.

Последний раз редактировалось Ship_1; 10.10.2014 в 14:45.
Ship_1 вне форума Ответить с цитированием
Старый 10.10.2014, 15:09   #4
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

100500 раз использовал такой функционал в своих программах. Кроме стандартных функций есть своя наработка, которая работает быстрее стандартной.
Изображения
Тип файла: png 31.png (29.8 Кб, 59 просмотров)
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 10.10.2014, 15:12   #5
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Пиарься дальше. Сам код или принцип, как и в прошлый раз, зажмёшь.
Ship_1 вне форума Ответить с цитированием
Старый 10.10.2014, 15:49   #6
min@y™
Цифровой кот
Старожил
 
Аватар для min@y™
 
Регистрация: 29.08.2014
Сообщений: 7,629
По умолчанию

Цитата:
Сам код или принцип, как и в прошлый раз, зажмёшь.
Пока и не просил никто.
А тебе не дам, пока за наезды не извинишься.
Расскажу я вам, дружочки, как выращивать грибочки: нужно в поле утром рано сдвинуть два куска урана...
min@y™ вне форума Ответить с цитированием
Старый 13.10.2014, 09:48   #7
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Цитата:
Сообщение от min@y™ Посмотреть сообщение
А тебе не дам, пока за наезды не извинишься.
Позвольте полюбопытствовать, о каких наездах речь?
Ship_1 вне форума Ответить с цитированием
Старый 13.10.2014, 15:09   #8
Ship_1
Форумчанин
 
Регистрация: 10.02.2014
Сообщений: 526
По умолчанию

Я таки изобрёл велосипед
Код:
function cosluw(zapr,prov:string):boolean;
var NextSym,NQ:integer;
    FSZ,FSZ2,podW:String;
    FirstSim,FirstQ,FirstSt:boolean;
begin
  FSZ:=AnsiLowerCase(zapr);
  FSZ2:=AnsiLowerCase(prov);
  begin
    if (FSZ<>FSZ2) and (pos('*',FSZ)=0) and (pos('?',FSZ)=0) then result:=false
    else result:=true;
    while (result) and ((pos('*',FSZ)>0) or (pos('?',FSZ)>0)) do
    begin
      FirstSim:=false;
      FirstQ:=false;
      FirstSt:=false;
      result:=false;
      if (pos('*',FSZ)>0) or (pos('?',FSZ)>0) then
      begin
        If FSZ[1]='*' then
        begin
           FirstSt:=true;
           delete(FSZ,1,1);
        end;
        if FSZ='' then
        begin
          result:=true;
          break;
        end;
        NQ:=0;
        While (FSZ[1]='?') and (length(FSZ)>1) do
        begin
          NQ:=NQ+1;
          delete(FSZ,1,1);
        end;
        If FSZ[1]='?' then
        begin
           NQ:=NQ+1;
           delete(FSZ,1,1);
        end;
        if NQ>0 then FirstQ:=true;
        if FSZ='' then
        begin
          if length(FSZ2)=NQ then result:=true;
          break;
        end;
        if (not FirstQ) and (not FirstSt) then
        begin
          FirstSim:=true;
        end;
        If ((pos('*',FSZ)<pos('?',FSZ)) and (pos('*',FSZ)>0)) or (pos('?',FSZ)=0) then
          NextSym:=pos('*',FSZ)
        else
          NextSym:=pos('?',FSZ);
        If NextSym<>0 then
          podW:=copy(FSZ,1,NextSym-1)
        else podW:=FSZ;
        if FirstSim and (pos(podW,FSZ2)=1) then result:=true;
        if FirstQ and (pos(podW,FSZ2)=1+NQ) then result:=true;
        if FirstSt and (pos(podW,FSZ2)>=1) then result:=true;
        if result then
        begin
          delete(FSZ2,1,pos(podW,FSZ2)+length(podW)-1);
          if (podW=FSZ) and (FSZ2<>'') then  result:=false;
          delete(FSZ,1,NextSym-1);
        end;
      end;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if cosluw(Edit1.Text,Edit2.Text) then ShowMessage('Подходит!')
end;
Работает с любыми нормальными сочетаниями служебных знаков * и ?, где ? - пропущена одна буква; * - пропущено несколько букв.
Под нормальными я подразумеваю любые логичные сочетания символов.
Нелогичные: *?, **, ?*, *** и т.п.
??? - логичное (пропущено ровно три буквы)

Раз никто не помог в решении - может кто хоть найдёт где оптимизировать код и процесс?..
Ship_1 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
поиск слов(C++) VadEr Помощь студентам 13 22.05.2014 15:42
Посчитать количество слов в кольцевом списке из элементов типа String, начинающихся на тот же символ, что и следующее слово. azalia Паскаль, Turbo Pascal, PascalABC.NET 7 13.01.2014 13:26
Поиск слов herman94 Общие вопросы C/C++ 1 22.12.2013 23:54
Поиск между символами в документе viter.alex Microsoft Office Word 7 24.05.2009 20:00
Как из переменной типа String удалить пару слов zotox Помощь студентам 3 30.11.2008 19:14