Есть ли в Windows стандартная функция кторая сравнивает строку по маске, например, '*asd?*ншгншг*'. * - любая последовательность символов ? - один символ
Напиши сам на ASMе, всё равно будет работать быстрее, чем API. Ничего сложного в твоей проблеме нет...
Я реализовал, занимает 776 байт, юникод, аски, без учета регистра, но в проекте каждый байт на счету. Думаю если есть уже стандартная можно ее юзать.
Ну тогда не знаю, чем помочь. Копай SDK. А вообще что-то многовато 776 байт. Я понял тебе скорость не важна. Используй более короткие команды и больше регистров.
bool TestString(char* Your_String) { char *p; p = strstr(Your_String, "asd"); if (p && strstr(p + 4, "ншгншг")) return true; return false; }
crypto неееет... мне нужен универсальный метод))))) Vasil А вообще что-то многовато 776 байт. Я понял тебе скорость не важна. Используй более короткие команды и больше регистров. я выбрал что-то среднне по размеру и скорости, т.к. скорость тоже не маловажна, в модуле есть еще сопутствующие функции, а TestMask 170 байт + 256 байт матрица сравнений. В любом случае эта апи есть, ведь FindFirstFile использует ее.
"Наверное тебе нужен готовый код? То, что предложил crypto, надо чуть доработать и всё." Мое решение меня вполне устраивает, оно тоже основывается на поиске подстроки.
Android Дык нету там ничего. В смысле какой-либо спец. функции, проверяющей совпадение маски. Из апи только RtlUnicodeStringToAnsiString, RtlAnsiStringToUnicodeString, RtlInitUnicodeString, RtlInitAnsiString, NtOpenFile
Я смотрел перед тем как давать пост, тоже ничего не нашел. Скорее всего она не експортируется никакой библиотекой, просто в каокй-то базовой процедуре реалезован этот алгоритм .
Вот тебе 490 байт, оптимизированные на скорость: Код (Text): //=============================================================== BOOL mask_search(char* Str, char* maskStr){ char array[1024]; char* offset = Str; int i=0; while ( *((char*)maskStr) =='*' ) maskStr++; do{ if ( '*' == (array[i] = maskStr[i]) ) array[i]=0; }while (maskStr[i++]); array[i]=0; i=0; while ( *((short*) &array[i]) ){ if ( 0 == (offset = strstr(offset, &array[i]))) return FALSE; while ( array[i] ){ i++; offset++; } i++; } return TRUE; } Компилируй и выдирай код. Ну и тщательно проверить не мешало бы. Я так, слегка проверил, если что, можно подправить. Тут основная масса кода - это strstr. Её можно и самому нарисовать, чтобы поменьше было.
Из старой библиотеки Snippets: Код (Text): static Boolean_T PASCAL patimat (const char *pat, const char *str) { switch (*pat) { case '\0': return !*str; case '*' : return patimat(pat+1, str) || *str && patimat(pat, str+1); case '?' : return *str && patimat(pat+1, str+1); default : return (toupper(*pat) == toupper(*str)) && patimat(pat+1, str+1); } } Очень просто, но медленно. В случаях case '?' и default хвостовую рекурсию можно легко оптимизировать, превратив в цикл. Мой вариант (оптимизирован по скорости; будучи откомпилированным VC++, занимает 169 байт + можно еще оптимизировать по размеру): Код (Text): static bool CheckMask(TCHAR* fn, TCHAR* mask) { // Соответствует ли имя файла маске? while(*mask) { if(*mask == '?') { mask++; if(*fn) fn++; } else if(*mask == '*') { mask++; while(*mask == '*' || *mask == '?') // ** эквивалентно *, а *? будем mask++; // считать эквивалентным * if(!*mask) // Звездочка в конце маски всегда совпадает return true; TCHAR* end = mask; // Продвинуться до конца сегмента, не содержащего * и ? while(*end != '*' && *end != '?' && *end != '\0') end++; while(*fn != *mask || memcmp(fn, mask, size_t((BYTE*)end - (BYTE*)mask))) { if(!*fn) // В маске после звездочки есть символ, return false; // а в строке такого символа нет fn++; } fn += size_t(end - mask); mask = end; } else { if(*mask != *fn) return false; mask++; fn++; } } return !*fn; } void TestCheckMask() { assert(CheckMask(_T("index.html"), _T("index.html")) == true); assert(CheckMask(_T("index.htm"), _T("index.html")) == false); assert(CheckMask(_T("text.txt"), _T("*.txt")) == true); assert(CheckMask(_T("lrmark.txt"), _T("lr*")) == true); assert(CheckMask(_T("soso.txt"), _T("so*so*.txt")) == true); assert(CheckMask(_T("solsol.txt"), _T("so*so*.txt")) == true); assert(CheckMask(_T("lssol.txt"), _T("*so*.txt")) == true); assert(CheckMask(_T("index.html"), _T("*.htm*")) == true); assert(CheckMask(_T("index.html"), _T("*.htm?")) == true); assert(CheckMask(_T("index.htm"), _T("*.htm?")) == true); assert(CheckMask(_T("index.htm"), _T("*.htm*")) == true); assert(CheckMask(_T("index.htm"), _T("*x.htm*")) == true); assert(CheckMask(_T("index.txt"), _T("index.*l")) == false); assert(CheckMask(_T("skynet.exe"), _T("sky???.exe")) == true); assert(CheckMask(_T("skynet.exe"), _T("sky??.exe")) == false); assert(CheckMask(_T("skynet.exe"), _T("sky????.exe")) == false); assert(CheckMask(_T("index.html"), _T("")) == false); assert(CheckMask(_T(""), _T("index.html")) == false); assert(CheckMask(_T(""), _T("")) == true); }
167 байт Код (Text): //=============================================================== __forceinline char* _stdcall _str_str (char* str1, char* str2){ while ( *str1 ){ char* cur1=str1; char* cur2=str2; while ( (*cur1 == *cur2) || (*cur2 == '?') ){ cur1++; cur2++; if ( ! *cur2 ) return str1; } if ( ! *cur1 ) return 0; str1++; } return 0; } //=============================================================== BOOL __stdcall mask_search (char* Str, char* maskStr){ char array[1024]; char* offset = Str; int i=0; while ( *((char*)maskStr) =='*' ) maskStr++; do{ if ( '*' == (array[i] = maskStr[i]) ) array[i]=0; }while (maskStr[i++]); array[i]=0; i=0; while ( *((short*) &array[i]) ){ if ( 0 == (offset = _str_str(offset, &array[i]))) return FALSE; while ( array[i] ){ i++; offset++; } i++; } return TRUE; } ////////////// mask_search ("eeeasdghjнгш", "??as?*?гш*");
cresta Код (Text): CheckMask("eeeasdghjнгш", "asd*нгш*") false, ясен пень! Если поставишь звездочку в начале, будет true: Код (Text): CheckMask("eeeasdghjнгш", "*asd*нгш*") Проверь, пожалуйста, этот вариант: Код (Text): assert(mask_search("index.html", "") == false); На остальных тестах твоя функция работает отлично. Плюс еще одно замечание: вместо Код (Text): array[i]=0; i=0; следует написать Код (Text): array[i]=0; array[i+1]=0; i=0; Ведь массив не обязательно будет инициализирован нулевыми значениями в начале. Например, в Debug-версии VC++ он инициализируется значениями 0xCC, а в Release-версии на стеке будут случайные значения, оставшиеся от вызова предыдущей функции.
SDragon Пардон, что-то со звездочкой я забыл [deleted] Массив можно завершить двойным нулём иначе. Если в качестве строки может передаваться "", то тогда добавляется условие на входе: Код (Text): //=============================================================== BOOL __stdcall mask_search(char* Str, char* maskStr){ char array[1024]; char* offset = Str; int i=0; if ( !*maskStr ) return FALSE; //проверка на пустую строку while ( *((char*)maskStr) =='*' ) maskStr++; do{ if ( '*' == (array[i] = maskStr[i]) ) array[i]=0; }while (maskStr[i++]); *((short*) &array[i])=0; i=0; while ( *((short*) &array[i]) ){ if ( 0 == (offset = _str_str(offset, &array[i]))) return FALSE; while ( array[i] ){ i++; offset++; } i++; } return TRUE; }