Форум программистов, компьютерный форум, киберфорум
C/C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22

Реализация LIKE как в VB или SQL на С++ или Си

04.06.2023, 10:06. Показов 13056. Ответов 62
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мое почтение, джентльмены.
Нужна быстрая реализация LIKE как в VB или SQL (алгоритм аналогичный) на С++ или Си.

Из вменяемого нашел только часть алгоритма (ссылка не вставляется, напишу ниже). А так же в Win32 SymMatchString(), которая на порядок медленее чем моя текущая реализация.

Не хочу колхозить свой велосипед, возможно кто-то сможет поделится проверенным алгоритмом.

Добавлено через 11 минут
Из stackoverflow: Как-проверить-соответствие-имени-файла-маске
Маска может содержать:
? - означает 1 любой символ
* - означает 0 или более любых символов
любые другие символы означают сами себя
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.06.2023, 10:06
Ответы с готовыми решениями:

Реализация Round Robin Algoritm, данные должны храниться или в памяти, или на внешнем SQL хранилище
Добрый день Уважаемое сообщество! Порекомендуйте аналог RRDLib на C#. NHawk и другие врапперы к RRDTool не предлагать по причине...

Есть ли в VB или в ADO, DAO или RDO функция преобразования MS SQL типов данных в MS Access?
Существует ли встроенная функция перевода типов данных SQL в Access, Paradox, Dbase и пр.?

Создайте приложение с SQL Server 2012 (или более поздней версии), .NET 4.8 и Entity Framework 6.2 (или 6.4) с по
Привет, мне дали такую задачу и у меня достаточно мало времени, 3-4 дня. Нужно его сделать и одновременно разобраться как это сделать...

62
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
09.06.2023, 09:48
Студворк — интернет-сервис помощи студентам
bedvit, чуть подпилил напильником

constexpr size_t passes= 5;
constexpr size_t testsRepeats= 200000;

https://onlinegdb.com/UzIuflRBK
LikeVB...
ok=81 error=0 ms=240
ok=81 error=0 ms=257
ok=81 error=0 ms=189
ok=81 error=0 ms=227
ok=81 error=0 ms=189

WildCardParser::Match...
ok=81 error=0 ms=333
ok=81 error=0 ms=323
ok=81 error=0 ms=320
ok=81 error=0 ms=328
ok=81 error=0 ms=319


Добавлено через 38 секунд
если будет время, ещё попробую поковырять

Добавлено через 1 час 4 минуты
что увидел, ещё подпилил. Осталось только убрать вьюху ) Но это уже лениво
https://onlinegdb.com/HojBlvIdj
LikeVB...
ok=81 error=0 ms=240
ok=81 error=0 ms=261
ok=81 error=0 ms=257
ok=81 error=0 ms=262
ok=81 error=0 ms=264

WildCardParser::Match...
ok=81 error=0 ms=414
ok=81 error=0 ms=343
ok=81 error=0 ms=324
ok=81 error=0 ms=325
ok=81 error=0 ms=328


Добавлено через 40 секунд
и на онлайнгдб скорость сильно плавает. Верить ли ему - хз

Добавлено через 1 минуту
на вандбоксе примерно так
LikeVB...
ok=81 error=0 ms=122
ok=81 error=0 ms=121
ok=81 error=0 ms=119
ok=81 error=0 ms=119
ok=81 error=0 ms=119

WildCardParser::Match...
ok=81 error=0 ms=245
ok=81 error=0 ms=242
ok=81 error=0 ms=242
ok=81 error=0 ms=242
ok=81 error=0 ms=241
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
09.06.2023, 09:51  [ТС]
Алексей1153, уже недалеко по скорости от паритета . А попробуйте на таком паттерне (расширенный):
C++
1
{L"XYXZZXYXYXZZXY123-#*[[]?!!19Aa--/!\#*[[]?!!19Aa--", L"*X*X?*X*X?***###*[[]][?][!]!1[?1-5-9][!B-Z][A-Za-z][a-][-a]",L"True"}
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
09.06.2023, 12:35
bedvit, символы не экранированные в этой строке (с точки зрения литерала). Вот с сырыми строками
C++
1
{LR"(XYXZZXYXYXZZXY123-#*[[]?!!19Aa--/!\#*[[]?!!19Aa--)", LR"(*X*X?*X*X?***###*[[]][?][!]!1[?1-5-9][!B-Z][A-Za-z][a-][-a])",L"True"}
мой вариант работает очень долго - думаю, из-за обработки звёздочки. То есть, тут явно не из-за языка

