Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71

Выбор операции сравнения на форме

10.06.2015, 20:29. Показов 1637. Ответов 12
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Подскажите, как красиво и аккуратно реализовать выбор пользователем операции сравнения некого значения с введеными данными.

Вот есть такая форма на первом скриншоте. В выпадающем меню - операция сравнения.

Думаю тут все понятно как работает форма. Юзер выбирает некоторый параметр и выбирает как его сравнивать с введеным значением.

Сейчас всё реализовано через Case (и все это сравниватся ни один раз).

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

Может у кого есть идеи?
Миниатюры
Выбор операции сравнения на форме   Выбор операции сравнения на форме  
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
10.06.2015, 20:29
Ответы с готовыми решениями:

Перегрузить операции сравнения комплексных чисел и операции потокового вывода
Создать класс комплексное число. Перегрузить операции сравнения комплексных чисел! =, ==,>, <,> =, <= И операции потокового...

Операции сравнения String
Как работает оператор == если нужно сравнить например string a,b; a==b

Операции присваивания и сравнения
Почему в Visual Basic нельзя иметь вот такую конструкцию? Dim a As Integer Dim b As Integer Dim c As Integer a = b = c = 7 ...

12
43 / 43 / 13
Регистрация: 17.05.2011
Сообщений: 162
10.06.2015, 21:04
Можно сделать все через классы с наследованием. То есть делаешь класс, у него вирутальную функцию которая принимает на вход два аргумента. Потом для каждой операции создаешь класс унаследованный от первого и в нем переопределяешь функцию, которая выполняет нужное сравнение или операцию с этими двумя аргументами.
Дальше например в вектор пихаешь экземпляры этих классов в той же последовательности, что у тебя в комбобоксе. И тогда вся обработка у тебя будет сводится к следующему коду.
C++
1
2
3
4
vector<TOperation *> Vec;
...
bool bResult = Vec[i]->Compare(crvr, crvr1);
...
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
10.06.2015, 21:17
Можно использовать константы DOP_* как индексы/ключи в каком-нибудь контейнере(vector,map) в самом контейнере хранить указатели на функции/предикаты сравнения.
Тогда всё сведется примерно к такому коду:
C++
1
bool truth = operations[ crdat[7] ]( crvr , crvr1 ) ;
0
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71
10.06.2015, 22:05  [ТС]
Тему неверно переместили. Нету у меня C#, только С++. Прошу не советовать лишнего))

Цитата Сообщение от Peperovich Посмотреть сообщение
Можно сделать все через классы с наследованием. То есть делаешь класс, у него вирутальную функцию которая принимает на вход два аргумента. Потом для каждой операции создаешь класс унаследованный от первого и в нем переопределяешь функцию, которая выполняет нужное сравнение или операцию с этими двумя аргументами.
Дальше например в вектор пихаешь экземпляры этих классов в той же последовательности, что у тебя в комбобоксе. И тогда вся обработка у тебя будет сводится к следующему коду.
C++
1
2
3
vector<TOperation *> Vec;
...
bool bResult = Vec[i]->Compare(crvr, crvr1);
Т.е. если у меня 5 операций сравнения, то нужно создать 5 экземпляров класса TOperation, но у каждого будет своя операция сравнения? А как экземпляр класса "Операция" поймет какую операцию ему делать? Или при его инициализации задавать некий параметр отвечающий за тип операции? Как бы наоборот это сложнее не вышло )))

Цитата Сообщение от Croessmah Посмотреть сообщение
Можно использовать константы DOP_* как индексы/ключи в каком-нибудь контейнере(vector,map) в самом контейнере хранить указатели на функции/предикаты сравнения.
Ну от самих констант DOP_ я бы хотел уйти. Это смотрится криво и сделано на дефайнах, так как изначально функция юзалась в прошивке микроконтроллера и написано на чистом Си.

Название: Снимок экрана 2015-06-10 в 21.59.22.png
Просмотров: 69

Размер: 9.7 Кб

В данный момент все правила хранятся в двухмерном массиве. Один столбец тип операции сравнения, второй что сравнивать, третий - введеные данные и так далее. Все сделано для передачи по каналам связи этой инфы.
Я хочу сделать класс например "Rule", у которого будут уже параметры типа (operation1, value1 и так далее). И соответвенно наверное каждый экземпляр класса будет проверять не выполнились ли его условия и выставлять флаг что все выполнилось.
Вообще
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
10.06.2015, 22:38
Лучший ответ Сообщение было отмечено MasMaX как решение

Решение

Цитата Сообщение от MasMaX Посмотреть сообщение
Ну от самих констант DOP_ я бы хотел уйти.
я имел ввиду подобное:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <vector>
#include <functional>
 
bool foo ( int x1 , int x2 , int op )
{
    static std::vector< std::function<bool(int,int)> > operations = { std::less<int>() , std::greater<int>() } ;
    if ( op < 0 || op >= operations.size() )
        throw "bla-bla-bla" ;
    return operations[op](x1,x2) ;
}
 
 
int main ()
{
    int x1 = 0 ;
    int x2 = 0 ;
    int op = 0 ;
    std::cin >> x1 >> x2 >> op ;
    std::cout << foo (x1,x2,op) << std::endl ;
}
1
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71
10.06.2015, 22:49  [ТС]
Croessmah,
Про std::less честно говоря не знал. Сейчас почитал, там есть все нужные функции. Скорее всего так и сделаю, очень красивый вариант :-) "bla-bla" тут конечно лишнее, достаточно просто false вернуть.
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
10.06.2015, 22:54
Цитата Сообщение от MasMaX Посмотреть сообщение
"bla-bla" тут конечно лишнее, достаточно просто false вернуть.
Всё-таки false - это результат операции, а если такой операции нет, тогда Вам виднее что делать
0
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71
10.06.2015, 23:05  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
Всё-таки false - это результат операции, а если такой операции нет, тогда Вам виднее что делать
Проще вернуть false, если операция сравнения вернула false то никаких действий делать не надо. Если же кривой индекс или еще что то тоже ничего делать не надо молча просто :-) Ну это уже особенности программы не относящиеся к теме. Завтра утром начну внедрять код в прогу и отпишу получается или нет результат.
0
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71
15.06.2015, 14:02  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
я имел ввиду подобное
Получилось вот так у меня:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
bool
SportRule::Compare (int x1, int x2, int op)
{
    std::vector< boost::function<bool(int,int)> > operations;
 
    operations.push_back(std::equal_to<int>());
    operations.push_back(std::greater<int>());
    operations.push_back(std::less<int>());
    operations.push_back(std::greater_equal<int>());
    operations.push_back(std::less_equal<int>());
    operations.push_back(std::not_equal_to<int>());
 
    if ( op < 0 || op >= operations.size() )
        return false;
 
    return operations[op](x1,x2);
}
На std::function ругался, говорит нет такого. Видимо #include <functional> подцепил автоматически функции из буста (установлен в IDE он).
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.06.2015, 15:12
Цитата Сообщение от MasMaX Посмотреть сообщение
На std::function ругался, говорит нет такого.
появился в c++11
Цитата Сообщение от MasMaX Посмотреть сообщение
Получилось вот так у меня:
лучше где-то один раз инициализировать вектор, а не при каждом вызове Compare
0
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71
15.06.2015, 19:42  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
лучше где-то один раз инициализировать вектор, а не при каждом вызове Compare
Спасибо. Копировал сначала не глядя :-) Сделал вектор статическим для всех экземпляров класса, а push_back вынес в конструктор класса.

Кстати, а правильно ли сделал с конструктором? Не будет ли повторно вызываться пушбек при создании КАЖДОГО экземпляра класса? В итоге после 10 вызовов конструктора там будет не 8, а 80 элементов векторе. Или я не прав?

В итоге реализация сравнения уместилась в 60 строчек, вместо прежних 240 :-)
Может кому подобный код пригодится, вот весь функции сравнения.

Весь код функции сравнения


valueIndex[i] - выбранный индекс первого листбокса, где указано какие значения мы сравниваем
userData[i] - введенные юзером значения в текстовые поля
this->timeGoing - надо ли следить за временем (второй листбокс на скриншоте в начале темы)

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
void
SportRule::CheckRules()
{
    bool result[3];
    result[0] = false;
    result[1] = false;
    result[2] = false;
 
    bool resultGoing = false; // Сравниение идет время или нет
    int valueToCompare = -1;
    int timeIndex = 4; // Индекс в листбоксе когда идут временные параметры
 
    for (int i = 0; i < 3; i++) {
        switch(valueIndex[i])
        {
            case 1:
                valueToCompare = sportData->score1_;
                break;
            case 2:
                valueToCompare = sportData->score2_;
                break;
            case 3:
                valueToCompare = sportData->period_;
                break;
            case 4:
                valueToCompare = sportData->mainTimeInSec_;
                break;
            case 5:
                valueToCompare = sportData->breakTime_;
                break;
            case 6:
                valueToCompare = sportData->timeoutTimeInSec_;
                break;
            case 7:
                valueToCompare = sportData->atackTime_;
                break;
        };
        result[i] = this->Compare(valueToCompare, userData[i], operation[i]-1);
 
        // Если первое условие и ввбрано время то смотрим тикает ли оно
        if ((i == 0) && (valueIndex[i]>3)) {
            resultGoing = !(sportData->timeGoing_[valueIndex[i]-4] ^ this->timeGoing);
            result[i] = (result[i] && resultGoing);
        }
 
        result[i] = ( result[i] || (valueIndex[i] == 0) );
    }
 
    this->result = (result[0] && result[1] && result[2]);
}
 
bool
SportRule::Compare (int x1, int x2, int op)
{
    if ( op < 0 || op >= operations.size() )
        return false;
 
    return operations[op](x1,x2);
}


