Много вложенных if

askkostya
Offline
Зарегистрирован: 28.04.2020
Здравствуйте.
Пишу код для управления розетками через СМС.
 
С форматами команд решил следующее
 
Для получения текущего состояния розетки отправляю смс вида GX
где G-это команда получения статуса, Х - номер розетки (от 1 до 6)
Пример G1 получить состояние розетки 1
 
 
Для включения/выключения розетки отправляю смс вида SX/Y
где S - это команда включения или выключения, Х - номер розетки (от 1 до 6), Y-установить значение (0-выключить, 1-включить)
Пример S4/0 Выключить розетку 4
 
 
 
Конкретно для команд получилась вот такая вот портянка из if
Мне приходится посимвольно забирать каждый символ, проверять его на валидность и уже идти дальше
 
Можно как-то упростить код, есть какие-нибудь мысли ?
 
#define SMSSTATUS 'G'
#define SMSCOMMAND 'S'
#define ROZETKED 6 //Количество розеток


int getSMSMessage(String smsmessage)
{
 int powerNumber=0;
 int powerStatus=0;
  if (smsmessage.charAt(0) == SMSSTATUS)
  {
    //  ToDo;
  }
  if (smsmessage.charAt(0) == SMSCOMMAND)
  {
    if (isDigit(smsmessage.charAt(1)))
    {
       powerNumber = smsmessage.charAt(1)-'0';
      if (powerNumber > 0 && powerNumber <= ROZETKED)
      {
        if (smsmessage.charAt(2) == '/')
        {
          if (isDigit(smsmessage.charAt(3)))
          {
             powerStatus = smsmessage.charAt(3)-'0';
            if (powerStatus == 0 || powerStatus == 1)
            {
            //Мы в нужном месте и наконец можем переключить питание
            }
          }
        }
      }
    }
  }
  
}

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Инвертировать условия, по срабатыванию делать return. Будет покрасивее и уменьшится шанс запутаться в дереве.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

За парсер зачитай чонить

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А в чём проблема-то? Ифы - как ифы. В строке №14 else перед иф не хватает, а так, код как код. 

Хочется в одну строчку? Тогда сюда, только потом не жалуйтесь :-)

askkostya
Offline
Зарегистрирован: 28.04.2020

ЕвгенийП пишет:

А в чём проблема-то? Ифы - как ифы. В строке №14 else перед иф не хватает, а так, код как код. 

Хочется в одну строчку? Тогда сюда, только потом не жалуйтесь :-)

Для одной команды regexp это наверное слишком, а так надо попробовать :)
Да как бы проблем нет, даже работает все :)

 

kalapanga
Offline
Зарегистрирован: 23.10.2016

Мне почему-то бросилась в глаза такая вещь. С одной стороны проверок накручено много - например проверяется наличие слэша, осбого смысла не несущего. А с другой стороны - читаются символы по номеру в строке без проверки длины этой самой строки. Чего там этот charAt(x) вернёт?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

kalapanga пишет:

Чего там этот charAt(x) вернёт?

Ноль.

Если r-value, то просто ноль, а если l-value, то ссылку на место, в котором уже есть ноль и куда можно что-то записать.

alexbmd
Offline
Зарегистрирован: 15.01.2016

*чтобы не плодить темы уже спрошу тут*

Здравствуйте.
такая ситуация - тоже много if else if (но не вложенных)