Добавлено через 2 часа 33 минуты
подправил работу звезды для длинных строк https://onlinegdb.com/yWaMcLtXY

LikeVB...
ok=82 error=0 ms=198
ok=82 error=0 ms=188
ok=82 error=0 ms=187
ok=82 error=0 ms=186
ok=82 error=0 ms=186

WildCardParser::Match...
ok=82 error=0 ms=372
ok=82 error=0 ms=373
ok=82 error=0 ms=371
ok=82 error=0 ms=372
ok=82 error=0 ms=371
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
09.06.2023, 17:56  [ТС]
Как ни странно, первый написанный вариант не удается еще сильнее оптимизировать по скорости. К примеру, вынося if перед циклом, .т.е. в каждои if свой цикл, только ухудшает ситуацию, хотя кажется что должно быть быстрее, не нужно в цикле перебирать if. А if, сразу на верхнем уровне. И еще несколько таких же не очевидных результатов. Видимо, компилятор достаточно хорошо оптимизиреут первоначальный вариант.

Добавлено через 2 минуты
Пока, то, что удалось достичь, это прирост в скорости, всего 5-8% (код в отладке, итоговый - нормально оформлю)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
bool LikeVBA(const wchar_t* s, const wchar_t* p)
{
    const wchar_t* rs = 0, * rp = 0, * pt = p;//p_temp
    while (1) {
        bool res = false;
        if (*p == L'[')
        {
            if (*(p + 1) == L']') { p += 2; continue; }// ""=="[]"
            bool chNo = false, match = false;
            pt = p; 
            if (*(++pt) == L'!' && *(pt + 1) != L']') { chNo = true; ++pt; }//[!...] not [!]
            while (*pt != L']') {
                if (!*pt) { throw 93; }//если забыли закрывающую скобку//' Throws Error 93 (invalid pattern string).
                if (*(pt + 1) == L'-' && *(pt + 2) != L']')//если есть диапазон ... - ...
                {
                    if (*s >= *pt && *s <= *(pt + 2))
                    {
                        if (chNo) { break; }//если таких символов не должно быть
                        else { match = true; }//если нашли
                    }
                    pt += 2; //for [1-4-9]
                }
                else { //если отдельный символ
                    if (*s == *pt) {
                        if (chNo) { break; }
                        else { match = true; }
                    }
                    ++pt;
                }
            }
            if (chNo == match) { res = false; }
            else { res = true; }
        }
        if (res) {
            ++s; p = ++pt;
        }
        else if (*p == L'#' && *s <= L'9' && *s >= L'0') {
            ++s, ++p;
        }
        else if (*p == L'*') {
            rs = s, rp = ++p;
        }
        else if (!*s) {
            return !*p;
        }
        else if (*p == L'?' || *s == *p && *p != L'[' && *p != L'#') {
            ++s, ++p;
        }
        else if (rs) {
            s = ++rs, p = rp;
        }
        else {
            return false;
        }
    }
}
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
09.06.2023, 21:16
bedvit, я вот тут объединил оба твои варианта и свои два (№2 - я тоже подшаманил)

на GDB
https://onlinegdb.com/SLxNXgneX
Кликните здесь для просмотра всего текста
LikeVB1
ok=82 error=0 ms=408
ok=82 error=0 ms=363
ok=82 error=0 ms=276
ok=82 error=0 ms=300
ok=82 error=0 ms=281

LikeVBA2
ok=82 error=0 ms=287
ok=82 error=0 ms=285
ok=82 error=0 ms=286
ok=82 error=0 ms=303
ok=82 error=0 ms=284

WildCardParser1
ok=82 error=0 ms=555
ok=82 error=0 ms=556
ok=82 error=0 ms=557
ok=82 error=0 ms=556
ok=82 error=0 ms=556

WildCardParser2
ok=82 error=0 ms=523
ok=82 error=0 ms=522
ok=82 error=0 ms=523
ok=82 error=0 ms=523
ok=82 error=0 ms=535


