Есть имя файла без пути и маска. Надо проверить, соответствует ли имя данной маске.
Маска может содержать:
? - означает 1 любой символ
* - означает 0 или более любых символов
любые другие символы означают сами себя
Ответ
Задачу можно решить следующим образом (порядок проверок менять нельзя):
bool check(char *s, char *p)
{
char *rs=0, *rp;
while(1)
if(*p=='*')
rs=s, rp=++p;
else if(!*s)
return !*p;
else if(*s==*p || *p=='?')
++s, ++p;
else if(rs)
s=++rs, p=rp;
else
return false;
}
Используемые переменные:
s (string) - указатель на проверяемую строку (имя файла). В процессе сравнения сдвигается на проверяемый символ строки (префикс до него уже проверен).
p (pattern) - шаблон, с которым сверяется строка s. В процессе работы сдвигается на проверяемый символ шаблона (префикс до него проверен).
rs (return in string) и rp (return in pattern) - куда надо откатиться в строке и шаблоне. rp ссылается на последнюю проверенную *, rs на часть строки, которую эта звёздочка уже поглотила.
Обоснование алгоритма:
Единственный символ шаблона, которому может соответствовать пустая строка в имени - это *, поэтому эта проверка должна быть первой.
Если в шаблоне встретилась *, то мы можем заменить её на подстроку любой длины (от 0 до длины всей оставшейся части строки). Будем перебирать все варианты в порядке увеличения длины, т. е. пропускать на 1 символ больше после каждой неудачи.
Если в шаблоне есть несколько *, то при неудаче достаточно возврата к последней. Увеличение числа пропускаемых символов у более ранней * не может улучшить результат, т. к. подстрока между * уже соответствует участку шаблона, при этом величина сдвига уменьшиться не может, а её увеличение возможно и за счёт последней *
Если строка закончилась, то это означает конец проверки. Результат соответствует тому, достигнут ли конец шаблона. Это объясняется тем, что единственный символ шаблона, который может что-то изменить - это *. Однако, количество пропущенных символов уменьшить нельзя, а его увеличение не сможет изменить результат (конец строки будет достигнут ещё раньше). Кроме того, в шаблоне не могут остаться только *, т. к. проверка конца строки делается после проверки на * в шаблоне.
PS: Этот алгоритм используется с 2010 года в Ureal Commander'е.
Комментариев нет:
Отправить комментарий