Конструкция ветвления

Робот получает разные данные и должен выбирать разные действия. Если путь свободен — ехать, если впереди препятствие — остановиться или повернуть. В C++ такой выбор записывают конструкциями if, else if и else. Они направляют выполнение по одной из предусмотренных ветвей.
if выполняет блок, когда условие истинно. Связанный else выполняет альтернативный блок, когда условие ложно. Цепочка else if проверяет варианты сверху вниз и выбирает первую истинную ветвь. Сравнения дают значение типа bool, а логические операторы объединяют несколько признаков.
Зачем это нужно
Без ветвления скетч повторяет одинаковые команды независимо от окружающей среды. Условия превращают измерения и команды в поведение:
- кнопка нажата — начать учебный тест;
- расстояние меньше порога — остановиться;
- оба датчика линии видят фон — искать линию;
- заряд ниже заданного уровня — запретить движение;
- пришёл символ остановки — выключить команды приводам.
На hero один упрощённый робот передаёт результат датчика в ромб решения. Оранжевый и мятный пути обозначают взаимоисключающие результаты одной проверки: остановиться либо продолжить маршрут вокруг препятствия. Это алгоритмические линии, не электрическая схема.
Ясные ветви нужны не только программе, но и испытанию. Для каждого условия можно подобрать входные значения, записать ожидаемое действие и сравнить его с фактическим. Так решение становится проверяемым до подключения мощного привода.
Главная идея
Условие — выражение, которое даёт true или false. Если оно истинно, выполняется тело if. Иначе программа пропускает этот блок и, если предусмотрен else, выполняет альтернативу.
const int distanceCm = 14;
void setup() {
Serial.begin(9600);
}
void loop() {
if (distanceCm < 20) {
Serial.println("stop");
} else {
Serial.println("move");
}
delay(500);
}
Здесь в каждом проходе выбирается ровно одна из двух ветвей. После выбранного блока выполнение продолжается со следующей инструкцией — delay(500).
| Результат условия | Выполняется | Не выполняется |
|---|---|---|
true | блок if | связанный блок else |
false | связанный блок else | блок if |
Сравнения
Показание датчика обычно сравнивают с порогом, режим — с кодом, а счётчик — с пределом. Результат сравнения имеет тип bool.
| Оператор | Читается | Пример |
|---|---|---|
== | равно | mode == 2 |
!= | не равно | command != 'x' |
< | меньше | distanceCm < stopDistanceCm |
<= | меньше или равно | voltageMv <= lowVoltageMv |
> | больше | temperatureC > limitC |
>= | больше или равно | sampleCount >= requiredSamples |
Оператор == сравнивает, а = присваивает. Ошибка особенно коварна, если присваивание допустимо в условном выражении:
if (mode = 2) { // неверный замысел: mode изменяется
Serial.println("test");
}
Компилятор с предупреждениями часто обращает внимание на такую запись, но полагаться только на предупреждение нельзя. Осмысленная форма выглядит так:
if (mode == 2) {
Serial.println("test");
}
Граница принадлежит одной стороне
Условия < и <= ведут себя по-разному на пороге. Для остановки ближе 20 см нужно заранее решить, что происходит ровно при 20:
distanceCm | distanceCm < 20 | distanceCm <= 20 |
|---|---|---|
| 19 | true | true |
| 20 | false | true |
| 21 | false | false |
Проверяйте как минимум три точки: непосредственно ниже границы, на границе и выше неё. Ошибка в одном символе способна изменить поведение именно в критической точке.
Измерения датчика могут быть недостоверными. Число 0 иногда означает очень близкий объект, а иногда — отсутствие корректного результата; это зависит от устройства и библиотеки. Сначала проверяют достоверность, затем сравнивают физическую величину.
Несколько вариантов: else if
Когда режимов больше двух, создают цепочку:
const int distanceCm = 32;
void setup() {
Serial.begin(9600);
}
void loop() {
if (distanceCm < 15) {
Serial.println("stop");
} else if (distanceCm < 40) {
Serial.println("slow");
} else {
Serial.println("normal");
}
delay(500);
}
Условия проверяются сверху вниз. При distanceCm = 10 истинны оба сравнения < 15 и < 40, но выполняется только первый подходящий блок. Если поставить < 40 раньше, ветвь < 15 станет недостижимой.
| Диапазон | Первая истинная проверка | Действие |
|---|---|---|
| меньше 15 см | distanceCm < 15 | остановка |
| 15–39 см | distanceCm < 40 после ложного первого условия | медленный режим |
| 40 см и больше | ни одно условие не истинно | обычный режим |

Три одинаковых значка робота на иллюстрации — не три одновременно работающих устройства, а три возможных результата одной цепочки: остановка, прямое движение или поворот. Цветные ветви — алгоритм, а не проводка.
Логические операторы
Несколько признаков соединяют так:
&&— логическое И: истинны обе части;||— логическое ИЛИ: истинна хотя бы одна часть;!— логическое НЕ: результат меняется на противоположный.
const bool startPressed = true;
const bool coverClosed = true;
const bool emergencyStopActive = false;
const bool startAllowed =
startPressed && coverClosed && !emergencyStopActive;
void setup() {
Serial.begin(9600);
if (startAllowed) {
Serial.println("start_allowed");
} else {
Serial.println("start_blocked");
}
}
void loop() {
}
| Выражение | Когда истинно | Пример для робота |
|---|---|---|
a && b | истинны a и b | старт нажат и крышка закрыта |
| `a | b` | |
!a | a ложно | аварийный стоп не активен |
Когда в выражении смешаны && и ||, добавляйте круглые скобки, отражающие замысел. Они уменьшают зависимость чтения от знания приоритетов:
const bool mustStop =
obstacleDetected || (lowBattery && !atChargingStation);
Сокращённое вычисление
Операторы && и || вычисляют слева направо с пропуском ненужной правой части. Для a && b выражение b не вычисляется, если a уже ложно. Для a || b правая часть не вычисляется, если a уже истинно.
Это позволяет сначала проверить возможность операции:
const int sampleCount = 3;
const int selectedIndex = 2;
const int samples[] = {34, 28, 19};
void setup() {
Serial.begin(9600);
if (selectedIndex >= 0 &&
selectedIndex < sampleCount &&
samples[selectedIndex] < 20) {
Serial.println("close_obstacle");
}
}
void loop() {
}
Обращение к элементу выполняется только после обеих проверок границ. Переставлять опасный доступ в начало нельзя. Побочные действия внутри правой части тоже нежелательны: их выполнение будет зависеть от результата слева.
Блоки и вложенность
Фигурные скобки явно ограничивают ветвь:
if (sensorValid) {
Serial.println("measurement_ok");
Serial.println(distanceCm);
}
C++ разрешает один оператор без скобок, но следующая добавленная строка уже окажется вне условия. В скетчах робота используйте скобки даже для коротких ветвей.
Вложенные if допустимы, но глубокая лестница усложняет проверку. Часто легче сначала вычислить именованные логические признаки, затем построить плоскую цепочку решений:
const bool measurementValid = distanceCm > 0;
const bool obstacleClose = measurementValid && distanceCm < 20;
Приоритет безопасной реакции
В цепочке первая истинная ветвь побеждает, поэтому порядок должен отражать приоритет. Отказ датчика проверяют раньше обычной команды движения:
const bool emergencyStopActive = false;
const bool sensorValid = true;
const int distanceCm = 18;
void setup() {
Serial.begin(9600);
}
void loop() {
if (emergencyStopActive) {
Serial.println("stop_emergency");
} else if (!sensorValid) {
Serial.println("stop_invalid_sensor");
} else if (distanceCm < 20) {
Serial.println("stop_obstacle");
} else {
Serial.println("move_allowed");
}
}
Этот программный порядок сам по себе не заменяет аппаратную аварийную защиту. Он делает поведение скетча предсказуемым при известных входах.
Шум около порога и гистерезис
Если измерение колеблется около одного порога, команда может быстро переключаться. Один способ снизить дрожание — использовать разные границы остановки и возобновления:
bool movementAllowed = true;
const int stopBelowCm = 20;
const int resumeAboveCm = 25;
void updateMovementState(int distanceCm) {
if (movementAllowed && distanceCm < stopBelowCm) {
movementAllowed = false;
} else if (!movementAllowed && distanceCm > resumeAboveCm) {
movementAllowed = true;
}
}
После остановки на 19 см значение 21 см ещё не разрешит движение: нужно превысить 25 см. Выбор порогов зависит от шума, динамики устройства и требований безопасности; универсальной пары нет.
Что запомнить о ветвлении
ifвыбирает блок по логическому условию.elseотносится к ближайшему подходящемуifи задаёт альтернативу.- Цепочка
else ifвыбирает первую истинную ветвь сверху вниз. ==сравнивает,=присваивает.- Граничные значения проверяют отдельно.
&&,||и!объединяют признаки и используют сокращённое вычисление.- Приоритет ветвей должен соответствовать приоритету реакций робота.
Практика
- Напишите три режима движения по расстоянию: остановка, медленное движение и обычное. Самостоятельно задайте пороги и составьте таблицу значений ниже, на и выше каждой границы.
- Добавьте
bool sensorValid. Недостоверное измерение должно выбирать отдельную безопасную ветвь раньше проверки расстояния. - Составьте разрешение запуска из кнопки, закрытой крышки и неактивного аварийного сигнала. Проверьте все восемь сочетаний без готовой таблицы ответов.
- Реализуйте гистерезис с двумя порогами и подайте последовательность значений около границы. Запишите моменты смены состояния.
Проверьте себя
- Какой тип имеет результат сравнения?
- Чем
==отличается от=? - Когда выполняется блок
else? - Почему порядок
else ifменяет результат? - Какие значения нужно проверить около порога?
- Когда правая часть
&&не вычисляется? - Зачем нужны фигурные скобки вокруг короткой ветви?
- Как два порога уменьшают переключения около шумной границы?
Сначала ответьте без подсказки. Ответ можно считать полным, если вы:
- формулируете основную мысль своими словами;
- называете важные условия, ограничения или меры безопасности;
- для схемы, кода или расчёта показываете ход решения и ожидаемый результат.
Если один из пунктов объяснить не получается, найдите соответствующую главу статьи, перечитайте её и повторите ответ.
Словарь статьи
| Термин | Значение |
|---|---|
| условие | выражение, приводимое к логическому результату |
| ветвление | выбор пути дальнейшего выполнения |
if | конструкция выполнения блока при истинном условии |
else if | следующая проверка в упорядоченной цепочке |
else | альтернативный блок, когда предыдущие связанные условия ложны |
| сравнение | операция, возвращающая bool по отношению двух значений |
| логический оператор | &&, ` |
| сокращённое вычисление | пропуск правой части, когда результат уже известен |
| граница | значение, на котором меняется результат условия |
| гистерезис | разные пороги перехода в состояние и выхода из него |
Связанные темы
- Переменные — хранение условий и состояний.
- Монитор порта Serial — наблюдение выбранной ветви.
- Циклы — повторная проверка условий.
- Функции — выделение вычисления признаков и действий.
- digitalRead: обработка кнопки — логический вход для условия.
- analogRead: обработка датчика — пороги по аналоговым данным.
- Драйвер моторов — безопасное выполнение выбранной команды приводом.
Источники
- Arduino Language Reference:
if - Arduino Language Reference:
if...else - Arduino Language Reference: equality
== - Arduino Language Reference: logical AND
&& - Arduino Language Reference: logical OR
|| - Arduino Language Reference: logical NOT
! - C++ Working Draft: Selection statements
- C++ Working Draft: Logical AND
- C++ Working Draft: Logical OR