на GCC
https://wandbox.org/permlink/skRKZ3HrIeLbbR8N
Кликните здесь для просмотра всего текста
LikeVB1
ok=82 error=0 ms=144
ok=82 error=0 ms=139
ok=82 error=0 ms=139
ok=82 error=0 ms=139
ok=82 error=0 ms=139

LikeVBA2
ok=82 error=0 ms=138
ok=82 error=0 ms=138
ok=82 error=0 ms=138
ok=82 error=0 ms=138
ok=82 error=0 ms=139

WildCardParser1
ok=82 error=0 ms=310
ok=82 error=0 ms=309
ok=82 error=0 ms=309
ok=82 error=0 ms=309
ok=82 error=0 ms=309

WildCardParser2
ok=82 error=0 ms=334
ok=82 error=0 ms=335
ok=82 error=0 ms=335
ok=82 error=0 ms=335
ok=82 error=0 ms=336


результаты разные
1
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
10.06.2023, 00:31  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
bedvit, я вот тут объединил оба твои варианта и свои два (№2 - я тоже подшаманил)
Второй оказался даже медленнее на тестах, вот немножко еще дожал, копейки по сути.
Больше не знаю, где можно оптимизнуть, перепробовал уже разное.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
bool LikeVBA(const wchar_t* s, const wchar_t* p)
{
    const wchar_t* rs = 0, * rp = 0;// , * pt = p;//p_temp
    while (1) {
        bool res = false;
        if (*p == L'[')
        {
            if (*(p + 1) == L']') { p += 2; continue; }// ""=="[]"
            bool chNo = false, match = false;
            const wchar_t* pt = p;
            if (*(++pt) == L'!' && *(pt + 1) != L']') { chNo = true; ++pt; }//[!...] not [!]
            while (*pt != L']') {
                if (!*pt) { throw 93; }//если забыли закрывающую скобку//' Throws Error 93 (invalid pattern string).
                if (*(pt + 1) == L'-' && *(pt + 2) != L']')//если есть диапазон ... - ...
                {
                    if (*s >= *pt && *s <= *(pt + 2))
                    {
                        if (chNo) { break; }//если таких символов не должно быть
                        else { match = true; }//если нашли
                    }
                    pt += 2; //for [1-4-9]
                }
                else { //если отдельный символ
                    if (*s == *pt) {
                        if (chNo) { break; }
                        else { match = true; }
                    }
                    ++pt;
                }
            }
            if (chNo == match) { res = false; }
            else { ++s; p = ++pt; res = true; }
        }
        if (res) {}
        else if (*p == L'#' && *s <= L'9' && *s >= L'0') {
            ++s, ++p;
        }
        else if (*p == L'*') {
            rs = s, rp = ++p;
        }
        else if (!*s) {
            return !*p;
        }
        else if (*p == L'?' || *s == *p && *p != L'[' && *p != L'#') {
            ++s, ++p;
        }
        else if (rs) {
            s = ++rs, p = rp;
        }
        else {
            return false;
        }
    }
}
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
10.06.2023, 10:51  [ТС]
Алексей1153, вообщем уже неплохо. С регулярками редко встречался, а было бы интересно замерять скорость самой простой реализации на регулярказ, первого шаблона со звездой, без экранирования и т.д. одна звезда, как любой набор символов.
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
14.06.2023, 12:01  [ТС]
Нашел у себя ошибку, поправил.
Сделал 2 варианта оформления +1й первоначальный из stackoverflow, какой True?
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
bool LikeVBA1(const wchar_t* s, const wchar_t* p)
{   //rs(return in string) и rp(return in pattern) - куда надо откатиться в строке и шаблоне. rp-ссылается на последнюю проверенную*, rs-на часть строки, которую эта звёздочка уже поглотила.
    const wchar_t* rs = 0, * rp = 0;
    while (1) {
        if (*p == L'[')
        {
            if (*(p + 1) == L']') { p += 2; continue; }// ""=="[]"
            if (!*s) { return false; }//если нулевая строка
            bool match = false;
            const wchar_t* b = p;//brackets
            if (*(++b) == L'!' && *(b + 1) != L']') { match = true; ++b; }//[!...] not [!]
            
            while (*b != L']') {
                if (!*b) { throw 93; }//если забыли закрывающую скобку//' Throws Error 93 (invalid pattern string).
                if (*(b + 1) == L'-' && *(b + 2) != L']')//если есть диапазон ... - ...
                {
                    if (*s >= *b && *s <= *(b + 2)) { match = !match; break; }//если нашли
                    b += 2; //for [1-4-9]//pt += 3; //for [1-44-9]
                }
                else { //если отдельный символ
                    if (*s == *b) { match=!match; break; }
                    ++b;
                }
            }
            if (match) {
                while (*b != L']') { if (!*b) { throw 93; }++b;}
                ++s; p = ++b; continue;
            }
        }
        if (*p == L'*') {
            rs = s, rp = ++p;
        }
        else if (!*s) {
            return !*p;
        }
        else if (*p == L'?' || *s == *p && *p != L'[' && *p != L'#') {
            ++s, ++p;
        }
        else if (*p == L'#' && *s <= L'9' && *s >= L'0') {
            ++s, ++p;
        }
        else if (rs) {
            s = ++rs, p = rp;
        }
        else {
            return false;
        }
    }
}

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
bool LikeVBA2(const wchar_t* string, const wchar_t* pattern)
{
    const wchar_t* returnString = 0, * returnPattern = 0;
    while (1) {
        if (*pattern == L'[')
        {
            if (*(pattern + 1) == L']') { pattern += 2; continue; }// ""=="[]"
            if (!*string) { return false; }//нулевая строка
            bool match = false;
            const wchar_t* inBrackets = pattern;
            if (*(++inBrackets) == L'!' && *(inBrackets + 1) != L']') { match = true; ++inBrackets; }//[!...] not [!]
 
            while (*inBrackets != L']') {
                if (!*inBrackets) { throw 93; }//нет закрывающей скобки//' Throws Error 93 (invalid pattern string).
                if (*(inBrackets + 1) == L'-' && *(inBrackets + 2) != L']')//диапазон ... - ...
                {
                    if (*string >= *inBrackets && *string <= *(inBrackets + 2)) { match = !match; break; }
                    inBrackets += 2; //for [1-4-9] //pt += 3;//for [1-44-9]
                }
                else { //отдельный символ
                    if (*string == *inBrackets) { match = !match; break; }
                    ++inBrackets;
                }
            }
            if (match) {
                while (*inBrackets != L']') { if (!*inBrackets) { throw 93; } ++inBrackets; }
                ++string, pattern = ++inBrackets; continue;
            }
        }
        if (*pattern == L'*') {
            returnString = string, returnPattern = ++pattern;
        }
        else if (!*string) {
            return !*pattern;
        }
        else if (*pattern == L'?' || *string == *pattern && *pattern != L'[' && *pattern != L'#') {
            ++string, ++pattern;
        }
        else if (*pattern == L'#' && *string <= L'9' && *string >= L'0') {
            ++string, ++pattern;
        }
        else if (returnString) {
            string = ++returnString, pattern = returnPattern;
        }
        else {
            return false;
        }
    }
}

Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
bool LikeVBA3(const wchar_t* string, const wchar_t* pattern)
{
    const wchar_t* returnString = 0, * returnPattern = 0;
    while (1) {
        if (*pattern == L'[')
        {
            if (*(pattern + 1) == L']') { 
                pattern += 2; 
                continue; // ""=="[]"
            }
            if (!*string) { 
                return false; //нулевая строка
            }
            bool match = false;
            const wchar_t* inBrackets = pattern;
            if (*(++inBrackets) == L'!' && *(inBrackets + 1) != L']') {
                match = true; 
                ++inBrackets; 
            }//[!...] not [!]
 
            while (*inBrackets != L']') {
                if (!*inBrackets) { 
                    throw 93; //нет закрывающей скобки//' Throws Error 93 (invalid pattern string).
                }
                if (*(inBrackets + 1) == L'-' && *(inBrackets + 2) != L']')//диапазон ... - ...
                {
                    if (*string >= *inBrackets && *string <= *(inBrackets + 2)) { 
                        match = !match; 
                        break; 
                    }
                    inBrackets += 2; //for [1-4-9] //pt += 3;//for [1-44-9]
                }
                else { //отдельный символ
                    if (*string == *inBrackets) { 
                        match = !match; 
                        break; 
                    }
                    ++inBrackets;
                }
            }
            if (match) {
                while (*inBrackets != L']') { 
                    if (!*inBrackets) { 
                        throw 93; //' Throws Error 93 (invalid pattern string).
                    } 
                    ++inBrackets; 
                }
                ++string; 
                pattern = ++inBrackets; 
                continue;
            }
        }
        if (*pattern == L'*') {
            returnString = string;
            returnPattern = ++pattern;
        }
        else if (!*string) {
            return !*pattern;
        }
        else if (*pattern == L'?' || *string == *pattern && *pattern != L'[' && *pattern != L'#') {
            ++string;
            ++pattern;
        }
        else if (*pattern == L'#' && *string <= L'9' && *string >= L'0') {
            ++string;
            ++pattern;
        }
        else if (returnString) {
            string = ++returnString;
            pattern = returnPattern;
        }
        else {
            return false;
        }
    }
}
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
14.06.2023, 12:15
bedvit, я египетские скобки не люблю, так что не вижу разницы в этих вариантах оформлдения
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
21.06.2023, 17:44  [ТС]
Добавил LikeVBAF (оптимизация для длинных строк)
Добавил std::regex_match
Итоги:
Кликните здесь для просмотра всего текста
Microsoft Visual Studio Community 2022
Speed test...1
check, ms: 46
1
LikeVBA, ms: 56
1
LikeVBAF, ms: 54
1
MatchWildcardAndText, ms: 172
1
Matching text: XYXZZXYXYXZZXY