Добавлено через 44 минуты
Update:
Вынес operations в static переменную класса, инициализирую в конструкторе - получаю unresolved external error. Вообще надо с этим разобраться еще, ранее со статическими векторами не сталкивался…
0
Неэпический
 Аватар для Croessmah
18149 / 10731 / 2067
Регистрация: 27.09.2012
Сообщений: 27,035
Записей в блоге: 1
15.06.2015, 20:35
Цитата Сообщение от MasMaX Посмотреть сообщение
инициализирую в конструкторе - получаю unresolved external error
Как вариант:
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
//Заголовон .h
//...
class MyClass
{
//...
private:
//...
    static std::vector< boost::function<bool(int,int)> > operations ;
    static std::vector< boost::function<bool(int,int)> > operations_init() ;
} ;
 
 
//В каком-то .cpp
std::vector< boost::function<bool(int,int)> > MyClass::operations ( MyClass::operations_init() )  ;
 
std::vector< boost::function<bool(int,int)> > MyClass::operations_init()
{
    static bool already_init = false ;
    if (already_init==true)
        return operations ;
    already_init = true ;
    std::vector< boost::function<bool(int,int)> > result ;
    result.push_back(std::equal_to<int>());
    result.push_back(std::greater<int>());
    result.push_back(std::less<int>());
    result.push_back(std::greater_equal<int>());
    result.push_back(std::less_equal<int>());
    result.push_back(std::not_equal_to<int>());
    return result ;
}
1
 Аватар для MasMaX
8 / 8 / 2
Регистрация: 07.02.2012
Сообщений: 71
16.06.2015, 09:23  [ТС]
Croessmah, оказалось не правильно юзал статик-переменные. Надо их инициализировать вне конструтора вначале. В итоге получился такой код:

Заголовочный файл:
C++
1
2
3
4
5
class MyClass {
private:
    static std::vector< boost::function<bool(int,int)> > operations;
    static bool already_init;
};
Исполнящий файл (cpp):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::vector< boost::function<bool(int,int)> > MyClass::operations = {};
bool MyClass::already_init = false;
 
// Конструктор
MyClass::MyClass() {
    if (already_init == false)
    {
        already_init = true;
        operations.push_back(std::equal_to<int>());
        operations.push_back(std::greater<int>());
        operations.push_back(std::less<int>());
        operations.push_back(std::greater_equal<int>());
        operations.push_back(std::less_equal<int>());
        operations.push_back(std::not_equal_to<int>());
   }
}
И всё работает как надо!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.06.2015, 09:23
Помогаю со студенческими работами здесь

Как переопределить операции сравнения?
Подскажите пожалуйста, каким образом осуществляется переопределение операций &lt; и &gt;?

переопределение операции сложения вычетания сравнения
Создать железнодорожный состав и переопределить для него операции сложения, вычитания и сравнения на равенство.

Операции сравнения, объединения, пересечения множеств
Есть лаба про операции над множествами с помощью перегрузки операторов. Надо реализовать операции сравнения, обьединения, пересичения...

Реализация операции сравнения для длинных чисел
c++ Реализация операции сравнения для длинных чисел A&gt;=B Используя &quot;длинную арифметику&quot; помогите пожста

Отсортировать массив по возрастанию, не используя операции сравнения
Отсортировать массив из N элементов по возрастанию, не используя операции сравнения


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
1С: Контроль уникальности заводского номера
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере документа выдачи шин для спецтехники с табличной частью. Данные берутся из регистра сведений, по которому настроено. . .
Хочу заставить корпорации вкладываться в здоровье сотрудников: делаю мат модель здравосохранения
anaschu 22.03.2026
e7EYtONaj8Y Z4Tv2zpXVVo https:/ / github. com/ shumilovas/ med2. git
1С: Программный отбор элементов справочника по группе
Maks 22.03.2026
Установка программного отбора элементов справочника "Номенклатура" из модуля формы документа. В качестве фильтра для отбора справочника служит группа номенклатуры. Отбор по наименованию группы. . .
Как я обхитрил таблицу Word
Alexander-7 21.03.2026
Когда мигает курсор у внешнего края таблицы, и нам надо перейти на новую строку, а при нажатии Enter создается новый ряд таблицы с ячейками, то мы вместо нервных нажатий Энтеров мы пишем любые буквы. . .
Krabik - рыболовный бот для WoW 3.3.5a
AmbA 21.03.2026
без регистрации и смс. Это не торговля, приложение не содержит рекламы. Выполняет свою непосредственную задачу - автоматизацию рыбалки в WoW - и ничего более. Однако если админы будут против -. . .
1С: Программный отбор элементов справочника по значению перечисления
Maks 21.03.2026
Установка программного отбора элементов справочника "Сотрудники" из модуля формы документа. В качестве фильтра для отбора служит значение перечислений. / / Событие "НачалоВыбора" реквизита на форме. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru