Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.97/35: Рейтинг темы: голосов - 35, средняя оценка - 4.97
 Аватар для nullpointer
48 / 48 / 14
Регистрация: 30.03.2009
Сообщений: 523

Избавиться от большого количества else-if

28.07.2015, 12:05. Показов 7590. Ответов 40
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Есть необходимость сравнения одной строки с другими. Использую конструкцию if-else if. Но таких сравнений довольно много и такое количество if'ов мне не нравится.
C++ (Qt)
1
2
3
4
if(str == st1){...}
else if(str == st2){...}
...
else if(str == stn){...}
Хотелось бы заменить это все дело на switch-case, но он естественно не работает с типом QString. Что посоветуете в данной ситуации? Я пока что придумал только так:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
QStringList list;
list << st1 << st2 << ... << stn;
 
switch(list.indexOf(str)
{
   case 0: ...
   case 1: ...
    ...
   case n: ...
}
Какие будут ваши советы?

P.S. Форматирование может хромать, т.к. пишу с телефона.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
28.07.2015, 12:05
Ответы с готовыми решениями:

Избавиться от большого количества обработчиков
Господа, есть такая проблема... Имеется главный index.php файл, он же основной контроллер. Он, как и полагается, разбирает урлик,...

Как избавиться от переполнения памяти при очистке большого html файла?
Всем привет. Имею текстовый фаил объемом 100 мегабайт. В html коде. Там большой набор статичтических данных. Начинаю его чистить выдает...

Создание большого количества переменных
Как создать много переменных с именами типа var1 var2 var3 var4 var5? Чтобы имена одинаковые, но цифры в конце разные.

40
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
29.07.2015, 09:52
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Kurles Посмотреть сообщение
и как это поможет избавиться от большого кол-ва if'ов? Этим ты только индекс элемента находишь, но для этого можно было
Код C++ (QT)
Индекс элемента имеет числовой тип и может быть использован в операторе switch. case же выглядят гораздо приличней, чем else if, быстро и с не понятной целью уводящие левую границу текста далеко за правую границу экрана. Но я предлагаю избавиться и от case тоже, все же указатели можно сложить в массив уже при его декларации.
0
Pied Piper
 Аватар для ArmanPrestige
237 / 228 / 57
Регистрация: 15.01.2013
Сообщений: 855
29.07.2015, 09:58
Q_ENUM and how to switch on QString
0
161 / 126 / 30
Регистрация: 30.05.2015
Сообщений: 380
29.07.2015, 10:03
Цитата Сообщение от alexu_007 Посмотреть сообщение
Хочешь в фигурных скобках обрабатывай, хочешь функцию вызывай, хочешь - что хочешь.
А как узнать, что в скобках обрабатывать? Как узнать какую функцию вызывать? Что вообще этот найденый индекс дать-то может? И чем этот вариант лучше
C++ (Qt)
1
2
3
4
int idx = list.indexOf(str);
if (idx >=0 ) {
   //...
}
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
29.07.2015, 10:05
Кстати, если для каких то целей необходимо, чтоб строки не были элементами массива, то в массив можно сложить указатели на них, причём, тоже сразу в его декларации. Идеально было бы сложить туда не указатели, а ссылки, но
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main()
{
 int i;
 int j;
 int t;
 int &a[3]={i, j, t};
 size_t k;
 for (k=0; k<3; ++k)
 {
  a[k]=k;
 }
 std::cout<<"i="<<i<<std::endl;
 std::cout<<"j="<<j<<std::endl;
 std::cout<<"t="<<t<<std::endl;
 return 0;
}
пишет
C:\Projects\Test12\Test12\Test12\Test.cp p|11|error: declaration of 'a' as array of references|
, что и понятно.
0
 Аватар для nullpointer
48 / 48 / 14
Регистрация: 30.03.2009
Сообщений: 523
29.07.2015, 10:06  [ТС]
Попробовал с указателями на функцию. Не работает. Не получается заполнить хэш указателями на функции, если эти функции являются членами класса.
0
161 / 126 / 30
Регистрация: 30.05.2015
Сообщений: 380
29.07.2015, 10:11
Цитата Сообщение от taras atavin Посмотреть сообщение
Но я предлагаю избавиться и от case тоже, все же указатели можно сложить в массив уже при его декларации.
И хранить два массива? И задолбаться при синхронизации значений обоих массивов при большом количестве элементов? Очень плохо поддерживаемая конструкция, как по мне. И не очень быстрая при большом количестве элементов.
0
 Аватар для taras atavin
4226 / 1796 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
29.07.2015, 10:18
Цитата Сообщение от Kurles Посмотреть сообщение
И чем этот вариант лучше
Код C++ (QT)
1
2
3
4
int idx = list.indexOf(str);
if (idx >=0 ) {
//...
}
Тем, что существует только в твоём воображении. А на самом деле не
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
idx = list.indexOf(str);
if (idx>=0)
{
 if (idx==0)
 {
 }
 else if (idx==1)
      {
      }
      else if (idx==2)
           {
           }
           else if (idx==3)
                {
                }
                else if (idx==4)
                     {
                     }
                     else if (idx==5)
                          {
                          }
                          else if (idx==6)
                               {
                               }
                               else if (idx==7)
                                    {
                                    }
                                    else if (idx==8)
                                         {
                                         }
                                         else if (idx==9)
                                              {
                                              }
                                              else if (idx==10)
                                              {
                                              }
                                              else if (idx==11)
                                                   {
                                                   }
                                                   else if (idx==12)
                                                        {
                                                        }
                                                        else if (idx==13)
                                                        {
                                                        }
                                                        else if (idx==14)
                                                             {
                                                             }
                                                             else if (idx==15)
                                                                  {
                                                                  }
                                                                  else if (idx==16)
                                                                       {
                                                                       }
                                                                       else if (idx==17)
                                                                            {
                                                                            }
                                                                            else if (idx==18)
                                                                                 {
                                                                                 }
                                                                                 else if (idx==19)
                                                                                      {
                                                                                      }
                                                                                      else if (idx==20)
                                                                                           {
                                                                                           }
                                                                                           else if (idx==21)
                                                                                                {
                                                                                                }
                                                                                                else if (idx==22)
                                                                                                     {
                                                                                                     }
                                                                                                     else if (idx==23)
                                                                                                          {
                                                                                                          }
, а
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
idx = list.indexOf(str);
swicth
{
 case 0:
 break;
 case 1:
 break;
 case 2:
 break;
 case 3:
 break;
 case 4:
 break;
 case 5:
 break;
 case 6:
 break;
 case 7:
 break;
 case 8:
 break;
 case 9:
 break;
 case 10:
 break;
 case 11:
 break;
 case 12:
 break;
 case 13:
 break;
 case 14:
 break;
 case 15:
 break;
 case 16:
 break;
 case 17:
 break;
 case 18:
 break;
 case 19:
 break;
 case 20:
 break;
 case 21:
 break;
 case 22:
 break;
 case 23:
 break;
}
.

Добавлено через 1 минуту
Цитата Сообщение от Kurles Посмотреть сообщение
И хранить два массива? И задолбаться при синхронизации значений обоих массивов при большом количестве элементов?
Да где ж там долбаться то? Но если охота одного массива, то можно в него сложить структуры, один член - строка, или указатель на неё, второй - указатель на функцию.
0
161 / 126 / 30
Регистрация: 30.05.2015
Сообщений: 380
29.07.2015, 10:24
Цитата Сообщение от nullpointer Посмотреть сообщение
Попробовал с указателями на функцию. Не работает. Не получается заполнить хэш указателями на функции, если эти функции являются членами класса.
Плохо пробовал.
C++ (Qt)
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
#include <QCoreApplication>
 
#include <QDebug>
 
class Tester {
 
    typedef void (Tester::*handlerFunc)(QString);
 
public:
    Tester() {
        mHandlers["str1"] = &str1Handler;
        mHandlers["str2"] = &str2Handler;
    }
 
    void str1Handler(QString value) {
        qDebug() << Q_FUNC_INFO << value;
    }
 
    void str2Handler(QString value) {
        qDebug() << Q_FUNC_INFO << value;
    }
 
    void defaultHandler(QString value) {
        qDebug() << Q_FUNC_INFO << value;
    }
 
    void switchReplacement(const QString &swithValue, const QString &additionalData) {
        handlerFunc func = mHandlers.value(swithValue, 0);
        if (func) {
            (this->*func)(additionalData);
        } else {
            defaultHandler(additionalData);
        }
 
    }
 
private:
    QHash<QString, handlerFunc> mHandlers;
};
 
int main(int , char **)
{
    Tester tester;
    tester.switchReplacement("str1", "test1");
    tester.switchReplacement("str2", "test2");
    tester.switchReplacement("str3", "test3");
 
    return 0;
}
Добавлено через 3 минуты
Цитата Сообщение от taras atavin Посмотреть сообщение
Но если охота одного массива, то можно в него сложить структуры, один член - строка, или указатель на неё, второй - указатель на функцию.
Для этого существуют контейнеры, хранящие пару "ключ-значение(я)", и работающие быстрее твоего варианта.
0
 Аватар для nullpointer
48 / 48 / 14
Регистрация: 30.03.2009
Сообщений: 523
29.07.2015, 12:14  [ТС]
У меня вот так сделано:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Test : public QObject
{
   Q_OBJECT
public:
   Test();
   ~Test();
 
   void func(QVariantList lst);
private:
   typedef void (*Func)(QVariantList params);
   QHash<QString, Func> hash;
};
 
Test::Test()
{
   hash["fun"] = &func;
}
Ругается на &. Он его применяет почему-то не к указателю, а к типу Test::
0
161 / 126 / 30
Регистрация: 30.05.2015
Сообщений: 380
29.07.2015, 12:58
потому что у тебя указатель на функцию, а не на метод класса Test.
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2015, 13:41
Цитата Сообщение от nullpointer Посмотреть сообщение
Я правильно понимаю?
Да. Только вероятно стоит проверять кол-во параметров и их тип.

Цитата Сообщение от nullpointer Посмотреть сообщение
C++ (Qt)
1
2
3
4
5
6
7
8
QString com = str.section("/",1); 
QVariantList lstParam;
lstParam << str.section("/",2,2).toInt() << str.section("/",3,3) << ... << str.section("/", n, n);
 QHashIterator<QString, int> i(hashMap);
 while (i.hasNext()) 
{ i.next(); if (i.key() == com) 
{ hashMap[com](lstParam); break; }
 }
Гавно код. Почитайте про хеш.

C++ (Qt)
1
2
3
4
void Parse(const QString& str,const QVariantList& params)
{
  hashMap[str](params);
}
Добавлено через 2 минуты
Цитата Сообщение от nullpointer Посмотреть сообщение
Ругается на &. Он его применяет почему-то не к указателю, а к типу Test::
Понятно, понту с тобой возиться нет, иди читай книгу по основам С++ а именно указатели на ф-ции, и указатели на функцию-член класса.
0
29.07.2015, 13:48

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Понятно, понту с тобой возиться нет, иди читай книгу по основам С++ а именно указатели на ф-ции, и указатели на функцию-член класса.
:D :D

0
161 / 126 / 30
Регистрация: 30.05.2015
Сообщений: 380
29.07.2015, 14:14
Цитата Сообщение от Avazart Посмотреть сообщение
Гавно код. Почитайте про хеш.
C++ (Qt)
1
2
3
4
void Parse(const QString& str,const QVariantList& params)
{
  hashMap[str](params);
}
А где проверка на наличие ключа? Если ключа нет, в данном случае вызовется метод, на который указывает нулевой (или вообще случайный) указатель, что приведёт к undefined behavior.
тогда уж так писать:
C++ (Qt)
1
2
3
4
void Test::Parse(const QString& str,const QVariantList& params)
{
  (this->*hashMap.value(str, &defaultHandler))(params);
}
0
Эксперт С++
 Аватар для Avazart
8489 / 6156 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2015, 14:27
Kurles, По ситуации, но конечно лучше проверять через find() или contains() сначала.
0
 Аватар для nullpointer
48 / 48 / 14
Регистрация: 30.03.2009
Сообщений: 523
29.07.2015, 18:27  [ТС]

Не по теме:

Цитата Сообщение от Avazart Посмотреть сообщение
Понятно, понту с тобой возиться нет, иди читай книгу по основам С++ а именно указатели на ф-ции, и указатели на функцию-член класса
:D
Ушел читать.


Цитата Сообщение от Avazart Посмотреть сообщение
вероятно стоит проверять кол-во параметров и их тип
Изначально все параметры в виде QString, а уже при заполнении полей структуры делаю приведение к нужному типу.
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
void Test::func1(QStringList lst)
{
        if (0 == lst.size())
              return;
    struct1.field1 = lst[0];
    struct1.field2 = lst[1].toInt();
    struct1.field3 = lst[2];
    struct1.field4 = lst[3].toDouble();
    ...
}
Цитата Сообщение от Avazart Посмотреть сообщение
По ситуации, но конечно лучше проверять
Вот такую проверку придумал или лучше как-то по-другому ее реализовать?
C++ (Qt)
1
2
3
4
5
6
7
8
9
void Test::Parse(QString str)
{
    QString com = str.section("/", 2, 2);
    QStringList params = str.split("/");
    if (hashMap.contains(com))
    {
        hashMap[com](params);
    }
}
0
161 / 126 / 30
Регистрация: 30.05.2015
Сообщений: 380
29.07.2015, 18:58
Цитата Сообщение от nullpointer Посмотреть сообщение
Вот такую проверку придумал или лучше как-то по-другому ее реализовать?
Если скорость критична, то можно немного оптимизировать.
C++ (Qt)
1
2
3
4
5
6
7
8
9
void Test::Parse(QString str)
{
    QString com = str.section("/", 2, 2);
    QStringList params = str.split("/");
    auto func = hashMap.value(com, 0);
    if (func) {
        func(params);
    }
}
В этом случае поиск будет выполняться один раз вместо двух.
0
0 / 0 / 0
Регистрация: 08.07.2015
Сообщений: 18
19.01.2016, 16:29
Если компилятор поддерживает новые фишки то можно объявить макросы SWITCH и CASE:
C++ (Qt)
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
#ifndef STR_SWITCH_H
#define STR_SWITCH_H
 
#include <string>
 
#define SWITCH(str)  switch(s_s::str_hash_for_switch(str))
#define CASE(str)    static_assert(s_s::str_is_correct(str) && (s_s::str_len(str) <= s_s::MAX_LEN),\
"CASE string contains wrong characters, or its length is greater than 9");\
case s_s::str_hash(str, s_s::str_len(str))
#define DEFAULT  default
 
namespace s_s
{
    typedef unsigned char uchar;
    typedef unsigned long long ullong;
 
    const uchar MAX_LEN = 9;
    const ullong N_HASH = static_cast<ullong>(-1);
 
    constexpr ullong raise_128_to(const uchar power)
    {
        return 1ULL << 7 * power;
    }
 
    constexpr bool str_is_correct(const char* const str)
    {
        return (static_cast<signed char>(*str) > 0) ? str_is_correct(str + 1) : (*str ? false : true);
    }
 
    constexpr uchar str_len(const char* const str)
    {
        return *str ? (1 + str_len(str + 1)) : 0;
    }
 
    constexpr ullong str_hash(const char* const str, const uchar current_len)
    {
        return *str ? (raise_128_to(current_len - 1) * static_cast<uchar>(*str) + str_hash(str + 1, current_len - 1)) : 0;
    }
 
    inline ullong str_hash_for_switch(const char* const str)
    {
        return (str_is_correct(str) && (str_len(str) <= MAX_LEN)) ? str_hash(str, str_len(str)) : N_HASH;
    }
 
    inline ullong str_hash_for_switch(const std::string& str)
    {
        return (str_is_correct(str.c_str()) && (str.length() <= MAX_LEN)) ? str_hash(str.c_str(), str.length()) : N_HASH;
    }
}
 
#endif // STR_SWITCH_H
Пример использования:
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    SWITCH(element) // не забывать что длинна элемента <=9
        {
            CASE ("id"):
                id = xml.text().toInt();
                break;
            CASE ("code"):
                code = xml.text().toInt();
                break;
            CASE ("ico"):
                ico = xml.text().toInt();
                break;
            CASE ("idDate"):
                idDate = xml.text().toInt();
                break;
            CASE ("isPub"):
                isPub = xml.text().toInt();
                break;
            CASE ("isRss"):
                isRss = xml.text().toInt();
                break;
            CASE ("isWarn"):
                isWarn = xml.text().toInt();
                break;
....
0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,316
19.01.2016, 21:01
Цитата Сообщение от Kurles Посмотреть сообщение
Сообщение от alexu_007 Посмотреть сообщение
Хочешь в фигурных скобках обрабатывай, хочешь функцию вызывай, хочешь - что хочешь.
А как узнать, что в скобках обрабатывать? Как узнать какую функцию вызывать? Что вообще этот найденый индекс дать-то может? И чем этот вариант лучше
А как switch-case поможет узнать, какую функцию вызывать? А как if-else поможет? Очевидно автор вопроса знает, какие действия предпринять в случае равенства, вопрос был о том, как убрать большое количество if-else при сравнении, например, ста строк? Ответ элементарный - сравнивать в цикле. А вы о чём?
0
0 / 0 / 0
Регистрация: 08.07.2015
Сообщений: 18
20.01.2016, 02:27
Цитата Сообщение от alexu_007 Посмотреть сообщение
А вы о чём?
В первом вопросе автор пишет

Цитата Сообщение от nullpointer Посмотреть сообщение
Хотелось бы заменить это все дело на switch-case, но он естественно не работает с типом QString.
в стандарте C++11 появилась возможность реализовать эту конструкцию, с рядом ограничений... "Она основана на constexpr-функциях из C++11..." см. подробнее: http://habrahabr.ru/post/166201/

Использование подобных макросов весьма удобно.
0
737 / 704 / 110
Регистрация: 29.05.2015
Сообщений: 4,316
20.01.2016, 08:42
Цитата Сообщение от RustAlex Посмотреть сообщение
В первом вопросе автор пишет
Хотелось бы заменить это все дело на switch-case, но он естественно не работает с типом QString.
В первом же вопросе автор пишет:
Есть необходимость сравнения одной строки с другими. Использую конструкцию if-else if. Но таких сравнений довольно много
А если таких сравнений несколько десятков тысяч, как вам тут поможет С++11 и switch-case?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
20.01.2016, 08:42

Хранение большого количества файлов
Есть свой видео-хостинг типа ютуба, и вот такой вопрос возник. Как мне организовать хранение файлов в файловой системе так, чтоб потом...

Считывание большого количества данных
Есть такой код: int main() { int n; FILE *fin fin = fopen(&quot;b.in&quot;, &quot;r&quot;); fscanf(fin, &quot;%d %d %d %d %d %d %d %d %d %d %d %d %d %d...

Удаление большого количества строк
Помогите начинающей, подскажите, пожалуйста, как избежать ошибки при удалении тысяч строк? Выдается 'Timeout Expired'. Сотни строк...

Чтение большого количества файлов
Всем привет. Возможно ли прочитать сразу огромное количество файлов? cat test/123/*/*.log - выдает сообщение о превышении количества...

Массив из большого количества кнопок
Добрый день! Как понятно из названия, хочу создать массив из большого количества кнопок, 100 например. Нагуглила вот что: int...


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
Создание формы заимствованного документа
Maks 03.08.2026
Задача: Необходимо создать собственную форму заимствованного документа. На форме должен быть реквизит "Покупатель", а также табличная часть со следующими реквизитами: - Расчетный счет покупателя. . .
Задача предоставления скидок покупателям
Maks 03.08.2026
Задача: В документе "Продажи" необходимо реализовать функционал предоставления скидок покупателям. Скидка должна автоматически рассчитываться и подставляться в соответствующее поле при выборе. . .
Почему SEO не начинается с ключевых слов: что проверить до написания текстов
Neotwalker 01.08.2026
Когда владельцу сайта предлагают заняться SEO, первым шагом часто становится сбор запросов и написание текстов. Логика кажется понятной: 1. Находим ключевые слова. 2. Добавляем их на. . .
Знание — сила: Доктрина интенциональности знаний, углубление в формулу
Hrethgir 01.08.2026
https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11957&stc=1&d=1785567302 Знаменитый афоризм Фрэнсиса Бэкона «Знание — сила» (Scientia potentia est) в массовой культуре принято понимать. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru