if-else switch

teodor4ik
Offline
Зарегистрирован: 04.11.2013

Вопрос на грани идиотизма:

Есть 2 подпрограммы запускающиеся IF зависимо от значения переменной (до 10 и больше 10). Переменная в процессе меняется и else ее отрабатывает запуская вторую подпрограмму. В саse есть break для такого гемора, но нету "диапазона", а только четкие значения. Как это обойти не вводя новую переменную для кейса?

Чую что туплю, но не могу понять где.

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

return

teodor4ik
Offline
Зарегистрирован: 04.11.2013

 if (menuItem < 10) {SelMSG();return;} else SelSubMSG();  

Так? Не работает. Точнее работает но как-то странно.

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

teodor4ik пишет:

Переменная в процессе меняется и else ее отрабатывает запуская вторую подпрограмму. 

Т.е.

1. сработал IF по истите
2. В процессе отработки истины поменялась флаговая переменная 
3. и это вызвало отработку ELSE того же IF'а?

Я правильно понял?

Еслии правильно, то так НЕ БЫВАЕТ - ищите ошибку в другом! Где-то фигурная скобка не на месте, где-то ещё что-то. Уберите всю фигню, оставьте чистый пример, печатайте отладочную информацию, - ищите. Так не бывает.

Кстати, а где кусок кода?

teodor4ik
Offline
Зарегистрирован: 04.11.2013
String inputString = "";
boolean stringComplete = false;
uint8_t menuItem=0;
void setup() {
  Serial.begin(9600);
  inputString.reserve(40);
  PrintMSG();
}
void loop()
 {  if (stringComplete) {
  if (menuItem < 10) SelMSG();
  else SelSubMSG();
 inputString = "";
 stringComplete = false;  }
}
void serialEvent() {                               // отлавливает ввод
 while (Serial.available()) {
    char inChar = (char)Serial.read();
    inputString += inChar;
    if (inChar == '\n') {
      stringComplete = true;
    }
   }
}
// набор сообщенийv
oid PrintMSG(){
switch (menuItem) {    
case 0:
        Serial.println ("Sho delat?");
        Serial.println ("? - What?");
        Serial.println ("1 - set clock, now:");
        Serial.println ("2 - set timers, now:");
        Serial.println ("3 - set pump delay, now:");
        Serial.println ("4 - set port inverse, now:");
        Serial.println ("5 - set period, now:");
        break;
    case 1:
      Serial.println ("input time in format: HH:MM:SS");
      break;
    case 2:
      Serial.println ("input timer1 in format: HH:MM:SS");
      break;
    case 3:
      Serial.println ("input delay in format: MM:SS");
      break;
    case 4:
      Serial.println ("port1 inverted: Y|N");
      break;
    case 5:
      Serial.println ("Input period in format: MM:SS");
      break;
    case 11:
      Serial.println ("Time is set to:");
      break
;    case 21:
      Serial.println ("Timer1 is set to:");
        Serial.println ("input timer2");
      break;
    case 22:
      Serial.println ("Timer2 is set to:");
      break;
    case 31:
      Serial.println ("Pump delay is set to:");
      break;
    case 41:
      Serial.println ("Inversion on port1 is set to:");
        Serial.println ("port2 inverted: Y|N");
      break;
    case 42:
      Serial.println ("Inversion on port is set to:");
      Serial.println ("port3 inverted: Y|N");
      break;
    case 43:
      Serial.println ("Inversion on port3 is set to:");
        Serial.println ("port4 inverted: Y|N");
      break;
    case 44:
      Serial.println ("Inversion on port4 is set to:");
        Serial.println ("port5 inverted: Y|N");
      break;
    case 45:
      Serial.println ("Inversion on port5 is set to:");
      break;
    case 51:
      Serial.println ("Period is set to:");
      break;
  }
}
// отображаем сообщение, ждем параметров
void SelMSG ()
{  
switch (inputString[0]){    
  case '?':
    menuItem=0;
    PrintMSG();
    break;
    case '1':
    menuItem=1;
    PrintMSG();
    menuItem=11;
     break;
    case '2':
    menuItem=2;
    PrintMSG();
    menuItem=21;
    break;
    case '3':
    menuItem=3;
    PrintMSG();
    menuItem=31;
    break;
    case '4':
    menuItem=4;
    PrintMSG();
    menuItem=41;
    break;
    case '5':
    menuItem=5;
    PrintMSG();
    menuItem=51;
    break;
  }
}
// обрабатываем параметры выдаем подтверждение.
void SelSubMSG (){
  if (menuItem == 11){
    PrintMSG();
    menuItem=0;
  }
  if (menuItem == 22){
    PrintMSG();
    menuItem=0;
      }
  if (menuItem == 21){
       PrintMSG();
    menuItem=22;
      }
  if (menuItem == 31){
    PrintMSG();
    menuItem=0;
      }
  if (menuItem == 45){
    PrintMSG();
    menuItem=0;
      }
  if (menuItem == 44){
    PrintMSG();
    menuItem=45;
      }
  if (menuItem == 43){
      PrintMSG();
    menuItem=44;
      }
  if (menuItem == 42){
     PrintMSG();
    menuItem=43;
      }
  if (menuItem == 41){
    PrintMSG();
    menuItem=42;
      }
  if (menuItem == 51){
      PrintMSG();
    menuItem=0;
      }
}

 

Patriot
Offline
Зарегистрирован: 25.06.2015

Ты бы хоть указал в каких строчках проблема.

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

 

 

teodor4ik
Offline
Зарегистрирован: 04.11.2013

Трабл в лупе.

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

Я правильно понял?

Еслии правильно, то так НЕ БЫВАЕТ

Проверил...

И правда не бывает...

но конструкция такого типа:

  if (menuItem < 10) subMenu=0; else subMenu=1;   
  if (subMenu == 0) SelMSG(); else SelSubMSG();  

помогла... Бред...

А вообще можете обхаять данный кусок? насколько так правильно-неправильно писать.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Только то, что на глаза попало.

Строки 124-166, лучше писать if - else - if - else (впрочем здесь switch тоже подходит). Во первых - это быстрее, не будет миллиона проверок, во-вторых, порядок проверки условий более понятный, тем более у Вас меняется значение переменной и можно влететь в ситуацию, где сработают два ифа, а потом удивляться.

Если использовать switch, то можно съэкономить и код, если он повторяется, типа так:

switch(menuItm) {
case 11:
case 22:
   blah-blafh-blah;
   break;
case 12:
   blah-blafh-blah;
   break;
default:
   blah-blafh-blah;
   break;
}

Можно еще съэкономить на ветках 22, 41-44, если сделать menuItem++;

switch(menuItem) {
case 11:
case 22:
case 31:
case 45:
case 51:
  PrintMSG();
  menuitem = 0;
  break;
case 21:
case 44:
case 43:
case 42:
case 41:
  PrintMSG();
  menuitem++;
  break;

Однако нужно помнить, что такой подход требует бОльшего внимания, иначе будете разгребать глюки.

На первых порах я бы предложил воспользоваться конструкцией if - else - if - else.

 

teodor4ik
Offline
Зарегистрирован: 04.11.2013

еще 1 затуп:

при inputString= "19" или "23" 

byte  value=inputString[0]*10+inputString[1]-16;

value==19  или 23...

Почему -16 ?

 

 

 

 

teodor4ik
Offline
Зарегистрирован: 04.11.2013

kisoft пишет:

Только то, что на глаза попало.

Большое спасибо, кейсы там и были, но в поиске глюков перепилил почем зря, не поняв сути брейка :)

++ и правда там логичнее и нагляднее, т.к. переводит к следующему полю ввода из той же менюшки. Опять же спасибо.

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

А чего тут хаять? Если Вам кажется, что в строках 11 и 12 вызываются ОБЕ функции, значит они вызываются при разных вызовах loop(). В одном и том же проходе они обе вызываться не могут.

teodor4ik
Offline
Зарегистрирован: 04.11.2013

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

А чего тут хаять? Если Вам кажется, что в строках 11 и 12 вызываются ОБЕ функции, значит они вызываются при разных вызовах loop(). В одном и том же проходе они обе вызываться не могут.

Не могут, уже согласен, проверил сам на простеньком примерчике... Но выше уровнем условие прихода "/n" с сериала. Его "не заметить" невозможно, строку не правлю нигде, чистится на каждом проходе безо всяких условий.  Возможно коряво прыгаю по ф-ям, но тогда бы не помогла затычка что выше... Короче я забил. Так работает... Сейчас больше напрягает:\

byte  value=inputString[0]*10+inputString[1]-16;

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

teodor4ik пишет:

Сейчас больше напрягает:\

byte  value=inputString[0]*10+inputString[1]-16;

Или Вы думаете, я что-то понял? Таки нет!

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

teodor4ik пишет:

byte  value=inputString[0]*10+inputString[1]-16;

А чего не inputString.toInt()? Или как то так, не пользуюсь этим классом.

Вообще может быть алгоритм и корректный (никогда такого изврата не видел). Но нужно, чтобы число состояло точно из двух цифр. Чтобы перевести символ '1' в число 1 нужно вычесть 0x30 или обрезать 4 старших бита, или вычесть 48, или вычесть '0'.

Т.е. тупо, без оптимизации (говнокодом):

byte  value=(inputString[0] - '0')*10+(inputString[1] - '0');

или так:

byte  value=(inputString[0] & 0xF)*10+(inputString[1] & 0xF);

 

 
teodor4ik
Offline
Зарегистрирован: 04.11.2013

Я понимаю что так не бывает, но оно работает!

А не... догнал проикол... например 00:

(48)*10+48=528, младший байт = 16, тоесть отняв от него 16 поимеем 0 :)

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

kisoft пишет:

А чего не inputString.toInt()? Или как то так, не пользуюсь этим классом.

Я им тоже не умею пользоваться. Кроме того строка значительно длиннее, и вырезать из нее нужные куски долго и муторно. Формируется она автоматом и при ошибке срс передается по новой, то-есть особой инвариантности там не предусмотрено. Все значения двузначны.

Но думаю что попробую все ж упростить. :)

Ну и, если не сложно. Как это оптимизировать?

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Если такой алгоритм работает, то зачем парить мозг, пусть так и продолжает работать.

 

teodor4ik
Offline
Зарегистрирован: 04.11.2013

Опять грабли...

Есть мега2560 уходящая в бутлуп от собаки. Обидно.

Перенес все на очень китайскую дуню RTC отказался работать. Полез щупать пины рс4, рс5 на камень: звонятся... Нашел там нереференсные ноги CSL/SDA, подцепился к ним. Ничего. Пошел читать как поменять бутлодер на меге...

Утром вспомнил что именно эти часы точно на такой же работали... Выколупал из пакетика новую. Включил, залил... Скотина, работает... Перекинул на первую. Нихрена. Подергал пинами, дергаются. А часы нет... Чо за нахрен?

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