Архив за месяц: Октябрь 2011

Занятие 5.Управляющая конструкция if-else. Логические операторы и выражения.Уроки программирования для чайников.Язык Си.

Для этого урока готова новая версия: "Операции отношения и логические операции" и "Условный оператор if-else".

В новой версии:

  • Ещё более доступные объяснения и больше примеров
  • Задачи с автоматической проверкой решений

Добрый день уважаемые читатели.
С сегодняшнего урока мы начинаем рассмотрение группы управляющих конструкций. Из названия понятно, что это конструкции, предназначены для управления программой.  До этого мы разбирали простейшие программки, в которых все записанные операторы выполняются последовательно друг за другом.  Такие программы называются линейными.  Но часто, то, как программа должна работать зависит от каких-либо условий.  Если условие выполняется, то надо действовать так, если не выполняется –  иначе. Вспомните любую игру с ветвящимся сюжетом, когда если вы беретесь за выполнение задания, то вы обязательно наткнетесь на что-то, а если нет, то ничего не будет.  Именно для этого используется управляющие конструкции, об одной из которых  и будет вестись сегодня речь.
Приступим.

Операторы соотношений и логические выражения.
Помимо арифметических операторов, рассматриваемых в прошлом уроке, в Си есть и операторы соотношений. К ним относятся следующие операторы:
>  - больше
>= - больше либо равно
<  - меньше
<= - меньше либо равно
== - равно
!= - не равно
Они используются в логических выражениях. Например:

Листинг 5.1
int a=4, b=10;
a>10;
b!=0;

Любое выражение либо истинно, либо ложно.  В нашем примере, первое выражение ложь (false) второе истина (true). Еще часто, когда условие ложно подразумевают 0, когда истинно подразумевают 1. Это очень удобно,  для компьютера  ведь для него двоичная система счисления является основной.  В электронике, например, под истиной подразумевается  «есть ток», под ложью - «нет тока» .  Рассмотрим пример:

Листинг 5.2
#include <stdio.h>
int main(void)
{
   int a=4, b=10, c, d;
   c = а>10;
   d = b != 0;
   printf("pervoe virazenie %d \nvtoroe virazenie %d \n",c,d);
   return (0);
}  

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

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

Листинг 5.3
#include <stdio.h>
int main(void)
{
      int a, b;
      printf("Vvedite dva celih chisla:");
      scаnf("%d %d", &a, &b);
      if (a > b)
         printf("%d naibolshee chislo\n", a);
      else
         printf("%d naibolshee chislo\n", b);
      return (0);
}

Теперь разберемся с синтаксисом конструкции if-else.
Сначала идет ключевое слово if(с английского «если»)  далее в скобочках записано условие, которое проверяется (в нашем случае а больше b). Следом записан ОДИН оператор, который должен выполняться, если условие истинно (в нашем случае printf("%d naibolshee chislo\n", a);) , потом ключевое слово else и следом за ним, ОДИН оператор, который должен выполняться, если условие ложно (в нашем случае printf("%d naibolshee chislo\n", b);).
Формально синтаксис конструкции if-else выглядит так:

Листинг 5.4
if (логическое выражение) оператор1; elseоператор 2;

Он работает следующим образом. Сначала вычисляется логическое выражение. Если оно истинно (т. е. отлично от нуля), выполняется оператор1. Если выражение ложно (т. е. его значение равно нулю), то выполняется оператор2.
Кстати, блок else может и отсутствовать. Такая запись наывается сокращенной записью, или неполной конструкцией ветвления.

Листинг 5.5
if (логическое выражение) оператор1;

В данном случае, если условие будет ложным программа ничего делать не будет.  А просто продолжит своё выполнение.

Теперь остановимся на на оговорке об одном операторе. Это оговорка очень существенна. Иначе конструкция if будет работать неправильно. Для того, чтобы выполнить несколько операторов, используется составной оператор. Это обычные фигурные скобки {} записанная между ними группа операторов, воспринимается компилятором как один.
Формально:

