Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760

[с++][дизайн][сложность] обсуждение

18.10.2017, 19:25. Показов 841. Ответов 10

Студворк — интернет-сервис помощи студентам
всем привет.


рассмотрим код:

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
#pragma once
 
#include <tools/text.h>
#include <cassert>
 
#define dTOOLS_MATCH_PATTERN_USED_ ::tools
 
namespace tools{
 
    template<class s1, class s2>
    bool match_pattern(const s1& value, const s2& mask) 
    {
        drequired_stringed(s1, value);
        drequired_stringed(s2, mask );
        drequired_compatible(s1, value, s2, mask);
 
        assert(dMYTEXT::valid(value));
        assert(dMYTEXT::valid(mask));
 
        dSTDSTRING(s1) ss(value);
        dSTDSTRING(s2) pp(mask );
 
        using ch = dMYTEXT::character<s1>;
 
        ch* s = &ss[0];
        ch* p = &pp[0];
 
        ch *rs=0, *rp=0;
        while(true)
            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;
    }
это функция сравнения текстового имени по файловой маске.
и кода вроде бы не много.
и выглядит он не особо сложно.

более того - код эффективен.
быстро работает.
а засчет шаблоно-природы
компилятор будет генерировать эффективный код
для любых входных аргументов.

функция без изменений может работать с любыми стрингообразными:
массивы/указатели/классы-строки

на самом деле собака зарыта в хедере:
C++
1
#include <tools/text.h>
он тянет за собой достаточно нетривиальный код,
что бы можно было в компалтайме обрабатывть любые строки.

то есть, за эффективность и универсальность
приходится платить сложностью.


рассмотрим альтернативу:

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
    inline bool match_pattern(const char* value, const char* mask) 
    {
        assert(value);
        assert(mask );
 
        std::string ss(value);
        std::string pp(mask );
 
        using ch = char;
 
        ch* s = &ss[0];
        ch* p = &pp[0];
 
        ch *rs=0, *rp=0;
        while(true)
            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;
    }
    inline bool match_pattern(const std::string& value, const char* mask)
        { return match_pattern(value.c_str(), mask); }
 
    inline bool match_pattern(const char* value, const std::string& mask)
        { return match_pattern(value, mask.c_str()); }
 
    inline bool match_pattern(const std::string& value, const std::string& mask)
        { return match_pattern(value.c_str(), mask.c_str()); }
 
//==============================================================================
//==============================================================================
 
    inline bool match_pattern(const wchar_t* value, const wchar_t* mask) 
    {
        assert(value);
        assert(mask );
 
        std::wstring ss(value);
        std::wstring pp(mask );
 
        using ch = wchar_t;
 
        ch* s = &ss[0];
        ch* p = &pp[0];
 
        ch *rs=0, *rp=0;
        while(true)
            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;
    }
    inline bool match_pattern(const std::wstring& value, const wchar_t* mask)
        { return match_pattern(value.c_str(), mask); }
 
    inline bool match_pattern(const wchar_t* value, const std::wstring& mask)
        { return match_pattern(value, mask.c_str()); }
 
