Сравнение строк по маске
Цитата:
"Hello*" == "Hello world!" //true!
Формат маски не принципиален. В Builder с удовольствием пользовался классом TMask.
Пробежавшись по МСДН ничего подобного не обнаружил.
Есть ли вообще подобные функции в WinAPI или MFC?
Может у кого-нибудь найдется кусок кода на эту тему?
Цитата:
Originally posted by ncode
Пишу приложение на VC++ (MFC). Необходима функция для сравнения строк по маске, наподобие файловой маски или регулярных выражений. Типа:
Формат маски не принципиален. В Builder с удовольствием пользовался классом TMask.
Пробежавшись по МСДН ничего подобного не обнаружил.
Есть ли вообще подобные функции в WinAPI или MFC?
Может у кого-нибудь найдется кусок кода на эту тему?
Пишу приложение на VC++ (MFC). Необходима функция для сравнения строк по маске, наподобие файловой маски или регулярных выражений. Типа:
Формат маски не принципиален. В Builder с удовольствием пользовался классом TMask.
Пробежавшись по МСДН ничего подобного не обнаружил.
Есть ли вообще подобные функции в WinAPI или MFC?
Может у кого-нибудь найдется кусок кода на эту тему?
Тоже помниться искал подобную фичу-ниче не нашел, решил сам написать, вообщим-то там не очень сложный алгоритм
если та почемуж не использоват strcmp()?
Цитата:
Originally posted by pod
если я не ошибаюсь, речь идёт о сравнении 2 строк?
если та почемуж не использоват strcmp()?
если я не ошибаюсь, речь идёт о сравнении 2 строк?
если та почемуж не использоват strcmp()?
К сожалению, ошибаешся :)
Цитата:
Originally posted by vAC
К сожалению, ошибаешся :)
К сожалению, ошибаешся :)
тогда извиняюсь
За неимением готового кода, решил написать свою функцию, но потом подумал, что лучше все таки класс. Получился такой код:
*.h
Цитата:
class CMask
{
private:
CStringArray m_Items;
public:
explicit CMask()
{
}
CMask(const CMask& mask); //copy ctor
CMask& operator=(const CMask& mask);
bool Init(const CString& mask_string);
bool Compare(const CString& string);
//published CStringArray interface
int GetCount() const
{
return m_Items.GetCount();
}
const CString& GetAt(int index) const
{
ASSERT(m_Items.GetCount() > 0);
ASSERT(index >= 0 && index < m_Items.GetCount());
return m_Items.GetAt(index);
}
};
*.cpp
Цитата:
bool CMask::Init(const CString& mask_string)
{
if(mask_string.IsEmpty()) //mask_string must be nonempty
return false;
//I don`t want to change mask_string strings, so I use it copy
CString mask_str = mask_string;
mask_str.MakeLower(); //I need case-insensitive comparison
CString sub_string; //sub string extracted from mask
int i = 0; //position in mask_str
//initialize
if(mask_str.FindOneOf("*?")==-1) //this is not a regular mask, so add whole mask_str
{
m_Items.Add(mask_str); //note that this is only one item in Mask
return true;
}
//break down mask_str into items
while(true)
{
if(i>=mask_str.GetLength()) //mask_str ended
return true;
if(mask_str == '*')
{
m_Items.Add("*");
//treat sequence of '*' as one '*'
do
i++;
while((mask_str=='*')&&(i<mask_str.GetLength()));
}
else if(mask_str == '?')
{
m_Items.Add("?");
i++;
}
else
{
sub_string.Empty(); //clear sub_string
do
{
sub_string += mask_str;
i++;
}
while((mask_str!='*')&&(mask_str!='?')&&(i<mask_str.GetLength()));
m_Items.Add(sub_string);
}
}
return true;
}
//---------------------------------------------------------------------------
CMask::CMask(const CMask& mask) //copy ctor
{
if(this == &mask)
return;
m_Items.RemoveAll();
for(int i = 0;i<mask.GetCount();i++)
m_Items.Add(mask.GetAt(i));
}
//---------------------------------------------------------------------------
CMask& CMask::operator=(const CMask& mask)
{
if(this == &mask)
return *this;
m_Items.RemoveAll();
for(int i = 0;i<mask.GetCount();i++)
m_Items.Add(mask.GetAt(i));
return *this;
}
//---------------------------------------------------------------------------
bool CMask::Compare(const CString& string)
{
if(m_Items.IsEmpty()) //CMask is not initialized, it looks like error
return false;
if(string.IsEmpty()) //don`t compare with empty string
return false;
//I don`t want to change string, so I use it copy
CString s = string;
s.MakeLower(); //I need case-insensitive comparison
int spos = 0; //position in s
int ipos; //position of item in s
bool b = false; //true if previous item was '*'
CString item; //item from m_Items
for(int i=0;i<m_Items.GetCount();i++)
{
item = m_Items.GetAt(i); //get ith item
if(spos>=s.GetLength()) //s ended, but items not, so return false
return false;
else if(item == "*")
{
b = true;
spos++; //at least one character must substitute '*'
}
else if(item == "?")
spos++;
else
{
ipos = s.Find(item.GetString(), spos); //find item in s
if(b) //is there item in s?
{
if(ipos == -1) //item not found in s
return false;
b = false;
}
else //check for item at spos
{
if(ipos != spos) //there is no item at spos
return false;
}
spos += ipos + item.GetLength();
}
}
return true;
}
P.S. Я подсматриваю в английский МСДН, поэтому комменты привык писать тоже на английском. Некоторые особенности в реализации связаны с моей программой.