Листинг 5.6
if (логическое выражение)
{
            оператор;
            оператор;
            оператор;
}
else
{
            оператор;
            оператор;
            оператор;
}

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

По своей сути, оператор if проверяет в условии числовое выражение. Т.е. либо ноль ( т.е. ложь), либо не ноль (т.е. истинна). Поэтому вместо условия (a != 0), можно просто писать (a). Но пользоваться такой записью надо осторожно, часто бывает она затрудняет понимание программы.

Внутри управляющей конструкций if-else можно использовать любые конструкции языка, в том числе и еще  саму конструкцию if-else. Если опять вспомнить пример с развилкой дорог,  получается, что после одной развилки  появляется другая развилка.
Отсутствие else-части в одной из вложенных друг в друга if-конструкций может привести к неправильному понимаю записи. Для разрешения этой проблемы, используется простое правило:  
«else относится к ближайшему if, у которого нет своего else.»
Для примера:

Листинг5.7
if (n > 0)
    if (а > b)
        z = a;
    else
        z = b;

В данном случае else относится к внутреннему (второму)  if, а если нам надо чтобы else относился к внешнему (первому) if, то необходимо расставить  соответствующим образом фигурные скобки.

Листинг 5.8
f ( > 0)
{
    if (а > b)
        z = a;
}
else
    z = b;

Кстати, конструкция if является одним оператором, и для неё одной в принципе скобки не нужны, но как я уже упоминал, лучше всегда использовать фигурные скобки, дабы избежать случаев  неправильного толкования записи. Потому что искать такие ошибки в программах очень тяжело. Еще, советую использовать отступы, для показания того, что и к чему относится. Это относится к стилю оформления кода. Как я уже обещал в комментариях к одному из уроков,  я посвящу в будущем этой теме отдельный пост.

Теперь немного о типичных ошибках. Для проверки равенства двух чисел используется оператор «==» два знака равно. Очень часто из-за невнимательности, в условиях вместо (a==b) пишут (a=b).  И программа работает не так как нужно. С точки зрения компилятора, когда написано выражение a=b истинно всегда, кроме случаев, когда b равно нулю. Мы, фактически, присваиваем переменной а значение b. Если оно не ноль, то выражение истинно, если 0 ложно. А нам-то нужно сравнить их значения. Поэтому будьте внимательны. Вот пример, с ошибкой:

Листинг 5.9
#include <stdio.h>
int main(void)
{
      int a, b;
      printf("Vvedite dva celih chisla:");
      scаnf("%d %d", &a, &b);
      if (a = b)
            printf("a i b ravni\n");
      else
            printf("a i b ne ravni\n");
      return (0);
}

Логические операторы. Сложные условия.
В предыдущих программах, мы рассматривали простейшие условия, состоящие из одного оператора отношения.  Теперь, давайте рассмотрим программу, которая проверяет, принадлежит ли точка с координатой х, заданному промежутку оси х  (-10; 10].

Листинг 5.10
#include <stdio.h>
int main(void)
{
      float x;
      printf("Vvedite x");
      scаnf("%f", &x);
      if (x>-10)
      {
            if (x<=10)
            {
                  printf("x prinadlegit promegytku\n");
            }
            else
            {
                  printf("x ne prinadlegit promegytku\n");
            }
      }
      else
      {
            printf("x ne prinadlegit promegytku\n");
      }

      return (0);
}

Эта программа состоит из двух вложенных условий. Для того, чтобы точка находилась в промежутке (-10;10] она должна быть больше -10, и меньше или равна 10. В нашей программе мы использовали два вложенных условия. Но ту же задачу можно решить и с помощью одной конструкции if. Для этого, для записи сложного условия, нужно применить логические операторы. Их всего несколько:
!(условие) – оператор логическое НЕ. Отрицает условие. Если условие было истина, оно становится ложным, если было ложным становится истинным.
(условие1) && (условие2) - оператор логическое И. Возвращает истину если  оба условия истинны. Иначе возвращает ложь.
(условие1) || (условие2) - оператор логическое ИЛИ. Возвращает истину, если хотя бы одно из условий истинно или оба сразу  истинны. Иначе ложь.

