Страницы

Поиск по вопросам

вторник, 23 апреля 2019 г.

Как проверить соответствие имени файла маске?

Есть имя файла без пути и маска. Надо проверить, соответствует ли имя данной маске.
Маска может содержать:
? - означает 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'е.

Комментариев нет:

Отправить комментарий