Сравнение


В языке C++ (как и пожалуй во всех языках) есть такое понятие, как логическая величина, которая принимает два значения: правда и ложь, true и false, 1 и 0. В качестве типа данных по работе с логическими величинами у нас есть boolean, который может принимать значения 0 (false) или 1 (true). Точно такое же значение возвращает результат сравнения двух чисел или переменных, для сравнения у нас есть несколько операторов сравнения:

  • == равенство (a == b)
  • != неравенство (a != b)
  • >= больше или равно (a >= b)
  • <= меньше или равно (a <= b)
  • > больше (a > b)
  • < меньше (a < b)

В рассмотренных выше абстрактных примерах с a и b происходит следующее: скобка “возвращает” логическое значение, которое является результатом сравнения чисел. Например если у нас a = 10, b = 20, то скобка (a > b) вернёт значение false, потому что a меньше b. А например (a != b) вернёт true, т.к. а действительно не равно b. Для связи нескольких логических величин используются логические операторы:

  • ! логическое НЕ, отрицание. Например flag имеет значение true, тогда (!flag) уже будет false. Или, возвращаясь к предыдущим значениям a и b: (a > b) вернёт значение false, тогда как !(a > b) вернёт уже true, потому что мы инвертировали результат, поставив перед скобкой !
  • && логическое И. Например a – true, b – false. Тогда (a && b) будет false (так как b у нас false). Если a – true и b – true, то (a && b) будет true, так как a И b одновременно true
  • || логическое ИЛИ. Например a – true, b – false. Тогда (a || b) будет true, так как хотя бы один из них true. Если a – false и b – false, то (a || b) будет false.

Результаты операторов сравнения можно использовать для работы с условиями, а также для цикла while (речь о нём пойдёт в следующем уроке)

Условный оператор


Условный оператор if (англ. “если”) позволяет разветвлять выполнение программы в зависимости от логических величин, т.е. результатов работы операторов сравнения, которые мы рассмотрели выше, а также напрямую от логических переменных.

if (лог. величина) {
  // выполняется, если лог. величина - true
}

Оператор else (англ. “иначе”) работает в паре с оператором if и позволяет предусмотреть действие на случай невыполнения if:

if (лог. величина) {
  // выполняется, если лог. величина - true
} else {
  // выполняется, если лог. величина - false
}

Также есть третья конструкция, позволяющая ещё больше разветвить код, называется она else if:

if (лог. величина 1) {
  // выполняется, если лог. величина 1 - true
} else if (лог. величина 2) {
  // выполняется, если лог. величина 2 - true
} else {
  // выполняется иначе 
}

Посмотрим на все эти операторы в действии в большом примере:

// при выполнения одного действия 
// внутри условия, {} не обязательны
if (a > b) c = 10;  // если a больше b, то c = 10
else c = 20;        // если нет, то с = 20

// вместо сравнения можно использовать лог. переменную
boolean myFlag, myFlag2;
// если myFlag true, то c присвоить 10
if (myFlag) c = 10;

// сложные условия
// если оба флага true, то c присвоить 10
if (myflag && myFlag2) c = 10;

// при выполнении двух и более действий
// внутри условия, {} обязательны!
if (myFlag) {
  с = 10;
  b = c;
} else {
  с = 20;
  b = a;
}

byte buttonState;
if (buttonState == 1) a = 10;       // если buttonState 1
else if (buttonState == 2) a = 20;  // если нет, но если buttonState 2
else a = 30;                        // если и это не верно, то вот

Вот так и работает условный оператор if, позволяя управлять программой и создавать разветвлённые действия в зависимости от разных условий. Обратите внимание на последний блок в примере выше, там где используется else if для выбора действия в зависимости от значения одной и той же переменной. Существует оператор выбора, позволяющий сделать код более красивым

Оператор ?


Оператор знак вопроса (?) является более коротким аналогом для записи конструкции if-else. Действие с оператором ? имеет следующий вид:

условие ? выражение1 : выражение2

Это работает так: вычисляется условие, если оно истинно, то вычисляется выражение1 и всё действие получает это значение (возвращает), а если оно ложно, то вычисляется выражение2 и всё действие получает это значение. Пример:

byte a, b;
a = 10;

// если а < 9, b получает значение 200
// если а > 9, b получает значение 100
b = (a > 9) ? 100 : 200;

Вот для сравнения аналогичная конструкция на if-else

a = 10;
if (a > 9) b = 100;
else b = 200;

Аналогичным образом можно использовать оператор ? для вывода данных и текста в последовательный порт (подробнее о нём позже):

Serial.println((a > 9) ? "больше 9" : "меньше 9");

Оператор выбора


Оператор выбора switch позволяет создать удобную конструкцию, разветвляющую действия в зависимости от значения одной переменной. Синтаксис такой:

switch (значение) {
  case 0:
    // выполнить, если значение 0
    break;
  case 1:
    // выполнить, если значение 1
    break;
  case 2:
  case 3:
  case 4:
    // выполнить, если значение 2, 3 или 4
    break;
  default:
    // выполнить, если значение не совпадает ни с одним case
    break;
}

Наличие оператора default не обязательно. Наличие оператора break обязательно, иначе сравнение пойдёт дальше, как показано для case 2, 3 и 4. Рассмотрим более живой пример:

switch (val) {
  case 1:
  case 2:
  case 3:
  case 4:
    // выполнить, если val == 1, 2, 3 или 4
    break;
  case 5:
    // выполнить, если val == 5
    break;
}

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

Условные директивы #if #else


Помимо директивы #define, сообщающей препроцессору о необходимости замены набора символов набором символов, есть ещё условные директивы, позволяющие заниматься так называемой условной компиляцией: обладая такой же логикой, как if-else, данные конструкции позволяют делать некоторый выбор перед компиляцией самого кода. Отличным примером является само “ядро” Ардуино – большинство функций написаны со спецификой каждого процессора, и перед компиляцией кода из множества вариантов реализации функции выбирается тот, который соответствует текущему выбранному микроконтроллеру. Проще говоря, условная компиляция позволяет по условиям включать или исключать тот или иной код из основной компиляции, т.е. сначала препроцессор анализирует код, что-то в него включается, что-то нет, и затем проходит компиляция.

Также например мы не можем объявить какую-либо константу или макро через #define более одного раза, это приведёт к ошибке. Условная компиляция позволяет сделать ветвящуюся конструкцию, где такое возможно. Для условной компиляции нам доступны директивы #if, #elif, #else, #endif. Как ими пользоваться давайте посмотрим на примере:

#define TEST 1    // определяем TEST как 1
#if (TEST == 1)   // если TEST 1
#define VALUE 10  // определить VALUE как 10
#elif (TEST == 0) // TEST 0
#define VALUE 20  // определить VALUE как 20
#else             // если нет
#define VALUE 30  // определить VALUE как 30
#endif            // конец условия

Таким образом мы получили задефайненную константу VALUE, которая зависит от “настройки” TEST. Конструкция позволяет включать или исключать куски кода перед компиляцией, вот например кусочек про отладку:

#define DEBUG 1

void setup() {
#if (DEBUG == 1)
  Serial.begin(9600);
  Serial.println("Hello!");
#endif
}

Таким образом при помощи настройки DEBUG можно включить или исключить кусок кода.

Есть у препроцессора ещё две директивы: #ifdef, #ifndef, они позволяют включать или исключать участки кода по условию: ifdef – определено ли? ifndef – не определено ли? Определено или не определено – речь идёт конечно же о #define

#define TEST      // определяем TEST 

#ifdef TEST       // если TEST определено 
#define VALUE 10  // определить VALUE как 10 
#else             // если закоммент. #define TEST
#define VALUE 20  // определить VALUE как 20 
#endif            // конец условия

Видео


Важные страницы


  • Каталог ссылок на дешёвые Ардуины, датчики, модули и прочие железки с AliExpress у проверенных продавцов
  • Подборка библиотек для Arduino, самых интересных и полезных, официальных и не очень
  • Полная документация по языку Ардуино, все встроенные функции и макро, все доступные типы данных
  • Сборник полезных алгоритмов для написания скетчей: структура кода, таймеры, фильтры, парсинг данных
  • Видео уроки по программированию Arduino с канала “Заметки Ардуинщика” – одни из самых подробных в рунете
Сравнения и условия
5 (100%) 1 vote[s]

Последнее обновление Май 07, 2019
2019-05-07T11:31:33+03:00