А нашем случае есть два условия (x>-10) (x<=10) если выполняется и первое И второе, то точка попадает в промежуток, иначе нет.
Если использовать логический оператор, то  программу можно переписать следующим образом:

Листинг 5.11
#include <stdio.h>
int main(void)
{
      float x;
      printf("Vvedite x");
      scаnf("%f", &x);
      if ((x>-10) && (x<=10))
      {
            printf("x prinadlegit promegytku\n");
      }
      else
      {
            printf("x ne prinadlegit promegytku\n");
      }
      return (0);
}

Как видите, запись программы стала более компактна и легче для понимания.
Приоритет логических операций.
Как и арифметические операции логические операции имеют тоже различный приоритет.
  1. Операции в скобках
  2. Логическая операция НЕ
  3. Логические отношения
  4. Логическая операция И
  5. Логическая операция ИЛИ

Так же как и для арифметических операций, скобками можно изменить порядок выполненияю
Как видите, приоритет операций логических соотношений выше, чем приоритет логических операций И и ИЛИ. Поэтому, в принципе, в программе Листинг 5.11 можно было бы условие записать (x>-10 && x<=10). Но опять же, чтобы не запутаться в более сложных условиях, я советую вам всегда явно указывать приоритет с помощью скобок, дабы избежать досадных ошибок.
Ну вот на этом и закончим сегодняшнее занятие.

Резюме урока:
  • Узнали и научились использовать составной оператор
  • Разобрались с логическими операциями соотношений и логическими выражениями
  • Ознакомились с управляющей конструкцией if-else и научились её пользоваться
  • Узнали про логические операторы НЕ, И, ИЛИ
  • Выяснили приоритет логических операторов
Задание для практической работы:


  1. Напишите программу которая по вводимому числу выводит его модуль, не используя функцию fabs(). Программа должна считать вещественное число с клавиатуры, и вывести на экран модуль этого числа.
  2. Напишите программу для решения уравнения ax = b относительно х в целых числах. Учтите, что a может принимать любые значения, в том числе и 0. 
  3. На вход программе подаются целые числа a, b, по модулю не превосходящие 30000. Требуется вывести целый корень уравнения, если он существует и единственный. Если уравнение не имеет корней, то вывести no solution. Если уравнение имеет больше одного целого корня, то вывести many solutions.
  4. Поле шахматной доски определяется парой чисел (a, b), каждое от 1 до 8, первое число задает номер столбца, второе – номер строки. Заданы две клетки. Определите, может ли шахматная ладья попасть с первой клетки на вторую за один ход. Входные данные: 4 целых числа от 1 до 8 каждое, первые два задают начальную клетку, вторые два задают конечную клетку. Начальные и конечные клетки не совпадают. Программа должна вывести YES, если из первой клетки ходом ладьи можно попасть во вторую или NO в противном случае.
  5. Даны вещественные числа a, b, c. Найдите все решения квадратного уравнения ax2+bx+c=0. Формат входных данных: три вещественных числа. Формат выходных данных: два вещественных числа, если уравнение имеет два корня, одно действительное число – при наличии одного корня. При отсутствии действительных корней программа выводит no solution.
  6. По данному числу n<100 закончите фразу "На лугу пасется..." одним из возможных продолжений: "n коров", "n корова", "n коровы", правильно склоняя слово "корова". Программа должна вывести введенное число n и одно из слов (на латинице): korov, korova или korovy, например, 1 korova, 2 korovy, 5 korov. Между числом и пробелом должен стоять ровно один пробел.
Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом  Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них.