if (flag == 2) {//заполняем массив}
else if (flag == 3) {//по другому заполняем массив}
else if (flag == 4) {//по другому заполняем массив}
и тд
в конце 
Serial.print(array);

но самый частый случай это когда flag==1 и для этого случая мы ничего не делаем с массивом а просто его печатаем. в данной реализации мы должны проверить все if и только потом распечатать самый частый случай.

если сделать так

if (flag == 1) {}
else if (flag == 2) {//заполняем массив}
else if (flag == 3) {//по другому заполняем массив}
else if (flag == 4) {//по другому заполняем массив}
и тд
в конце 
Serial.print(array);

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

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Можно и так, но в вашем случае, когда в if-ах нет условий посложнее, удобнее пользоваться switch..case - проще читается.

switch(flag) {
  case 2:
    // fill array for case 2
    break;
  case 3:
    // fill array for case 3
    break;
  default:
    // here case 1
    break;
}

Serial.println(array);

 

b707
Онлайн
Зарегистрирован: 26.05.2017
if (flag != 1) {
 if (flag == 2) {//заполняем массив}
 else if (flag == 3) {//по другому заполняем массив}
 else if (flag == 4) {//по другому заполняем массив}
}
Serial.print(array);

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

negavoid2 ну так тоже все пробегут пока до дефолта дойдём, хотя надо на асме посмотреть что получается...

вот как b707 получается то что надо

Green
Онлайн
Зарегистрирован: 01.10.2015

negavoid2 пишет:
...удобнее пользоваться switch..case - проще читается.

Предпочитаю так. Но некоторые считают такты.

  switch (key) {
    case KEY_CODE1:      on(PIN_R1); break;
    case KEY_CODE1_LONG: on(PIN_R0); break;
    case KEY_CODE2:      on(PIN_R2); break;
    case KEY_CODE3:      on(PIN_R3); break;
    case KEY_CODE4:      on(PIN_R4); break;
    case KEY_CODE4_LONG: on(PIN_R5); break;
  }

 

mixail844
Offline
Зарегистрирован: 30.04.2012

alexbmd пишет:

вот как b707 получается то что надо

еще можно так :

синтаксис не проверял , только показываю идею

typedef void (*Func_t)(char *arr , uint16_t len);

void printArray(char* arr, uint16_t len)
{
  serial.print(arr , len);
}

void modifyArray_1(char* arr, uint16_t len)
{
   for(uint16_t i = 0 ;i < len ;i++)
   {
       arr[i] = i ;
   }
}

void modifyArray_2(char* arr, uint16_t len)
{
   for(uint16_t i = 0 ;i < len ;i++)
   {
       arr[i] = i * i ;
   }
}

char dataArray[5] = {1 ,2, 3, 4, 5};


Func_t arraysFunc[3] = {printArray , modifyArray_1 , modifyArray_2} ; 


if(arraysFunc[flag])
     arraysFunc[flag](dataArray , sizeof(dataArray));

 

 

b707
Онлайн
Зарегистрирован: 26.05.2017

трудно выстрелить себе в ногу стотонным танком... но у некоторых получается

sadman41
Offline
Зарегистрирован: 19.10.2016

Что вы тут за задачи решаете, что свич нужно в asm-listingе смотреть? Прямо страшно становится...

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Очевидно, параноидальную экономию микросекунд :)

alexbmd
Offline
Зарегистрирован: 15.01.2016

negavoid2 еще раз посмотрел неправильно у вас. нужнобыло это

switch(flag) {
  case 2:
    // fill array for case 2
    break;
  case 3:
    // fill array for case 3
    break;}
// here case 1
Serial.println(array);

в асме не микрос хотел увидеть :) а разницу в коде. посмотрел разницы нет. он также пробегает все условия.  а хотелось проскочить все лишние условия. как мой второй пример или пример b707

Green
Онлайн
Зарегистрирован: 01.10.2015

Тяжелый случай.(

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Боджечки )) ну поставьте первым case 1:break; хотя раз неправильно, значит неправильно :)))))

b707
Онлайн
Зарегистрирован: 26.05.2017

Green пишет:

Тяжелый случай.(

это ж алекс...

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

negavoid2 пишет:

Боджечки )) ну поставьте первым case 1:break; 

https://www.youtube.com/watch?v=aw10753OJyg

SLKH
Offline
Зарегистрирован: 17.08.2015

alexbmd пишет:

  а хотелось проскочить все лишние условия. 

На хера? чтобы поскорее запустить неповоротливый (по сравнению с ифами и свитчами) сериалпринтлн ?  а после этого подать питание на чудовищно неповоротливое электромагнитное реле? 

Green
Онлайн
Зарегистрирован: 01.10.2015

b707 пишет:

это ж алекс...


...из прекрасной страны, где не едят солёных огурцов.) Думал исправился со временем.(

negavoid2
negavoid2 аватар
Offline
Зарегистрирован: 06.05.2020

Надо, alexbmd, надо! (с)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

negavoid2 пишет:

Надо, alexbmd, надо! (с)

Мож и надо, но метод не наш!