regex_match, ms: 30927
1

Speed test...2
LikeVBA, ms: 373
1
LikeVBAF, ms: 156
1
MatchWildcardAndText, ms: 1718
1


https://onlinegdb.com/11kcuHsbB
Speed test...1
check, ms: 21
1
LikeVBA, ms: 36
1
LikeVBAF, ms: 37
1
MatchWildcardAndText, ms: 73
1
Matching text: XYXZZXYXYXZZXY

regex_match, ms: 1693
1

Speed test...2
LikeVBA, ms: 265
1
LikeVBAF, ms: 115
1
MatchWildcardAndText, ms: 600
1


https://wandbox.org/permlink/H29gVGjk0zwaBCbQ
Speed test...1
check, ms: 28
1
LikeVBA, ms: 28
1
LikeVBAF, ms: 35
1
MatchWildcardAndText, ms: 62
1
Matching text: XYXZZXYXYXZZXY

regex_match, ms: 945
1

Speed test...2
LikeVBA, ms: 233
1
LikeVBAF, ms: 95
1
MatchWildcardAndText, ms: 490
1


Итого в студии регулярки самые медленные! более 500 раз медленнее LikeVBAF
В onlinegdb.com всего в 45 раз
В wandbox.org всего в 27 раз

Что не так со студией?
Студия - компиляция с флагом -O2 (максимальная оптимизация) и приоритет на скорость кода, на сайтах с флагом -О3

Добавлено через 13 минут
MatchWildcardAndText от Алексей1153, отстает от LikeVBAF всего от 2 до 5 раз.
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
21.06.2023, 17:50
bedvit, попробуй ещё в конструктор регвыра передать флаг optimize

Добавлено через 4 минуты
Цитата Сообщение от bedvit Посмотреть сообщение
отстает
думаю, если там убрать std::wstring_view, то можно сделать скорость побольше

тут ещё загвоздка в том, что у тебя тестовый контейнер такой std::vector < std::vector<const wchar_t* >> testArr =, поэтому на входе вьюха считает длину строки. Если передавать std::wstring, то такого подсчёта не будет. И может стать быстро даже со вьюхой. Но мне просто лень это переделывать, да и не гибко получится.
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
21.06.2023, 18:01  [ТС]
Алексей1153, в студии флаг std::regex_constants::syntax_option_type ::optimize работает, но скорость не увеличивает, а на сайтах не работает (ошибка).

Добавлено через 1 минуту
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Если передавать std::wstring,
можем для эксперемента, в функцию передавать длину строки. Я тоже пишу обработчик для COM-строк (BSTR), там длину строки тоже быстро получить (длина хранится со строкой)

Добавлено через 5 минут
Мне интересно почему так плохо с реализацией регулярок в студии? В 19-20 раз медленее других компиляторов. Может я что-то не знаю и не правильно что-то делаю?
0
фрилансер
 Аватар для Алексей1153
6500 / 5731 / 1133
Регистрация: 11.10.2019
Сообщений: 15,332
21.06.2023, 19:46
Цитата Сообщение от bedvit Посмотреть сообщение
Мне интересно почему так плохо с реализацией регулярок в студии?
это в релизе пробовал? Я не сравнивал с другими компиляторами
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
21.06.2023, 20:05  [ТС]
Алексей1153, в релизе, запуск через exe
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
08.05.2025, 22:20  [ТС]
Хочу выложить итоговую версию кода, но не могу определится: делать функцию noexcept (в случае некорректной маски возвращаем False) или в случае некорректной маски вызывать исключения. Тогда нужно подпиливать функционал, обязательной полной проверки маски, если даже её просто не прошли, в силу уже не совпадающих символов, что отрицательно скажется на скорости и усложнит алгоритм. Сейчас маска проверяется до того символа, который даёт False , т.е. дальше без её обязательной проверки. True без проверки всей маски вернуться не может.

Т.е.
1.На одной стороне скорость, noexcept, проще код, и не проверяется маска до конца если результат уже False, при True - проверяется до конца. Всегда только два результата False, True. Признак некорректной маски от отрицательного результата не отличим.
2.На другой стороне сложнее код, медленнее, но пользователю/разработчику будет 100% признак некорректной маски, в виде исключения. Нужен ли 100% признак некорректной маски для такого простого инструмента в виде исключения в счет усложнения и замедления? Результат: False, True, Exception
3.Оставить как есть: возвращается False, True, Exception и не проверяется маска до конца, если результат уже False, при True - проверяется до конца. Этот вариант мне не нравится, но именно так реализован Like Operator от microsoft (маска проверяется не всегда до конца, и есть исключения)

Какой подход считаете правильным?

Насколько я слышал в регулярных выражения С++ есть exception: std::regex_error (для примера)
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
09.05.2025, 11:48
Цитата Сообщение от bedvit Посмотреть сообщение
Это закрытый код и подозреваю медленный.
Чего это он закрытый?
https://github.com/gcc-mirror/... /fnmatch.c
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
09.05.2025, 22:37  [ТС]
DrOffset, рад, что вы зашли в тему.
Интересная ссылка, есть где-то в онлайн возможность протестировать маски в этом инструменте?

Из замеченного:
1. fnmatch работает только с Си строками
2. в fnmatch нет в маске символа # - Любая однозначная цифра (0–9).
2. fnmatch не выдает исключения при некорректной маске, т.е. похож на мой подход №1
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
09.05.2025, 23:57
Цитата Сообщение от bedvit Посмотреть сообщение
есть где-то в онлайн возможность протестировать маски в этом инструменте?
Можно вытащить этот код и вставить в любой онлайн компилятор.

Цитата Сообщение от bedvit Посмотреть сообщение
Из замеченного:
1 и 3 - это само собой разумеется, ведь код на C.
0
 Аватар для bedvit
1210 / 261 / 22
Регистрация: 20.05.2016
Сообщений: 1,147
Записей в блоге: 22
10.05.2025, 10:24  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
Можно вытащить этот код и вставить в любой онлайн компилятор.
Быстро не выйдет, много идентификаторов не определено: TOLOWER, FNM_CASEFOLD, FNM_NOMATCH, FNM_FILE_NAME ,FNM_PERIOD, FNM_NOESCAPE. По контексту понятно для чего они. Была идея сравнить это со своим инструментом. Нужно тогда подпиливать до двухбайтовых символов. Плюс мне не только Си-строки нужно сравнивать, см. ниже.

Цитата Сообщение от DrOffset Посмотреть сообщение
1 и 3 - это само собой разумеется, ведь код на C.
Строго говоря это не так (см. ниже), но не хочу спорить, в данном контексте это не существенно, ваша мысль понятна.

Сейчас решение 3, максимально похожее на VB(A) Lile такое...
Особенности, в соответствии и дополнительно к основным:
1. Сравнивает строки: СИ, С++, COM(BSTR), строки C API Excel XCHAR (Паскаль?), строго говоря любая последовательность 2х байтовых Unicode символов.
2.Выброс исключений при ошибках:
- нет парного закрывающего символа "]", пример: "[..."
- отдельный символ разделителя диапазона "-" не в начале и не в конце и не разделяет диапазон [], пример: "[A-B-D]" - Error, "[A-BC-D]" - OK . !Не совпадает с реализации от Microsoft (нет данных об алгоритме)
- первое значение диапазона больше последнего, пример: "[B-A]."
3.Прочие особенности:
+ последовательность [] символов считается строкой нулевой длины ("")
+ небольшая оптимизация уменьшение количества проверок для символов маски: "?", "#"
+ исключения COM AtlThrow()
+ код сгруппирован по однотипным операциям (не в классическом подходе), мне так было проще собрать логику, возможно, не конечный вариант оформления.
+ работает с нулевыми указателями (считается валидным для COM(BSTR) передавать нулевой указатель если строка пустая)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
inline bool LikeVBAF(const wchar_t* string, const wchar_t* stringEnd, const wchar_t* pattern, const wchar_t* patternEnd)
{
    const wchar_t* returnString = 0, * returnPattern = 0;
    while (1) {
        if (pattern >= patternEnd) {// конец шаблона
            if (string >= stringEnd) { return pattern >= patternEnd; }//конец строки
            else if (returnString) { string = ++returnString, pattern = returnPattern; continue; }
            else { return false; }
        }
        if (*pattern > L'[') {// not wildcardCh 
            if (string >= stringEnd) { return pattern >= patternEnd; }//нулевая строка
            else if (*pattern == *string) { ++string, ++pattern; continue; }
        }
        else if (*pattern > L'*') {// ?[
            if (*pattern == L'[')
            {
                if (pattern + 1 >= patternEnd) { AtlThrow(E_INVALIDARG); }//если последний символ '[' - ошибка//Throws Error 93 (invalid pattern string).
                if (*(pattern + 1) == L']') { pattern += 2; continue; }//Последовательность [] символов считается строкой нулевой длины ("").
                if (pattern + 2 >= patternEnd) { AtlThrow(E_INVALIDARG); }//если конец маски и нет закрывающей скобки ]//' Throws Error 93 (invalid pattern string).
                if (string >= stringEnd) { return pattern >= patternEnd; }//нулевая строка
                bool match = false;
                const wchar_t* inBrackets = pattern;
                if (*(++inBrackets) == L'!' && *(inBrackets + 1) != L']') { match = true; ++inBrackets; }//[!...] not [!]
                while (inBrackets < patternEnd && *inBrackets != L']') {
                    if ((inBrackets + 2) < patternEnd && *(inBrackets + 1) == L'-' && *(inBrackets + 2) != L']')//диапазон ... - ...
                    {
                        if (*inBrackets > *(inBrackets + 2)) { AtlThrow(E_INVALIDARG); }//первое значение диапазона больше последнего//' Throws Error 93 (invalid pattern string).
                        if (*string >= *inBrackets && *string <= *(inBrackets + 2)) { match = !match; break; }
                        inBrackets += 3; //// += 2//for [1-4-9] // += 3;//for [1-44-9]
                    }
                    else { //отдельный символ
                        if (*(inBrackets) == L'-' && *(inBrackets + 1) != L']' && *(inBrackets - 1 - match) != L'[') { AtlThrow(E_INVALIDARG); }//отдельный символ "-" не в начале и не в конце и не разделитель диапазона - ошибка//' Throws Error 93 (invalid pattern string).
                        if (*string == *inBrackets) { match = !match; break; }
                        ++inBrackets;
                    }
                }
                if (inBrackets >= patternEnd) { AtlThrow(E_INVALIDARG); }//если конец маски и нет закрывающей скобки ]//' Throws Error 93 (invalid pattern string).
                if (match) {
                    while (inBrackets < patternEnd && *inBrackets != L']') { ++inBrackets; }
                    if (inBrackets >= patternEnd) { AtlThrow(E_INVALIDARG); }//нет закрывающей скобки//' Throws Error 93 (invalid pattern string).
                    ++string, pattern = ++inBrackets; continue;
                }
            }
            else if (string >= stringEnd) { return pattern == patternEnd; } //проверка должна быть ДО разыменовывания указателя, но после []
            else if (*pattern == *string) { ++string, ++pattern; continue; }
            else if (*pattern == L'?') { ++string, ++pattern; continue; }
        }
        else {  // *#
            if (*pattern == L'*') {
                returnString = string, returnPattern = ++pattern;
                //быстрый поиск (wmemchr()) нужного символа после * + поиск # любой цифры 0-9
                if (pattern >= patternEnd) { return true; }//если последний символ в маске '*', далее строку не проверяем
                else if (*pattern > L'[') {// not wildcardCh 
                    if (!(string = wmemchr(string, *pattern, stringEnd - string))) { return false; }
                    ++string, ++pattern; continue;
                }
                else if (*pattern > L'*') {
                    if (*pattern != L'[' && *pattern != L'?') {
                        if (!(string = wmemchr(string, *pattern, stringEnd - string))) { return false; }
                        ++string, ++pattern; continue;
                    }
                }
                else if (*pattern == L'#') {
                    if (string >= stringEnd) { return pattern == patternEnd; } //если конец строки
                    while (*string > L'9' || *string < L'0' && *string) { ++string; }
                    if (string >= stringEnd) { return false; }//если не нашли и строка пустая
                    ++string, ++pattern; continue;
                }
                else if (*pattern != L'*') {
                    if (!(string = wmemchr(string, *pattern, stringEnd - string))) { return false; }
                    ++string, ++pattern; continue;
                }
                continue;
            }
            else if (string >= stringEnd) { return pattern == patternEnd; } //проверка должна быть ДО разыменовывания указателя, но после "*"
            else if (*pattern == L'#') {
                if (*string <= L'9' && *string >= L'0') { ++string, ++pattern; continue; }
            }
            else if (*pattern == *string) { ++string, ++pattern; continue; }
        }
 
        if (returnString) { string = ++returnString, pattern = returnPattern; }
        else { return false; }
    }
}
0
19505 / 10108 / 2463
Регистрация: 30.01.2014
Сообщений: 17,828
10.05.2025, 11:01
Цитата Сообщение от bedvit Посмотреть сообщение
Строго говоря это не так (см. ниже), но не хочу спорить
Давайте не будем спорить, но раз уж зашла речь, нужно расставить точки над i.

Вообще тут все наоборот, насчет этого "строго говоря". Как раз строго говоря (т.е. по стандарту) в C нет исключений, и поэтому, строго говоря, ожидать их отсутствие в коде на С - само собой разумеется. Но если, наоборот, говорить нестрого, то мы можем в коде прибегнуть к симуляции исключений, или, вот как вы, использовать платформоориентированные механизмы их заменяющие.

И кстати отсюда вопрос, вы же понимаете, что приколачиваете этим AtlThrow свой код к конкретной платформе? Зачем это делать?

Цитата Сообщение от bedvit Посмотреть сообщение
Быстро не выйдет, много идентификаторов не определено
Ну если анализом работы кода этой функции можно пренебречь, то в сети полно GNU-ориентированных онлайн компиляторов, в которых эта функция сразу доступна. Скорость проверить сможете. Только вот от винды надо сначала ваш код отвязать, а то он там не скомпилируется.

Добавлено через 9 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
в сети полно GNU-ориентированных онлайн компиляторов, в которых эта функция сразу доступна
https://wandbox.org/permlink/bBIsGXnWH2Aq5Ukk
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
10.05.2025, 11:01

SQL или Visual Basic? Или Макросы?
Здравствуйте. Делая проект по заданию базы для избирательного, столкнулась с такой проблемой - в мою готовую базу данных Access...

Как получить индекс элемента (или его позицию или количество элементов до него) в set или multiset от lower_bound?
не работающий код((( #include&lt;bits/stdc++.h&gt; #define ff first #define ss second #define ll long long // #define int long...

Есть ли такая функция даты SQL которая позволяет вытащить записи по опред году, или месяцу или дню
не используя оператор like

Как лучше и быстрее из SQL в QVector и в GUI или сразу из SQL в GUI
Доброе время суток! Ну собственно вопрос в теме, как лучше сделать. Сначала прочитать SQLite в вектор и работать с ним и оставить файл...

Что лучше, учить команды CMD или BASH или PowerShell или все они важны или лучше язык программирования?
В заголовке имел в виду, что если изучаю распространенный язык программирования, например Python, то команды из этих сред командных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru