В Python-курсе ты уже учился находить и исправлять чужие ошибки — это отдельный навык, не завязанный на конкретный язык. Сегодня применим его к C++: соберём каталог типичных ошибок этого курса и потренируемся их находить.

После урока сможешь: различать ошибку компиляции и ошибку логики, узнавать частые ошибки этого курса, использовать Serial.print как инструмент отладки. В конце — найдёшь и исправишь несколько багов в готовой программе.
Вспомни: в Python-курсе отладка была сквозной линией (Р8, с занятия 3) — искать причину и чинить, не переписывая всё заново. Здесь тот же навык, просто на новом языке: причины ошибок другие, а сам подход «прочитать сообщение → сузить место → проверить гипотезу» — тот же.
Два вида ошибок: компиляция и логика
В C++ программа сначала ПОЛНОСТЬЮ проверяется компилятором — и только если проверка прошла, начинает работать. Ошибка компиляции — программа не соберётся вовсе, симулятор покажет текст ошибки и номер строки ДО запуска. Ошибка логики — программа успешно соберётся и запустится, но поведёт себя не так, как задумано, — тут никакого сообщения не будет, придётся разбираться самому.
Путь программы Arduino:
код -> [ КОМПИЛЯЦИЯ ] -> прошивка на плату -> выполнение (setup/loop)
|
ошибка здесь = ошибка КОМПИЛЯЦИИ
(программа вообще не соберётся, покажет текст ошибки)
Если компиляция прошла, но поведение неверное -
это ошибка ЛОГИКИ (программа работает, но не так, как задумано)
Частые ошибки компиляции
Пропущенная точка с запятой ;, незакрытая фигурная скобка {, неверный регистр в имени команды (Pinmode вместо pinMode — C++ различает большие и маленькие буквы). Сообщение компилятора обычно указывает номер строки — но настоящая причина иногда стоит СТРОКОЙ ВЫШЕ (например, не закрытая скобка ломает всё, что идёт дальше).
void setup() {
pinMode(13, OUTPUT);
Serial.begin(9600)
}
Частые ошибки логики — уже встречались на этом курсе
Собери в голове каталог: = вместо == в условии (занятие про кнопку) — присваивание вместо сравнения; неверный порядок условий в if/else if/else (занятие про пороговую логику) — от мягкого к строгому вместо строгого к мягкому; забытое обновление previousMillis внутри if (занятие про millis) — условие остаётся истинным всегда; забытый dht.begin() в setup() (занятие про DHT22) — датчик не запущен, всегда NaN; ошибка на границе цикла — i <= razmer вместо i < razmer (занятие про массивы) — обращение к несуществующему индексу.
Скрытая ловушка: & и && — это РАЗНЫЕ операции
В C++ есть логическое И && (сравнивает истинность условий) и побитовое И & (сравнивает числа побитово, на уровне отдельных битов). Они выглядят похоже, но результат может отличаться даже для положительных чисел.
int temperatura = 4;
int vlazhnost = 8;
Serial.println(temperatura && vlazhnost);
Serial.println(temperatura & vlazhnost);
1
0
temperatura && vlazhnostистинно — оба числа не равны нулю. Аtemperatura & vlazhnost— это побитовое И самих чисел 4 (0100 в двоичном виде) и 8 (1000): общих единичных битов нет, результат 0. Для условий в if/else всегда используй && и || — одиночные & и | почти всегда не то, что нужно.
Serial.print как инструмент отладки
Когда непонятно, что реально происходит внутри программы, — временно добавь Serial.print в подозрительное место и посмотри РЕАЛЬНОЕ значение переменной, а не то, что кажется по коду. Это универсальный приём, который работает в любом языке — ты уже пользовался им (неявно) в Python-курсе, разбирая вывод программ.
Миссия: найди и почини баги
В программе ниже — три ошибки (одна компиляции, две логики). Вставь код в Wokwi, прочитай сообщение об ошибке, исправь по одной и проверь работу после каждого исправления.
// БАГИ (для проверки себя, не показывай ученику решение раньше времени):
// 1) пропущена ; после pinMode
// 2) previousMillis не обновляется внутри if
// 3) i <= 5 вместо i < 5 в переборе массива размером 5
int pin_led = 13;
void setup() {
pinMode(pin_led, OUTPUT)
Serial.begin(9600);
}
unsigned long previousMillis = 0;
const long interval = 500;
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
digitalWrite(pin_led, !digitalRead(pin_led));
}
float pokazaniya[5] = {22.0, 23.0, 21.0, 24.0, 22.0};
float summa = 0;
for (int i = 0; i <= 5; i = i + 1) {
summa = summa + pokazaniya[i];
}
}
Проверь себя
Контрольный вопрос. Чем ошибка компиляции отличается от ошибки логики?
Подсказка: Обратись к блоку «Два вида ошибок: компиляция и логика».
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Какая из этих проблем — ошибка КОМПИЛЯЦИИ?
Подсказка: Ошибка компиляции — та, из-за которой программа вообще не соберётся.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Программа собирается и запускается, но кнопка почему-то всегда «считается нажатой», хотя её не трогали. В условии стоит if (knopka = LOW). Это ошибка компиляции или логики?
Подсказка: Вспомни занятие про кнопку: = вместо == компилируется без проблем, ломается только поведение.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Что выведет программа?
Исходный код для этого задания:
int a = 10; int b = a; // должно было быть b = a * 2, но программист ошибся при копировании Serial.println(b);Подсказка: Программа делает ровно то, что написано, а не то, что задумал автор — это и есть логическая ошибка.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. Массив pokazaniya объявлен размером 5. Цикл написан как for (int i = 0; i <= 5; i = i + 1). К какому классу ошибок это относится и что произойдёт?
Подсказка: Вспомни занятие про массивы: индексы массива размером 5 — это 0..4, не 0..5.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. dht.readTemperature() всё время возвращает NaN, хотя в схеме датчик подключён верно. Какую строку скорее всего забыли в setup()?
Подсказка: Вспомни занятие про DHT22 — там разбирался именно этот симптом.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Задание. Напиши код сам. Ниже — строка с ошибкой компиляции. Перепиши её исправленно (сама ошибка — в блоке «Частые ошибки компиляции» этого занятия).
Исходный код для этого задания:
Serial.begin(9600)Подсказка: Каждая отдельная команда в C++ обязана заканчиваться символом ;
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. В этом коде переключение светодиода должно происходить раз в interval миллисекунд, но происходит на КАЖДОМ проходе loop() без пауз, как только порог пройден один раз. Какую переменную забыли обновить внутри if?
Исходный код для этого задания:
unsigned long previousMillis = 0; const long interval = 500; void loop() { unsigned long currentMillis = millis(); if (currentMillis - previousMillis >= interval) { digitalWrite(13, !digitalRead(13)); } }Подсказка: Вспомни занятие про millis(): без обновления этой переменной разность будет расти и всегда останется больше interval.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Задание. Напиши код сам. Перепиши строку с if так, чтобы previousMillis обновлялась внутри if — исправь логическую ошибку из предыдущего задания.
Исходный код для этого задания:
if (currentMillis - previousMillis >= interval) { digitalWrite(13, !digitalRead(13)); }Подсказка: Добавь строку previousMillis = currentMillis; внутрь тела if, до или после переключения светодиода.
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
Проверить ответ →
Реальная проверка — на нашей платформе, бесплатно и без регистрации. Открыть задачу и ввести ответ →
Контрольный вопрос. temperatura равна 4, vlazhnost равна 8 (типы int). Что выведет Serial.println(temperatura & vlazhnost)? Впиши число.
Исходный код для этого задания:
int temperatura = 4; int vlazhnost = 8; Serial.println(temperatura & vlazhnost);Подсказка: & — это побитовое И самих чисел, а не логическое сравнение истинности. Переведи оба числа в двоичный вид и сравни биты.
Онлайн-проверка ответа появится позже
Контрольный вопрос. Скользящее окно объявлено как float okno[5], а RAZMER_OKNA по ошибке отдельно задан как 6. Индекс двигают через indeks = (indeks + 1) % RAZMER_OKNA. К чему это приведёт?
Исходный код для этого задания:
const int RAZMER_OKNA = 6; // ошибка: массив объявлен на 5 float okno[5]; int indeks = 0; void zapisatPokazanie(float novoe) { okno[indeks] = novoe; indeks = (indeks + 1) % RAZMER_OKNA; }Подсказка: % RAZMER_OKNA ограничивает индекс диапазоном 0..RAZMER_OKNA-1 — то есть 0..5, а не 0..4, если константы разошлись.
Онлайн-проверка ответа появится позже
Задание. Напиши код сам. Перепиши программу целиком (около 8 строк), исправив ДВЕ ошибки сразу: (1) в условии сравнение написано через = вместо ==, (2) цикл переберает массив размером 4 с условием i <= 4 вместо i < 4.
Исходный код для этого задания:
int knopka = digitalRead(2); if (knopka = LOW) { Serial.println("Нажата"); } float arr[4] = {1.0, 2.0, 3.0, 4.0}; float summa = 0; for (int i = 0; i <= 4; i = i + 1) { summa = summa + arr[i]; }Подсказка: Первая ошибка — замени = на == в сравнении. Вторая — замени <= на < в границе цикла.
✅ Готово, если: программа запускается без ошибок и выводит то, что просят в задании.
Онлайн-проверка ответа появится позже
Что дальше
Теперь ты умеешь находить и различать ошибки компиляции и логики на C++, и у тебя есть каталог типичных багов этого курса. Дальше — итоговый проект: соберём станцию мониторинга целиком, по шагам, за два занятия.
Итог: ты различаешь ошибки компиляции и логики, знаешь частые баги этого курса и умеешь пользоваться Serial.print для отладки. Дальше — итоговый проект: станция мониторинга.
