Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 Сравнение по маске [C++]
Добрый вечер, уважаемые посетители форума!
Прошу у вас помощи в реализации функции, проверяющей слово по маске.
Маска дана в формате следующего типа a*b, то есть какая-то подстрока a , затем любая последовательность символов, затем подстрока b. Нам нужно проверить слово на соответствие маске.
Как реализовать эту функцию наиболее просто?
Просто все те идеи, которые я начал реализовывать - они очень долгие. Что-то вроде:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
int checkmask(char *word, char *mask)
{
  char *cp = mask;
  int flag = 0;
  while(TRUE)
  {
    if(*mask == '*')
    {
    while(*mask++!='*');
    while(*word)
      if(!strncmp(word, cp , mask - cp))
      {
        flag = 1;
        break;
      }
     if(!flag)
         return FALSE;
     }
  .....// продолжение в том же стиле
  }
}
 

 Re: Сравнение по маске
shukshin в сообщении #813918 писал(а):
Как реализовать эту функцию наиболее просто?
Используя существующие реализации регулярных выражений. В качестве регулярного выражения ваша маска переведётся как a.*b. Правда, придётся поэкранировать некоторые символы.

Или используя проверку, соответствует ли a началу строки и b концу. При этом, если заранее известно, что никакой конец a не может быть началом b, этим всё и кончится, а иначе надо будет проверить, не пересекаются ли вхождения (разумеется, не ходя по символам. Всё нужное можно собрать к этому моменту в виде чисел).

А, ну, во втором случае вам придётся сначала быстренько распарсить маску, хотя бы определив положение b в ней и длину a.

 Re: Сравнение по маске
Если вы можете гарантировать, что в строке mask всегда будет ровно одна звездочка, то все делается очень просто:

Используется синтаксис C++
bool checkmask(const char* word, const char* mask)
{
    const char *star = strchr(word, '*');
    assert(star);
    if (strncmp(word, mask, star - mask)) { return false; }

    size_t wlen = strlen(word + (star - mask)), blen = strlen(star + 1);
    if (wlen < blen) { return false; }

    return (!strcmp(word + wlen - blen, star + 1));
}

 Re: Сравнение по маске
По традиции рекомендую простейший способ, описанный arseniiv под номером два, безо всяких библиотечных функций. Независимо от формата строки (сишная или паскальная, т.к. вы не указали явно язык, хотя пример кода на С++) сначала определить ее длину и конец и после проверок вхождений проверить отсутствие перехлеста. Имхо, гораздо проще остальных вариантов и не требует никаких гарантий от входящих данных.

 Re: Сравнение по маске

(Оффтоп)

_Ivana в сообщении #814026 писал(а):
не требует никаких гарантий от входящих данных.

Я имел в виду случай, когда mask равно aaa*bbb*ccc или aaa* или *bbb или aaabbb — что тут делать?

 Re: Сравнение по маске
Joker_vD я сразу воспринимаю маску как пару подстрок (начала и конца), любая (или обе) из которых может быть пустой. Как запарсивать/распарсивать эти 2 подстроки в одну со звездочкой имхо в данной задаче непринципиально. На ваших примерах первый случай - более широкая задача, не рассматриваем, второй и третий - подстрока конца/начала пустая, четвертый - можно рассмотреть на полное равенство, но опять же, это за рамками поставленной задачи.

 Re: Сравнение по маске
_Ivana
Ну я тоже так подумал, что маска — это essentially две строки, но в исходном-то посте маска передается одной строчкой. А поскольку человек явно учится программировать, то необходимо вкладывать в голову представление о необходимости как-то справляться с некорректными данными.

 Re: Сравнение по маске
В принципе, идеи вполне правильные, только фрагмент, вами приведённый, явно нерабочий. Сильно быстрее не получится.

 Re: Сравнение по маске
_Ivana в сообщении #814026 писал(а):
безо всяких библиотечных функций
С библиотечными будет короче и яснее. Вот, например, Python 3 (надеюсь, ничего не упустил; может быть и не быть совместимым с 2):
Используется синтаксис Python
def satisfies_mask(s, mask):
    elems = mask.split('*')
    assert len(elems) == 2, 'mask должна содержать ровно один символ "*"'
    if len(s) < len(mask) - 1:
        return False
    return s.startswith(elems[0]) and s.endswith(elems[1])

Даже если их нет, startswith и endswith должны писаться в пару строк — и как просто с ними выглядит код.

 [ Сообщений: 9 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group