Понимание потока управления в C: логика и условные операторы

3

C не просто выполняет код линейно. Он принимает решения. В основе каждого решения, которое принимает программа на C, лежит булево выражение. Независимо от того, используете ли вы оператор if или цикл while, логика сводится к одному вопросу: истинно это условие или ложно?

Рассмотрим базовый пример.

Здесь программа запрашивает ввод. Она сохраняет это число в переменной b. Затем она проверяет условие. Булево выражение, о котором идет речь, — это (b < 0). C вычисляет его. Если результат истинен, программа выводит «The value is negative». Если он ложен, программа ничего не делает. Она молчит.

Правило простое. Если выражение вычисляется как True (истина), C выполняет единственную строку, непосредственно следующую за if. Или, если вы используете фигурные скобки {}, он выполняет весь блок внутри. Если выражение False (ложь), C полностью пропускает эту строку или блок.

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

Эта структура использует else if и else для охвата оставшихся случаев. Она проверяет ноль следующим. Если это не удается, она предполагает, что значение положительно.

Иногда решения усложняются. Вам может понадобиться проверить несколько условий одновременно.

Это утверждение читается как естественный язык. Если x равно y И j больше k, то установите z в 1. В противном случае установите q в 10. Вы будете использовать подобные утверждения на протяжении всей своей карьеры в C. Большинство решений будут простыми. Иногда они могут стать сложными.

Внимательно следите за синтаксисом. Распространенная ошибка для начинающих — путаница между присваиванием и сравнением.

C использует == для проверки на равенство.
C использует = для присваивания значения переменной.

Их перепутывание приводит к ошибкам, которые трудно найти. Одно устанавливает значение. Другое проверяет условие. Они не взаимозаменяемы.

C также опирается на специфические операторы для логических операций. Символ && представляет собой логическую операцию И (AND). Он гарантирует, что обе стороны условия должны быть истинными.

Вот краткая справочная информация по всем булевым операторам в C:

  • == : равенство
  • != : неравенство
  • < : меньше чем
  • > : больше чем
  • <= : меньше или равно
  • >= : больше или равно

Циклическая логика в C: while, do-while и for

Использование цикла while является простым. Он отражает простоту стандартного оператора if. Рассмотрим этот фрагмент кода:

while (a < b) { printf("%d\n", a); a = a + 1; }

Эта структура повторяет выполнение двух строк, находящихся внутри фигурных скобок. Она останавливается только тогда, когда a становится больше или равно b. Логика линейна. Проверить условие. Выполнить тело цикла. Повторить.

C также предлагает конструкцию do-while. В отличие от стандартного цикла while, она проверяет условие после первого выполнения. Это гарантирует, что блок кода выполнится как минимум один раз.

Примечание: Приведенный выше пример использует оператор if внутри функции. Настоящий цикл do-while оборачивал бы тело цикла и проверял условие в конце.

Цикл for как сокращенная запись

Цикл for по сути является сжатой записью оператора while. Он объединяет инициализацию, проверку и увеличение значения в одну строку.

Посмотрите на этот стандартный цикл while:

x=1;
while (x<10) { blah blah blah x++; // x++ идентично x=x+1 }

Вы можете переписать это как цикл for:

for(x=1; x<10; x++) { blah blah blah }

Компоненты очевидны. x=1 выполняет инициализацию. x<10 выполняет проверку. x++ увеличивает значение. Цикл for просто сжимает их. Вы не ограничены простыми переменными. Вы можете поместить сложную логику в эти секции.

Рассмотрим этот пример:

a=1;
b=6;
while (a < b) { a++; printf("%d\n",a); }

Он превращается в:

for (a=1,b=6; a < b; a++,printf("%d\n",a));

Это работает. Это также запутанно. Оператор запятая позволяет использовать несколько операторов в секциях инициализации и увеличения. Он не работает в секции проверки. Многие разработчики C любят эту компактность. Другие считают ее нечитаемой. Они разбивают код на части. Оба подхода допустимы. Выбирайте в зависимости от того, кто будет поддерживать код в будущем.

Опасность использования = вместо == в C

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

В C логические выражения оцениваются как целые числа. Ноль означает False (Ложь). Любое ненулевое целое число означает True (Истина). Это означает, что любое целое число может существовать в логическом контексте.

Рассмотрим этот корректный код на C:

if (a) { printf("Non-zero"); }

Если a равно чему-либо, кроме 0, блок выполняется.

Теперь посмотрите на if (a=b). Это не сравнивает значения. Оно присваивает b переменной a, а затем проверяет новое значение a. Если b равно 0, условие ложно. Если b равно чему-либо еще, условие истинно. Переменная a изменяется. Скорее всего, это не то, что вы планировали. Вероятно, вы имели в виду == для сравнения.

Эта особенность не бесполезна. У нее есть обоснованные случаи использования. Но это ловушка. Будьте осторожны с использованием = и ==. Один символ меняет логику с сравнения на присваивание.