    inline bool match_pattern(const std::wstring& value, const std::wstring& mask)
        { return match_pattern(value.c_str(), mask.c_str()); }
теперь сложность ушла.
и код настолько простой,
что в нем без труда сможет разобраться даже новичок.
самое главное - ушла зависимость от чего то сложного и непонятного.

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

но за это пришлось заплатить копипастой.


вопрос к сообществу:
как вы считаете, что лучше?


представьте себе, что нужно иметь дело не с 1 функцией,
а с апи... функций на 50.

копипасту начнет зашкаливать.
или начнет зашкаливать сложность шаблонов.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
18.10.2017, 19:25
Ответы с готовыми решениями:

Как вычислять сложность алгоритма, или найти асимптотическую сложность любой программки?
Например Вычислить x^n по алгоритму быстрого возведения в степень Добавлено через 43 секунды var x, n, r: word; ...

Дизайн сайтов (desktop и адаптивный дизайн), баннеров и логотипов
Добрый день! Меня зовут Катя. Я - начинающий дизайнер. Рисую за гроши сайты (desktop и адаптивный дизайн), баннеры и логотипы. Моя...

Дизайн выпадающего меню под дизайн обычного
Здравствуйте, у меня то есть меню, но, есть одно но... Есть меню в стиле лава-лампы, и я хочу чтобы при уменьшении ширины экрана,...

10
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
19.10.2017, 11:43
Почему бы не оставить единственный вариант?
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
#ifndef UNICODE
    using tstring = std::string;
#else
    using tstring = std::wstring;
#endif
 
bool match_pattern(const tstring& value, const tstring& mask)
{
    using ch = tstring::const_pointer;
    ch s = &value[0];
    ch p = &mask[0];
 
    ch rs=0, rp=0;
    while(true)
        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;
}
Либо (если нужно поддержать и юникодный вариант и обычный)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
template <typename CharT>
bool match_pattern(const std::basic_string<CharT>& value, const std::basic_string<CharT>& mask)
{
    const CharT *s = &value[0];
    const CharT *p = &mask[0];
 
    const CharT *rs=0, *rp=0;
    while(true)
        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;
}
Что бы ни было - DRY. Изменять один и тот же код в нескольких местах при любом изменении алгоритма - не комильфо.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.10.2017, 15:25  [ТС]
Цитата Сообщение от MrGluck Посмотреть сообщение
Почему бы не оставить единственный вариант?
потому, что если бы это было приемлемо,
этой темы бы не существовало.


Цитата Сообщение от MrGluck Посмотреть сообщение
const std::basic_string<CharT>& value
1.
смысл менять один шаблон на другой?

2.
теперь код не эффективен.
будет зажирать на стрингах
без необходимости.

3.
нельзя подсунуть какие то другие строки.
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
19.10.2017, 17:40
Цитата Сообщение от hoggy Посмотреть сообщение
теперь код не эффективен.
будет зажирать на стрингах
без необходимости.
Так у тебя же выше
Цитата Сообщение от hoggy Посмотреть сообщение
C++
1
2
std::string ss(value);
std::string pp(mask );
1
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
19.10.2017, 18:57  [ТС]
Цитата Сообщение от MrGluck Посмотреть сообщение
Так у тебя же выше
кстати да.
мерси.
Цитата Сообщение от Atakai Посмотреть сообщение
Хорошая виндовая практика
это - виндузятно-сишное наследие.
от которого многие уже давно отказываются.

особенно, круто выходит костылями,
если нужна кроссплатформа.

шаблон позволяет вообще не заморачиваться:
char или wchar_t
0
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
20.10.2017, 12:14
hoggy, что бы ни было - я считаю копипасту хуже сложности. Если код "сложен" - его можно прокомментировать/задокументировать.
В случае, если нужно предусмотреть вариант для char и wchar_t - я бы предпочёл обернуть всё это в шаблон.
Цитата Сообщение от hoggy Посмотреть сообщение
смысл менять один шаблон на другой?
Под class s1 может подойти что угодно. А в случае std::basic_string<CharT>, мы явно подчёркиваем, что используем строки, при этом у нас может быть разный тип. Это, возможно, дело вкуса.
Про другие строки в задании не говорилось.

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

Вобщем на единственный вопрос (что выбрать) я ответ высказал.
2
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
20.10.2017, 14:27  [ТС]
Цитата Сообщение от MrGluck Посмотреть сообщение
Под class s1 может подойти что угодно. А в случае std::basic_string<CharT>, мы явно подчёркиваем, что используем строки, при этом у нас может быть разный тип. Это, возможно, дело вкуса.
Про другие строки в задании не говорилось.
говорилось:

Цитата Сообщение от hoggy Посмотреть сообщение
компилятор будет генерировать эффективный код
для любых входных аргументов.
код из первого примера без каких либо модификаций скушает и QString,
и сишную строку, и стдешную, и вообще любые стринги.
если уж решили юзать шаблон - зачем ограничиваться std ?

Цитата Сообщение от MrGluck Посмотреть сообщение
не вижу ничего плохого.
на 1 единственной функции в итоге расплодилась куча перегрузок.
а если там апи из 100 функций?

я пока их писал уже тогда понял - лучше оставить 1 шаблон.
в итоге, как мне кажется получается,
и лаконичнее,
и проще.

и если позарез нужно будет избавиться от зависимостей от хедеров,
шаблон легко скопипастить и переделать под ключ.
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
21.10.2017, 10:48
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template<typename T, typename M>
bool match_pattern(const T& value, const M& mask) {
    auto s = std::begin(value);
    auto p = std::begin(mask);
 
    const auto se = std::end(value);
    const auto pe = std::end(mask);
 
    auto rs = se;
    auto rp = pe;
    while (true)
        if (*p == '*')
            rs = s, rp = ++p;
        else if (s == se)
            return p != pe;
        else if (*s == *p || *p == '?')
            ++s, ++p;
        else if (rs != se)
            s = ++rs, p = rp;
        else
            return false;
}
Нужно проверить логику, ибо я не разбирался, а "ручной автозаменой" жахнул.
0
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
21.10.2017, 18:19
Цитата Сообщение от Nosey Посмотреть сообщение
Нужно проверить логику
не работает так:
C++
1
2
3
const char * s = "ololo";
//...
match_pattern(s, "olo*");
2
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
21.10.2017, 21:11

Не по теме:

GbaLog-, Эээ, дорогой, этож не логика - раз. И мы же вроде в ветке С++ - два (что за си строки) :)


Ну и да, конечно так не будет работать.
Т.е. меня мой вариант устроил бы. Если раз в тыщу лет мне потребуется с си строками поработать, то можно накатать специализацию std::begin&end<const char*> через strlen, wchar туда же. Ну либо сконструировать std::string.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
22.10.2017, 18:07  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Нужно проверить логику, ибо я не разбирался, а "ручной автозаменой" жахнул.
значит вы - за шаблон.

Цитата Сообщение от Nosey Посмотреть сообщение
меня мой вариант устроил бы
моральный шаблон, ориентированный на работу со строками,
должен уметь работать с различными типами строк.

а то ведь с таким успехом можно сделать обычную функцию,
для std::string, и сказать:
"а чо? меня устраивает. нужно std::wstring, можно накатать рядышком"

Цитата Сообщение от Nosey Посмотреть сообщение
можно накатать специализацию std::begin&end<const char*> через strlen, wchar туда же
ну вот примерно так и родился
Цитата Сообщение от hoggy Посмотреть сообщение
#include <tools/text.h>
сейчас он содержит весь необходимый стафф
для быстрого запиливания универсальных шаблонов.

вот только код в итоге получается шаблонным по все поля.
и тянет за собой все эти вспомогательные деталюшки-зависимости.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
22.10.2017, 18:07
Помогаю со студенческими работами здесь

С++ идиомы - обсуждение
Тема создана для вопросов и обсуждений С++ идиом

Обсуждение COBOL
Всем привет. Мало кто знает COBOL на сегодняшний день... По иронии судьбы я работаю именно с ним (на самом деле он ещё более чем жив). ...

Обсуждение по книге
Как происходит выбор песни по переменной tittle Где мы используем переменную artist Не пойму как должны работать методы setTitle ...

Обсуждение литературы
Давайте-ка поделимся и обсудим плюсы и минусы книг программирование андроид устройств. Итак я выделяю 3 основный категории: 1....

Обсуждение литературы
День добрый! Сам авопрос: В документе Общая концепция.doc - есть пункт по созданию Фреймсетов, Схем навигаций (Outline) п. 2.7, 2.8. Вот...


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

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru