Все записи автора KaDeaT

Занятие 9.Циклические конструкции.Циклы WHILE и DO-WHILE. Уроки программирования для чайников.Язык Си.

Прочитайте улучшенную версию этого урока "Циклы с условием while и do-while".

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

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

Добрый день дорогие друзья.
После долгого перерыва,я снова с вами.
Сегодняшнее занятие будет продолжением занятия номер 7.Циклические конструкции 
Сегодня поговорим о еще двух циклических конструкциях. 
Как уже говорилось ранее,цикл for используется,когда известно сколько раз надо выполнить тело цикла. А что же делать если количество повторений заранее не известно, а есть только условие которое после которого нужно прекратить выполнять цикл. Для этих целей используют циклические конструкции while и do-while. Остановимся на каждом из них поподробнее. 

Цикл while.
Цикл  while называют еще циклом с предусловием. Чаще всего он используется когда неизвестно конкретно сколько раз нужно выполнить тело цикла.
Вот его синтаксис:

Листинг 9.1
while (условие)
    оператор;

Работает эта конструкция следующим образом.

1.Сначала проверяется условие в скобках.
1.1 Если оно истинно, то выполняется тело цикла. (Оператор). И программа снова переходит к проверке условия.  
Напомню,что тело цикла всегда состоит из одного оператора. И если нам нужно использовать несколько операторов, то как и в случае с конструкцией if-else или циклом for, применяется составной оператор {...}.
1.2 Если условие ложно, то выполнение циклической конструкции заканчивается  и программа выполняется дальше.

Заметим, что цикл может не выполниться ни одного раза,если изначально условие будет ложным.
Например:
Листинг 9.2
while (0)
{   ...   }


Цикл do-while.
Цикл do-while называют еще циклом с постусловием. И в этом состоит его основное отличие от цикла while. Сейчас мы разберем его синтаксис, поймем как он работает и увидим как раз в чем разница.

Синтаксис:


Листинг 9.3
do //заголовок цикла
оператор;} // тело цикла 
while (условие); //условие


как видите цикл do-while состоит из 3 частей. Заголовка цикла, тела цикла и условия. 
Работает эта конструкция следующим образом.
1)После того как программа встречает ключевое слово do,она понимает, что имеет дело с циклом do-while. 
2)выполняется тело цикла.
3) Проверяется условие.
3.1) Если условие истинно,то снова выполняется тело цикла.
3.2) Если условие ложно, то работа циклической конструкции заканчивается и программа выполняется дальше.

Обратите внимание, что при использовании цикла do-while, тело цикла выполнится всегда хотя бы один раз! Это очень важная особенность и иногда её очень удобно использовать.


Прочитайте улучшенную версию этого урока "Операторы управления циклом. Зацикливание.".

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

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

Зацикливание.
Теперь поговорим немного о такой пренеприятнейшей вещи как зацикливание. Зацикливание - это когда программа постоянно выполняет тело цикла и не может из него выйти. Причиной зацикливания всегда является программист. Надо всегда внимательно следить за тем, чтобы работа операторов как-то влияла на условие. 

Напоследок напишем одну маленькую программку.С использованием циклов do-while и while.
Пусть требуется написать программу которая принимает на входе положительное натуральное число, а на выходе выдает сумму цифр этого числа. При этом, надо запретить пользователю вводить отрицательные числа. (защита от дурака). 
Сначала напишем основную часть программы.
Считаем число и  посчитаем сумму его цифр.
Листинг 9.4

#include <stdio.h>

int main()
{
      int A, sum=0;
      printf("Vvedite chislo:");
      scanf("%d",&A); //считываем число

//начинаем последовательно получать каждую последнюю цифру числа. 
      while (A>0)
      {
            sum=sum+A%10;
            A= A/10;
      }
      printf("summa chifr etogo chisla: %d\n", sum);

return(0);
}


Эта программа работает. Теперь добавим в неё так называемую "защиту от дурка". Чтобы пока не введешь правильные данные,программа не будет работать. Для этого используем цикл do-while.И будем повторить ввести ввод до тех пор, пока не будет введено положительное число.
Получим следующий код.
Листинг9.5

#include <stdio.h>

int main()
{
int A, sum=0;
do {
    printf("Vvedite chislo:");
    scanf("%d",&A); //считываем число
} while(A<=0);

while (A>0){
    sum=sum+A%10;
    A= A/10;
}    

printf("summa chifr etogo chisla: %d\n", sum);
return(0);
}


На этом сегодня всё. Домашнего задания к этому уроку не будет. Так как мне надо разобраться с той кучей вопросов, которые накопились за это время в комментариях. 


Задание для практической работы.




  1. Дано целое число N (вводится с клавиатуры), причем N<30000. По заданному N вывести через пробел все (натуральные, т.е. 0, 1, 2, 3, ... ) степени числа 2, которые меньше N.
  2. Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон.с шагом dх.  Функция F должна принимать действительное значение, если выражение (Ац^Вц)|(Ац^Сц) не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a,b,c. Значения a,b,c, Хнач., Хкон., dx ввести с клавиатуры. Пока что не обязательно к выполнению.!
  3. Дано натуральное число N. Напишите программу которая считает сумму цифр этого числа.
  4. Дано натуральное число N. Выведите его представление в двоичном виде в обратном порядке.

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

Занятие 9.Циклические конструкции.Циклы WHILE и DO-WHILE. Уроки программирования для чайников.Язык Си.

Прочитайте улучшенную версию этого урока "Циклы с условием while и do-while".

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

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

Добрый день дорогие друзья.
После долгого перерыва,я снова с вами.
Сегодняшнее занятие будет продолжением занятия номер 7.Циклические конструкции 
Сегодня поговорим о еще двух циклических конструкциях. 
Как уже говорилось ранее,цикл for используется,когда известно сколько раз надо выполнить тело цикла. А что же делать если количество повторений заранее не известно, а есть только условие которое после которого нужно прекратить выполнять цикл. Для этих целей используют циклические конструкции while и do-while. Остановимся на каждом из них поподробнее. 

Цикл while.
Цикл  while называют еще циклом с предусловием. Чаще всего он используется когда неизвестно конкретно сколько раз нужно выполнить тело цикла.
Вот его синтаксис:

Листинг 9.1
while (условие)
    оператор;

Работает эта конструкция следующим образом.

1.Сначала проверяется условие в скобках.
1.1 Если оно истинно, то выполняется тело цикла. (Оператор). И программа снова переходит к проверке условия.  
Напомню,что тело цикла всегда состоит из одного оператора. И если нам нужно использовать несколько операторов, то как и в случае с конструкцией if-else или циклом for, применяется составной оператор {...}.
1.2 Если условие ложно, то выполнение циклической конструкции заканчивается  и программа выполняется дальше.

Заметим, что цикл может не выполниться ни одного раза,если изначально условие будет ложным.
Например:
Листинг 9.2
while (0)
{   ...   }


Цикл do-while.
Цикл do-while называют еще циклом с постусловием. И в этом состоит его основное отличие от цикла while. Сейчас мы разберем его синтаксис, поймем как он работает и увидим как раз в чем разница.

Синтаксис:


Листинг 9.3
do //заголовок цикла
оператор;} // тело цикла 
while (условие); //условие


как видите цикл do-while состоит из 3 частей. Заголовка цикла, тела цикла и условия. 
Работает эта конструкция следующим образом.
1)После того как программа встречает ключевое слово do,она понимает, что имеет дело с циклом do-while. 
2)выполняется тело цикла.
3) Проверяется условие.
3.1) Если условие истинно,то снова выполняется тело цикла.
3.2) Если условие ложно, то работа циклической конструкции заканчивается и программа выполняется дальше.

Обратите внимание, что при использовании цикла do-while, тело цикла выполнится всегда хотя бы один раз! Это очень важная особенность и иногда её очень удобно использовать.


Прочитайте улучшенную версию этого урока "Операторы управления циклом. Зацикливание.".

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

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

Зацикливание.
Теперь поговорим немного о такой пренеприятнейшей вещи как зацикливание. Зацикливание - это когда программа постоянно выполняет тело цикла и не может из него выйти. Причиной зацикливания всегда является программист. Надо всегда внимательно следить за тем, чтобы работа операторов как-то влияла на условие. 

Напоследок напишем одну маленькую программку.С использованием циклов do-while и while.
Пусть требуется написать программу которая принимает на входе положительное натуральное число, а на выходе выдает сумму цифр этого числа. При этом, надо запретить пользователю вводить отрицательные числа. (защита от дурака). 
Сначала напишем основную часть программы.
Считаем число и  посчитаем сумму его цифр.
Листинг 9.4

#include <stdio.h>

int main()
{
      int A, sum=0;
      printf("Vvedite chislo:");
      scanf("%d",&A); //считываем число

//начинаем последовательно получать каждую последнюю цифру числа. 
      while (A>0)
      {
            sum=sum+A%10;
            A= A/10;
      }
      printf("summa chifr etogo chisla: %d\n", sum);

return(0);
}


Эта программа работает. Теперь добавим в неё так называемую "защиту от дурка". Чтобы пока не введешь правильные данные,программа не будет работать. Для этого используем цикл do-while.И будем повторить ввести ввод до тех пор, пока не будет введено положительное число.
Получим следующий код.
Листинг9.5

#include <stdio.h>

int main()
{
int A, sum=0;
do {
    printf("Vvedite chislo:");
    scanf("%d",&A); //считываем число
} while(A<=0);

while (A>0){
    sum=sum+A%10;
    A= A/10;
}    

printf("summa chifr etogo chisla: %d\n", sum);
return(0);
}


На этом сегодня всё. Домашнего задания к этому уроку не будет. Так как мне надо разобраться с той кучей вопросов, которые накопились за это время в комментариях. 


Задание для практической работы.




  1. Дано целое число N (вводится с клавиатуры), причем N<30000. По заданному N вывести через пробел все (натуральные, т.е. 0, 1, 2, 3, ... ) степени числа 2, которые меньше N.
  2. Вычислить и вывести на экран в виде таблицы значения функции F на интервале от Хнач. до Хкон.с шагом dх.  Функция F должна принимать действительное значение, если выражение (Ац^Вц)|(Ац^Сц) не равно нулю, и целое значение в противном случае. Через Ац, Вц и Сц обозначены целые части значений a,b,c. Значения a,b,c, Хнач., Хкон., dx ввести с клавиатуры. Пока что не обязательно к выполнению.!
  3. Дано натуральное число N. Напишите программу которая считает сумму цифр этого числа.
  4. Дано натуральное число N. Выведите его представление в двоичном виде в обратном порядке.

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

Занятие 8.Оформление кода программы на Си.Уроки программирования для чайников.Язык Си.

Добрый день уважаемые читатели.
Сегодняшний пост начну не так как обычно. Сегодня 27 ноября, воскресенье, последнее воскресенье в этом месяце. А значит что? Значит, что сегодня отмечается международный День матери. От всей души хочу поздравить матерей, бабушек, у кого живы прабабушек, всех моих читателей, да и вообще всех матерей. Частенько мы бываем нетерпимы к родителям, особенно когда они читают нам мораль и учат жить. Вот сегодня замечательный повод извиниться перед своими мамами, за свою нетерпимость.Поздравить их, при наличии возможности подарить им цветы, им будет очень приятно.
Теперь же перейдем к самому занятию.Сегодня мы не будем разбирать какие-то новые конструкции языка, а поговорим об оформлении кода наших программ. Тема это очень важная. Дабы самому не путаться в своем коде написанном несколько месяцев назад. У каждого программиста есть свой стиль, свои привычки при написании программ. Они появляются с течением времени и закрепляются у каждого. В компаниях и командах где несколько разработчиков, обычно разработчики договариваются об каком-то одном стиле написания исходного кода. Оформляя определенным образом код программы, человек приучается к дисциплине. Вот об основных таких советах оформления кода мы сегодня и поговорим.

Имена и способы описания переменных.
Основной совет таков, давайте переменным осмысленные имена.
Это очень важный совет на самом деле. В маленьких программках которые мы пишем в практических занятиях это не столь серьезно, но в большой программе это вам очень поможет. Даже в небольших программах это иногда очень помогает. У меня есть небольшой опыт олимпиадного программирования, так вот когда переменным даешь короткие имена, ничего не обозначающие, можно очень легко запутаться. Когда имя переменной несет в себе информацию которая хранится в переменной, это позволяет легче искать ошибки в ходе отладки программы. А в условиях нехватки времени, отлаживать и оптимизировать программу  постоянно вспоминая что именно хранится в переменной q, что в get, очень непросто. Так что давайте своим переменным осмысленные имена. 
Немного о разделении слов в именах переменных. Пусть есть переменная целого типа в который содержится номер ящика. Её логично назвать number_box. Так вот, разделение слов с помощью нижнего подчеркивания, можно считать традицией программистов на Си. В паскалеподобных языках обычно подчеркивания для это цели не используют программисты. Для этого используется заглавные буквы. Возвращаясь к нашему примеру: NumberBox. Но так как Си регистрозависимый, а паскаль нет, то при если случайно ошибиться и написать потом numberBox, то в паскале программа будет работать, а в Си нет, ибо NumberBox и numberBox являются по правилам языка Си разными переменными. Отсюда, есть еще традиция в языке Си, имена переменных всегда пишутся маленьким буквами, а имена констант  только заглавными.И всегда понятно, где используется константа, а где переменная.  
Еще одна из условностей, это указание типа переменной в её имени. Опять же обратимся к нашему примеру, количество ящиков величина целая, поэтому достаточно удобно в имени это указать каким-то образом. Например так. n_number_box. Т.е. в начале имени переменной писать  определенный префикс для каждого типа свой (int - n, char - ch, double,float - d, file - f, и другие). Я лично таким способом не пользуюсь постоянно, хотя это иногда очень удобно.

Оформление логических блоков и запись лесенкой.
Запись лесенкой очень-очень полезная и практичная вещь. Оформлять код лесенкой это первое, что каждый может сделать на пути избежания ошибок в коде своих программ и повышения удобчитаемости.
Смысл в том, чтобы каждый вложенный блок сдвигать несколько в сторону. Вот пример такого оформления.
Листинг 8.1
#include <stdio.h>

int main(void)
{
      int n,b;
      printf("Vvedite chislo ot 1 do 100: ");
      scanf("%d", &n);
            if(n>=11&&n<=14){
                  printf("Na lugu pasetsya %d korov n", n);
            }
            else{
                  b=n%10;
                  if(b==1)          printf("Na lugu pasetsya %d korova n", n);
                  if(b>=2&&b<=4)    printf("Na lugu pasetsya %d korovy n", n);
                  if(b>=5&&b<=9)    printf("Na lugu pasetsya %d korov n", n);
                  if(b==0)          printf("Na lugu pasetsya %d korov n", n);
            }
return(0); 
}

Оформляя таким образом свой код, его очень удобно читать другим, да и самому спустя какое-то время, да и непосредственно во время написания. Отступы можно делать как пробелами, так и табуляциями, я предпочитаю табуляции, и вам советую тоже пользоваться ими. Это удобно.Касательно табуляций и пробелов есть хороший пост на ресурсе Хабрахабр. Рекомендую ознакомится.

Теперь оформление логических блоков, а точнее разберемся с написание составного оператора. Есть несколько типов написания составного оператора. Рассмотрим основные, на примере с оператором if.Обратите внимание в каких местах расставлены фигурные скобки.
Личтинг 8.2.
1)
if(n>=11&&n<=14){
                 printf("Na lugu pasetsya %d korov n", n);
}
2)

if(n>=11&&n<=14)
{
                printf("Na lugu pasetsya %d korov n", n);
}
3)

if(n>=11&&n<=14)
               {
               printf("Na lugu pasetsya %d korov n", n);
               }

Вам надо раз и навсегда определиться где вы будете ставить скобки и непременно следовать этому своему стилю. Каюсь, я и сам грешен, частенько используя второй стиль, перепрыгиваю на первый. Хотя смешивание это плохо. В ближайшее время, я постараюсь пройтись по всем листингам в блоге и привести оформление к единому образцу.
В качестве совета который я уже давал в комментариях. Всегда пишите фигурные скобки, даже если у вас один оператор в теле цикла, и в конструкции if. И при том сразу напишите заготовку if () {}, а потом уже записывайте условие и что делать при этом условии. Так же и с циклами.
Еще один совет, если у вас много вложенных друг в друга циклов и там еще вложены конструкции if, то очень удобно после закрывающей фигурной скобки писать к чему она относится например:
Листинг 8.3.


for (int i=0; i<100; i++){
      for(int j=i+1; j<200-i; j++){
            b=i*j+4;
            if(b%2!=0){
                  g=13*b;
            }//IF
      }//FOR(j)
}//FOR(i)


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


Оформление арифметических выражений и сложных условий.

И тут есть свои нюансы, в основном они касаются использования пробелов. 
Посмотрите на пример:
Листинг 8.4.
if ((x-1 < 0) && (b-x != 0))  print_task1(x, a*x*x+b, P);
   else
       if ((x-1 > 0) && (b+x == 0)) print_task1(x, (x-a)/x, P);

Использование умеренного количества пробелов облегчает чтение исходного кода программы. Но некоторые в и тут борщат. Не стоит ставить пробелы после каждого печатного знака, это не украшает программу. 

Использование комментариев.

Комментарии использовать нужно. Комментировать можно отдельные куски кода, функции, всякие оригинальные трюки используемые вами, но стоит избегать комментирования всего подряд.  

На сегодня все. Завтра ждите домашнее задание к предыдущему уроку. 
UPD (от 29 ноября):Сегодня был занят важными делами, поэтому не сумел подобрать задачи.Извиняюсь. 

Резюме урока:
  • Надеюсь каждый осознал важность использования одного стиля написания и оформления кода программы. И теперь определится для себя как ему удобно.


До свидания. Удачной недели.

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

Занятие 8.Оформление кода программы на Си.Уроки программирования для чайников.Язык Си.

Добрый день уважаемые читатели.
Сегодняшний пост начну не так как обычно. Сегодня 27 ноября, воскресенье, последнее воскресенье в этом месяце. А значит что? Значит, что сегодня отмечается международный День матери. От всей души хочу поздравить матерей, бабушек, у кого живы прабабушек, всех моих читателей, да и вообще всех матерей. Частенько мы бываем нетерпимы к родителям, особенно когда они читают нам мораль и учат жить. Вот сегодня замечательный повод извиниться перед своими мамами, за свою нетерпимость.Поздравить их, при наличии возможности подарить им цветы, им будет очень приятно.
Теперь же перейдем к самому занятию.Сегодня мы не будем разбирать какие-то новые конструкции языка, а поговорим об оформлении кода наших программ. Тема это очень важная. Дабы самому не путаться в своем коде написанном несколько месяцев назад. У каждого программиста есть свой стиль, свои привычки при написании программ. Они появляются с течением времени и закрепляются у каждого. В компаниях и командах где несколько разработчиков, обычно разработчики договариваются об каком-то одном стиле написания исходного кода. Оформляя определенным образом код программы, человек приучается к дисциплине. Вот об основных таких советах оформления кода мы сегодня и поговорим.

Имена и способы описания переменных.
Основной совет таков, давайте переменным осмысленные имена.
Это очень важный совет на самом деле. В маленьких программках которые мы пишем в практических занятиях это не столь серьезно, но в большой программе это вам очень поможет. Даже в небольших программах это иногда очень помогает. У меня есть небольшой опыт олимпиадного программирования, так вот когда переменным даешь короткие имена, ничего не обозначающие, можно очень легко запутаться. Когда имя переменной несет в себе информацию которая хранится в переменной, это позволяет легче искать ошибки в ходе отладки программы. А в условиях нехватки времени, отлаживать и оптимизировать программу  постоянно вспоминая что именно хранится в переменной q, что в get, очень непросто. Так что давайте своим переменным осмысленные имена. 
Немного о разделении слов в именах переменных. Пусть есть переменная целого типа в который содержится номер ящика. Её логично назвать number_box. Так вот, разделение слов с помощью нижнего подчеркивания, можно считать традицией программистов на Си. В паскалеподобных языках обычно подчеркивания для это цели не используют программисты. Для этого используется заглавные буквы. Возвращаясь к нашему примеру: NumberBox. Но так как Си регистрозависимый, а паскаль нет, то при если случайно ошибиться и написать потом numberBox, то в паскале программа будет работать, а в Си нет, ибо NumberBox и numberBox являются по правилам языка Си разными переменными. Отсюда, есть еще традиция в языке Си, имена переменных всегда пишутся маленьким буквами, а имена констант  только заглавными.И всегда понятно, где используется константа, а где переменная.  
Еще одна из условностей, это указание типа переменной в её имени. Опять же обратимся к нашему примеру, количество ящиков величина целая, поэтому достаточно удобно в имени это указать каким-то образом. Например так. n_number_box. Т.е. в начале имени переменной писать  определенный префикс для каждого типа свой (int - n, char - ch, double,float - d, file - f, и другие). Я лично таким способом не пользуюсь постоянно, хотя это иногда очень удобно.

Оформление логических блоков и запись лесенкой.
Запись лесенкой очень-очень полезная и практичная вещь. Оформлять код лесенкой это первое, что каждый может сделать на пути избежания ошибок в коде своих программ и повышения удобчитаемости.
Смысл в том, чтобы каждый вложенный блок сдвигать несколько в сторону. Вот пример такого оформления.
Листинг 8.1
#include <stdio.h>

int main(void)
{
      int n,b;
      printf("Vvedite chislo ot 1 do 100: ");
      scanf("%d", &n);
            if(n>=11&&n<=14){
                  printf("Na lugu pasetsya %d korov \n", n);
            }
            else{
                  b=n%10;
                  if(b==1)          printf("Na lugu pasetsya %d korova \n", n);
                  if(b>=2&&b<=4)    printf("Na lugu pasetsya %d korovy \n", n);
                  if(b>=5&&b<=9)    printf("Na lugu pasetsya %d korov \n", n);
                  if(b==0)          printf("Na lugu pasetsya %d korov \n", n);
            }
return(0); 
}

Оформляя таким образом свой код, его очень удобно читать другим, да и самому спустя какое-то время, да и непосредственно во время написания. Отступы можно делать как пробелами, так и табуляциями, я предпочитаю табуляции, и вам советую тоже пользоваться ими. Это удобно.Касательно табуляций и пробелов есть хороший пост на ресурсе Хабрахабр. Рекомендую ознакомится.

Теперь оформление логических блоков, а точнее разберемся с написание составного оператора. Есть несколько типов написания составного оператора. Рассмотрим основные, на примере с оператором if.Обратите внимание в каких местах расставлены фигурные скобки.
Личтинг 8.2.
1)
if(n>=11&&n<=14){
                 printf("Na lugu pasetsya %d korov \n", n);
}
2)

if(n>=11&&n<=14)
{
                printf("Na lugu pasetsya %d korov \n", n);
}
3)

if(n>=11&&n<=14)
               {
               printf("Na lugu pasetsya %d korov \n", n);
               }

Вам надо раз и навсегда определиться где вы будете ставить скобки и непременно следовать этому своему стилю. Каюсь, я и сам грешен, частенько используя второй стиль, перепрыгиваю на первый. Хотя смешивание это плохо. В ближайшее время, я постараюсь пройтись по всем листингам в блоге и привести оформление к единому образцу.
В качестве совета который я уже давал в комментариях. Всегда пишите фигурные скобки, даже если у вас один оператор в теле цикла, и в конструкции if. И при том сразу напишите заготовку if () {}, а потом уже записывайте условие и что делать при этом условии. Так же и с циклами.
Еще один совет, если у вас много вложенных друг в друга циклов и там еще вложены конструкции if, то очень удобно после закрывающей фигурной скобки писать к чему она относится например:
Листинг 8.3.


for (int i=0; i<100; i++){
      for(int j=i+1; j<200-i; j++){
            b=i*j+4;
            if(b%2!=0){
                  g=13*b;
            }//IF
      }//FOR(j)
}//FOR(i)


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


Оформление арифметических выражений и сложных условий.

И тут есть свои нюансы, в основном они касаются использования пробелов. 
Посмотрите на пример:
Листинг 8.4.
if ((x-1 < 0) && (b-x != 0))  print_task1(x, a*x*x+b, P);
   else
       if ((x-1 > 0) && (b+x == 0)) print_task1(x, (x-a)/x, P);

Использование умеренного количества пробелов облегчает чтение исходного кода программы. Но некоторые в и тут борщат. Не стоит ставить пробелы после каждого печатного знака, это не украшает программу. 

Использование комментариев.

Комментарии использовать нужно. Комментировать можно отдельные куски кода, функции, всякие оригинальные трюки используемые вами, но стоит избегать комментирования всего подряд.  

На сегодня все. Завтра ждите домашнее задание к предыдущему уроку. 
UPD (от 29 ноября):Сегодня был занят важными делами, поэтому не сумел подобрать задачи.Извиняюсь. 

Резюме урока:
  • Надеюсь каждый осознал важность использования одного стиля написания и оформления кода программы. И теперь определится для себя как ему удобно.


До свидания. Удачной недели.

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

Занятие 7.Циклические конструкции. Цикл со счетчиком for.Уроки программирования для чайников.Язык Си.

Прочитайте улучшенную версию этого урока "Цикл со счётчиком for".

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

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

Добрый день уважаемые друзья.
Вот и подошло время очередного занятия. Одно занятие было мной пропущено, из-за важных дел, я хотел его восстановить в течении недели, но навалились другие проблемы и мне не удалось этого сделать. Уж извините, всё предусмотреть невозможно. Сегодняшнее занятие будет посвящено новой управляющей конструкции. Сам того не подозревая, подбираю практические задачи для прошлого урока, я очень выгодно выбрал задачу с коровами, и дело вот в чем. Обычно, когда происходит изучение языка программирования не сразу понятно зачем и что нужно. И бывает достаточно сложно привести хороший пример. Можно конечно просто словами сказать, для чего предназначена та или иная конструкция. Но человеку гораздо понятнее, когда он сам увидел, и так сказать "пощупал", "поковырял" какой-то механизм. Еще Конфуций говорил "То, что я слышал, я забываю. То, что видел, я помню. То, что я делал сам, я  понимаю". Теперь вернемся к нашей задаче с коровами. Естественно мне надо было её как-то проверять. Нужно было ввести все значения от 0 до 99 и посмотреть какой результат программа выдает. Всё это можно было-бы сделать вручную, но это крайне не продуктивно.Представьте, сколько времени уйдет, чтобы проверить одну программу. Вот именно здесь мне и пригодилась циклическая конструкция. Циклическая конструкция предназначена для того, чтобы выполнять какую-то последовательность действий несколько раз. В нашем случае для того чтобы 100 раз запустить одну и ту же программу с разными входными данными. Надеюсь общее назначение циклов и польза от их применения вы осознали, теперь можно приступить непосредственно к изучению.

Циклическая конструкция for. (Цикл for)
В языке Си несколько циклических конструкций. Сегодня мы познакомимся с одной из них, а именно циклом for. Его ещё называют цикл со счетчиком. Он чаще всего используется, когда нужно повторить заданное действие известное число раз. 
Сначала посмотрим на формат цикла for. Он выглядит следующим образом:

Листинг 7.1:
for (инициализация счетчика; условие; изменение счетчика)
    оператор;

Теперь опишем словесно как работает эта инструкция. Цикл for состоит как бы из двух частей: заголовка (первая строка) и тела цикла (вторая строка). 
Сначала разберемся с заголовком. После слова for, в скобках, записаны три выражения. 

  • Первое выражение - инициализация счетчика
Мы должны завести переменную-счетчик и присвоить ей начальное значение.Например:

Листинг 7.2.
for (i=0;...;...) 
или
for (j=13;...;...)

  • Второе выражение - условие.
Здесь записано условие при котором будет выполняться тело цикла. Т.е. цикл будет работать пока условие истинно. Например:

Листинг 7.3.
for (i=0; i<10; ...)
или
for (d=-100; d<=0; ...)

  • Третье выражение - изменение счетчика.
Здесь записывается как изменяется переменная-счетчик после каждого выполнения тела цикла. Например:

Листинг 7.4.
for (i=0; i<10; i++)
или
for (d=-100; d<=0; d+10)

Теперь немного поговорим о теле цикла. Тело цикла всегда состоит из одного оператора. И если нам нужно использовать несколько операторов, то как и в случае с конструкцией if-else, применяется составной оператор {...}. 

Опишем работу цикла for словами и потом перейдем к рассмотрению практических примеров.
  1. Когда программа встречает слово for она понимает что перед ней цикл. 
  2. Сначала определяется переменная счетчик (выражение 1). 
  3. Проверяется условие выполнение цикла (выражение 2)
  4. Если условие ложно, то программа выходит из цикл for и продолжает свое выполнение. Т.е. если в самом начале условие будет ложно, то тело цикла не выполнится ни одного раза.
  5. Если условие истинно, то начинает выполняться тело цикла. 
  6. После того как тело цикла выполнится, программа возвращается к заголовку и выполняет изменение значение переменной-счетчика (выражение 3). 
  7. После этого возвращаемся к пункту два, и все действия повторяются до тех пор, пока условие не станет ложным.
Для лучшего понимаю работы циклической конструкции for разберем сначала простейший пример, а потом вернемся к нашей задачке с коровами.

Пусть нам надо посчитать сумму 10 чисел введенных пользователем с клавиатуры.
Такая программа будет выглядеть следующим образом:

Листинг 7.5.
#include <stdio.h>
int main(void){
      int i,summ=0, temp=0;

      for (i=0;i<10;i++){
            printf("\nVvedite chislo: ");
            scanf("%d",&temp);
            summ+=temp;
      }
      printf("Summa vvedennih chisel = %d\n",summ);
      return(0);
}

Теперь распишем по пунктам как работает наша программа.
Начнем с 4 строки, всё остальное вам уже должно быть ясно после ознакомления с предыдущими уроками.

  1. Переменная i счетчик и ей присваивается значение 0.
  2. Проверяется условие i<10. Оно истинно, значит выполняется тело цикла: выводится надпись, пользователь вводит число и оно прибавляется к переменной summ. Тело цикла заканчивается программа возвращается к заголовку.
  3. Программа выполняет выражение i++, изменяет значение переменной счетчика, в нашем случае увеличивает i на единицу.  Теперь i  = 1.
  4. Снова проверяется условие, i<10. Оно опять истинно. Снова выполняется тело цикла и происходит изменение переменной счетчика. И процесс повторяется. 
  5. Потом, через несколько шагов значение i после изменения  выражения счетчика становится равным 10. Проверяется условие. Оно ложно. Программа выходит из цикла и продолжает свое выполнение. В нашем случае выводит на экран значение переменной summ.
На рисунке представлен результат работы этой программы:

Припер работы программы с циклом for.

Ну а теперь напишем программу для проверки задания с коровами.
Изначально имеется программа (код юзера Dispose, с моими небольшими изменениями):

Листинг 7.6

#include <stdio.h>

int main(void)
{
      int n,b;
      printf("Vvedite chislo ot 1 do 100: ");
      scanf("%d", &n);
            if(n>=11&&n<=14)
            {
                  printf("Na lugu pasetsya %d korov \n", n);
            }
            else
            {
                  b=n%10;
                  if(b==1)          printf("Na lugu pasetsya %d korova \n", n);
                  if(b>=2&&b<=4)    printf("Na lugu pasetsya %d korovy \n", n);
                  if(b>=5&&b<=9)    printf("Na lugu pasetsya %d korov \n", n);
                  if(b==0)          printf("Na lugu pasetsya %d korov \n", n);
            }
return(0); 
}

Нам нужно проверить эту программу. Смотрим что количество коров задается в переменной n. Именно её и возьмем в качестве переменной счетчика. начальное значение у нас 0 конечное 99 . С каждым  шагом значение изменяется на 1 Значит заголовок будет выглядеть следующим образом: 
Листинг 7.7
for(n=0,n<=99,n++)

Теперь из исходной программы удалим строчки, где просится ввести число n и строку, где введенное число считывается в переменную n. Также добавим туда наш заголовок и возьмем оставшуюся часть программы в фигурные скобки. Получим следующий код:

Листинг 7.8.

#include <stdio.h>
int main(void)
{
      int n,b;
      for(n=0;n<=99;n++)
        {
            if(n>=11&&n<=14)
            {
                  printf("Na lugu pasetsya %d korov \n", n);
            }
            else
            {
                  b=n%10;
                  if(b==1)          printf("Na lugu pasetsya %d korova \n", n);
                  if(b>=2&&b<=4)    printf("Na lugu pasetsya %d korovy \n", n);
                  if(b>=5&&b<=9)    printf("Na lugu pasetsya %d korov \n", n);
                  if(b==0)          printf("Na lugu pasetsya %d korov \n", n);
            }
        }
return(0); 
}


Если теперь запустить нашу полученную программу то можно посмотреть, какое окончание прибавляет программа к какому количеству коров.


Иллюстрация работы программы листинг 7.8

Напоследок хочу заметить что тело цикла может содержать в себе другие циклы, т.е. могут быть вложенные циклы.И опять же советую вам использовать в теле цикла составной оператор.
На этом на сегодня всё.

Резюме урока:

  • Посмотрели на примерах для чего используются в программировании циклы.
  • Изучили циклическую конструкцию for.

Задания для практической работы:

  1. На вход поступает четыре целых числа a,b,c,d. Выведите все числа на отрезке от a до b, дающие остаток c при делении на d.
  2. На вход программе подается число N. Напишите программу, для вычисления произведения всех чисел от 1 до N (N!  N-факториал). По условию N не больше 10.
  3. На вход программе подается два числа.Первое сумма двух неизвестных чисел х и у, а второе произведение х и у. По двум введенным числам, найти х и у. х и у не превосходят 1000.
  4. На вход программе подается одно положительное число N, которое по не превосходит 10000. Написать программу которая выводит одно единственное число равное сумме чисел от 1 до N. 
Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом  Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них. 

    Занятие 7.Циклические конструкции. Цикл со счетчиком for.Уроки программирования для чайников.Язык Си.

    Прочитайте улучшенную версию этого урока "Цикл со счётчиком for".

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

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

    Добрый день уважаемые друзья.
    Вот и подошло время очередного занятия. Одно занятие было мной пропущено, из-за важных дел, я хотел его восстановить в течении недели, но навалились другие проблемы и мне не удалось этого сделать. Уж извините, всё предусмотреть невозможно. Сегодняшнее занятие будет посвящено новой управляющей конструкции. Сам того не подозревая, подбираю практические задачи для прошлого урока, я очень выгодно выбрал задачу с коровами, и дело вот в чем. Обычно, когда происходит изучение языка программирования не сразу понятно зачем и что нужно. И бывает достаточно сложно привести хороший пример. Можно конечно просто словами сказать, для чего предназначена та или иная конструкция. Но человеку гораздо понятнее, когда он сам увидел, и так сказать "пощупал", "поковырял" какой-то механизм. Еще Конфуций говорил "То, что я слышал, я забываю. То, что видел, я помню. То, что я делал сам, я  понимаю". Теперь вернемся к нашей задаче с коровами. Естественно мне надо было её как-то проверять. Нужно было ввести все значения от 0 до 99 и посмотреть какой результат программа выдает. Всё это можно было-бы сделать вручную, но это крайне не продуктивно.Представьте, сколько времени уйдет, чтобы проверить одну программу. Вот именно здесь мне и пригодилась циклическая конструкция. Циклическая конструкция предназначена для того, чтобы выполнять какую-то последовательность действий несколько раз. В нашем случае для того чтобы 100 раз запустить одну и ту же программу с разными входными данными. Надеюсь общее назначение циклов и польза от их применения вы осознали, теперь можно приступить непосредственно к изучению.

    Циклическая конструкция for. (Цикл for)
    В языке Си несколько циклических конструкций. Сегодня мы познакомимся с одной из них, а именно циклом for. Его ещё называют цикл со счетчиком. Он чаще всего используется, когда нужно повторить заданное действие известное число раз. 
    Сначала посмотрим на формат цикла for. Он выглядит следующим образом:

    Листинг 7.1:
    for (инициализация счетчика; условие; изменение счетчика)
        оператор;

    Теперь опишем словесно как работает эта инструкция. Цикл for состоит как бы из двух частей: заголовка (первая строка) и тела цикла (вторая строка). 
    Сначала разберемся с заголовком. После слова for, в скобках, записаны три выражения. 

    • Первое выражение - инициализация счетчика
    Мы должны завести переменную-счетчик и присвоить ей начальное значение.Например:

    Листинг 7.2.
    for (i=0;...;...) 
    или
    for (j=13;...;...)

    • Второе выражение - условие.
    Здесь записано условие при котором будет выполняться тело цикла. Т.е. цикл будет работать пока условие истинно. Например:

    Листинг 7.3.
    for (i=0; i<10; ...)
    или
    for (d=-100; d<=0; ...)

    • Третье выражение - изменение счетчика.
    Здесь записывается как изменяется переменная-счетчик после каждого выполнения тела цикла. Например:

    Листинг 7.4.
    for (i=0; i<10; i++)
    или
    for (d=-100; d<=0; d+10)

    Теперь немного поговорим о теле цикла. Тело цикла всегда состоит из одного оператора. И если нам нужно использовать несколько операторов, то как и в случае с конструкцией if-else, применяется составной оператор {...}. 

    Опишем работу цикла for словами и потом перейдем к рассмотрению практических примеров.
    1. Когда программа встречает слово for она понимает что перед ней цикл. 
    2. Сначала определяется переменная счетчик (выражение 1). 
    3. Проверяется условие выполнение цикла (выражение 2)
    4. Если условие ложно, то программа выходит из цикл for и продолжает свое выполнение. Т.е. если в самом начале условие будет ложно, то тело цикла не выполнится ни одного раза.
    5. Если условие истинно, то начинает выполняться тело цикла. 
    6. После того как тело цикла выполнится, программа возвращается к заголовку и выполняет изменение значение переменной-счетчика (выражение 3). 
    7. После этого возвращаемся к пункту два, и все действия повторяются до тех пор, пока условие не станет ложным.
    Для лучшего понимаю работы циклической конструкции for разберем сначала простейший пример, а потом вернемся к нашей задачке с коровами.

    Пусть нам надо посчитать сумму 10 чисел введенных пользователем с клавиатуры.
    Такая программа будет выглядеть следующим образом:

    Листинг 7.5.
    #include <stdio.h>
    int main(void){
          int i,summ=0, temp=0;

          for (i=0;i<10;i++){
                printf("\nVvedite chislo: ");
                scanf("%d",&temp);
                summ+=temp;
          }
          printf("Summa vvedennih chisel = %d\n",summ);
          return(0);
    }

    Теперь распишем по пунктам как работает наша программа.
    Начнем с 4 строки, всё остальное вам уже должно быть ясно после ознакомления с предыдущими уроками.

    1. Переменная i счетчик и ей присваивается значение 0.
    2. Проверяется условие i<10. Оно истинно, значит выполняется тело цикла: выводится надпись, пользователь вводит число и оно прибавляется к переменной summ. Тело цикла заканчивается программа возвращается к заголовку.
    3. Программа выполняет выражение i++, изменяет значение переменной счетчика, в нашем случае увеличивает i на единицу.  Теперь i  = 1.
    4. Снова проверяется условие, i<10. Оно опять истинно. Снова выполняется тело цикла и происходит изменение переменной счетчика. И процесс повторяется. 
    5. Потом, через несколько шагов значение i после изменения  выражения счетчика становится равным 10. Проверяется условие. Оно ложно. Программа выходит из цикла и продолжает свое выполнение. В нашем случае выводит на экран значение переменной summ.
    На рисунке представлен результат работы этой программы:

    Припер работы программы с циклом for.

    Ну а теперь напишем программу для проверки задания с коровами.
    Изначально имеется программа (код юзера Dispose, с моими небольшими изменениями):

    Листинг 7.6

    #include <stdio.h>

    int main(void)
    {
          int n,b;
          printf("Vvedite chislo ot 1 do 100: ");
          scanf("%d", &n);
                if(n>=11&&n<=14)
                {
                      printf("Na lugu pasetsya %d korov \n", n);
                }
                else
                {
                      b=n%10;
                      if(b==1)          printf("Na lugu pasetsya %d korova \n", n);
                      if(b>=2&&b<=4)    printf("Na lugu pasetsya %d korovy \n", n);
                      if(b>=5&&b<=9)    printf("Na lugu pasetsya %d korov \n", n);
                      if(b==0)          printf("Na lugu pasetsya %d korov \n", n);
                }
    return(0); 
    }

    Нам нужно проверить эту программу. Смотрим что количество коров задается в переменной n. Именно её и возьмем в качестве переменной счетчика. начальное значение у нас 0 конечное 99 . С каждым  шагом значение изменяется на 1 Значит заголовок будет выглядеть следующим образом: 
    Листинг 7.7
    for(n=0,n<=99,n++)

    Теперь из исходной программы удалим строчки, где просится ввести число n и строку, где введенное число считывается в переменную n. Также добавим туда наш заголовок и возьмем оставшуюся часть программы в фигурные скобки. Получим следующий код:

    Листинг 7.8.

    #include <stdio.h>
    int main(void)
    {
          int n,b;
          for(n=0;n<=99;n++)
            {
                if(n>=11&&n<=14)
                {
                      printf("Na lugu pasetsya %d korov \n", n);
                }
                else
                {
                      b=n%10;
                      if(b==1)          printf("Na lugu pasetsya %d korova \n", n);
                      if(b>=2&&b<=4)    printf("Na lugu pasetsya %d korovy \n", n);
                      if(b>=5&&b<=9)    printf("Na lugu pasetsya %d korov \n", n);
                      if(b==0)          printf("Na lugu pasetsya %d korov \n", n);
                }
            }
    return(0); 
    }


    Если теперь запустить нашу полученную программу то можно посмотреть, какое окончание прибавляет программа к какому количеству коров.


    Иллюстрация работы программы листинг 7.8

    Напоследок хочу заметить что тело цикла может содержать в себе другие циклы, т.е. могут быть вложенные циклы.И опять же советую вам использовать в теле цикла составной оператор.
    На этом на сегодня всё.

    Резюме урока:

    • Посмотрели на примерах для чего используются в программировании циклы.
    • Изучили циклическую конструкцию for.

    Задания для практической работы:

    1. На вход поступает четыре целых числа a,b,c,d. Выведите все числа на отрезке от a до b, дающие остаток c при делении на d.
    2. На вход программе подается число N. Напишите программу, для вычисления произведения всех чисел от 1 до N (N!  N-факториал). По условию N не больше 10.
    3. На вход программе подается два числа.Первое сумма двух неизвестных чисел х и у, а второе произведение х и у. По двум введенным числам, найти х и у. х и у не превосходят 1000.
    4. На вход программе подается одно положительное число N, которое по не превосходит 10000. Написать программу которая выводит одно единственное число равное сумме чисел от 1 до N. 
    Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом  Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них. 

      Занятие 6. Оператор множественного выбора switch. Уроки программирования для чайников.Язык Си.

      Прочитайте улучшенную версию этого урока "Оператор выбора switch".

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

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

      Добрый день друзья.
      Вот и подошло время очередного занятия. Оно будет посвящено инструкции switch.  Это еще одна из инструкций управления программой. В качестве вступления вспомним опять пример с дорогами. Представьте, что у нас развилка не из двух, а из трех дорог. Тут уже одной конструкцией if-else не отделаешься. Можно конечно использовать несколько конструкций if-else, но представьте если у нас будет 10 вариантов, например, для каждой цифры от 0 до 9 нужно выполнять какое-то своё действие? Тогда нам придется написать несколько вложенных конструкций if-else, но это не очень удобно. Для этих целей и служит инструкция switch, о которой мы и поговорим в сегодняшнем занятии.

      Инструкция switch.
      Как уже упоминалось выше, данная инструкция служит для выбора одного из многих путей. Рассмотрим её формат.
      Листинг 6.1
      switch (выражение) {
          caseконстное выражение: операторы
          caseконстное выражение: операторы
          default: операторы
      }

      Как видите, инструкция switchсостоит из двух частей: заголовок switch, тело инструкции, записанное в составном операторе (фигурных скобках). В заголовке нас интересует только выражение в скобках. Именно от значения этого выражения зависит, какая из ветвей программы будет выполняться. Для этого выражения существует одно ограничение.
      • Там может быть записана любое выражение, или переменная символьного или целочисленного типа.

      Ниже приведены примеры правильного и неправильного заголовков.

      Листинг 6.2.
      int c,a;
      char s;
      double g;

      switch (c)        //Правильно (целая переменная)
      switch ((a+c)+2)  //Правильно (выражение целого типа)
      switch (g)        //Неправильно (вещественная переменная)
      switch (s)        //Правильно (символьная переменная)

       В фигурных скобках записаны несколько (не обязательно две) ветвей case. Каждая такая ветка соответствует одному из вариантов выбора. Каждая из таких веток состоит из слова case, после которого через пробел записано константное выражении, или другими словами одно из значений выражения в заголовке. Именно с этим выражением сравнивается выражение в заголовке оператора switch (инструкция и оператор это одно и то же, поэтому не удивляйтесь, что иногда я пишу инструкция switch, а иногда оператор switch). Как только выражение в заголовке совпадает с одним из константных выражений в какой-либо ветке  case, начинает выполнять операторы следующие в данной ветке после двоеточия. 
      • Тут тоже есть ограничение,  константные выражения каждой из ветки case должны быть разными между собой.

       Т.е. следующий пример ошибочен (так как для двух веток (первой и третей) константные выражения совпадают :
      Листинг 6.3
      {
      case 10: a+10; break;
      case 34: a+34; break;
      case 10: a-23; break;
      }

      В теле оператора switchможет быть еще одна ветка default. Она необязательна. Её операторы выполняются, если выражение в заголовке оператора switchне совпало ни с одним из константных выражений в ветках  case. Если же такой ветки не будет, а ни одно из константных выражений не подходит, то просто ничего не будет делаться. И программа продолжит свое выполнение.

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

      Для лучшего усвоения понимая работы оператора switch, и иллюстрации некоторых особенностей, давайте напишем программу которая реализует управление в какой-то гипотетической игре, потом при изучении циклов и функций мы переделаем это меню. Оно будет оболочкой для всех остальных программ. А пока, что примем следующие клавиши управления: W– вперед, A – влево, S – вниз, D – вправо.  Так как это символы для их хранения потребуется переменная типа char.

      Листинг6.4
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'w': printf("\nVpered\n");
                  case 'a': printf("\nVlevo\n");
                  case 's': printf("\nVniz\n");
                  case 'd': printf("\nVpravo\n");
                  default: printf("\nNeizvestnaya komanda\n");
            }
            return (0);
      }

      На рисунке ниже вы видите, как работает программа при нажатии клавиши a.

      Рис. 6.1 Иллюстрация сквозного выполнения инструкции switch.

      Как видите, на экране появилось, не то, что предполагалось. Эта программа иллюстрирует одну из особенностей инструкции switch – сквозное выполнение. Т.е. после того, как нашлось совпадение в одном из case, если явно не указан выход из оператора switch, то программа выполняет последовательно все остальные ветки записанные ниже той, с которой выполнено совпадение, пока не закончится оператор switch или пока не будет явно указан выход из оператора. В нашем случае мы нажали  клавишу a, программа выполнила ветку с выражение a, и продолжила выполнять последовательно все ветки, которые записаны в коде после этой, т.е. ветки s,d,w и ветку default. Эта особенность может играть как  отрицательную роль, как в нашем случае, так и положительную (мы применим её чуть позже). 
      Для выхода из оператора switchиспользуется оператор безусловного выхода break.Он так же применяется и в других конструкциях, например, в циклах, но об этом мы еще будем говорить. Как только программа встретит данный оператор, она закончит выполнение инструкции switch. Поэтому, нам нужно в каждую веточку дописать этот оператор выхода. Я настоятельно рекомендую писать break во все без исключения  ветки. С учетом внесенных изменений программа примет следующий вид:

      Листинг 6.5
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'w': printf("\nVpered\n"); break;
                  case 'a': printf("\nVlevo\n"); break;
                  case 's': printf("\nVniz\n"); break;
                  case 'd': printf("\nVpravo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
            }
            return (0);
      }
      Теперь если запустить программу она будет работать  так, как и предполагалось.
      Сейчас поговорим об еще одной особенности оператора switch. Внутри тела оператора, порядок написания caseи default не важен. Т.е. Сначала можно написать ветку default, а затем ветки case. Или же ветку default можно пометить между других веток case. Программа Листинг 6.6  работает так же как и программа Листинг 6.5:

      Листинг6.5
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'w': printf("\nVpered\n"); break;
                  case 'a': printf("\nVlevo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
                  case 's': printf("\nVniz\n"); break;
                  case 'd': printf("\nVpravo\n"); break;
            }
            return (0);
      } 
      Теперь разберемся с ситуацией когда сквозное выполнение оператора switch играет полезную роль. Представим ситуацию,  что у пользователя нажата клавиша CapsLock. Поэтому все вводимы буквы будут в верхнем регистре. Но компьютер различает буквы в верхнем и нижнем регистре, и поэтому если в нашей программе написать W, то мы увидим на экране надпись о неизвестной команде.  Для того чтобы исправить эту оплошность, надо добавить еще 4 ветки case. Перепишем программу.

      Листинг 6.7
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'W': printf("\nVpered\n"); break;              
                  case 'w': printf("\nVpered\n"); break;
                  case 'A': printf("\nVlevo\n"); break;
                  case 'a': printf("\nVlevo\n"); break;
                  case 'S': printf("\nVniz\n"); break;
                  case 's': printf("\nVniz\n"); break;
                  case 'D': printf("\nVpravo\n"); break;
                  case 'd': printf("\nVpravo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
            }
            return (0);
      }
      Сейчас она будет работать так, как надо. А вот теперь вспомним о сквозном выполнении оператора switch. Рассмотрим на примере команды «Вперед».
      Имеем^

      Листинг6.8
      case 'W': printf("\nVpered\n"); break;              
      case 'w': printf("\nVpered\n"); break;

      Если в верхней строчке Листинг 6.8 убрать оператор break, то из-за свойства сквозного выполнения, выполнится сначала одна функция printf, а затем вторая из ветки с маленькой w. Потом программа встретит breakи закончит выполнение оператора. Теперь уберем первую функцию printf.

      Листинг 6.9
      case 'W':              
      case 'w': printf("\nVpered\n"); break;

      Теперь программа будет работать независимо от того в каком регистре введена буква. Т.е. мы как бы для одной ветки сделали два условия. Если какое-либо из них выполнится, то эта ветка выполнится. Т.е. если мы нажмем W то программа выполнит сначала операторы ветки W. Там их нет и оператор breakотсутствует,  программа начнет выполнять следующую ветку w. И потом встретив оператор break выйдет из инструкции switch. Таким же образом поступим с остальными ветками. Программа приобретет следующий вид:

      Листинг 6.10
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'W':        
                  case 'w': printf("\nVpered\n"); break;
                  case 'A':
                  case 'a': printf("\nVlevo\n"); break;
                  case 'S':
                  case 's': printf("\nVniz\n"); break;
                  case 'D':
                  case 'd': printf("\nVpravo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
            }
            return (0);
      }

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

      Резюме урока:
      • Узнали об операторе множественного выбора switch
      • Разобрались с нюансами его работы.
      • Научились использовать оператор безусловного выхода break.
      • Поговорили о области применимости инструкций switch и if-else.


      Задание для практической работы:
            Написать программу простейший  калькулятор для следующих действий  +,-,*,/. На вход программе подается два числа и знак действия. Например: 4 23.5 *. Программа должна вывести результат арифметического действия. При недопустимой арифметической команде вывести ERROR.


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

      Занятие 6. Оператор множественного выбора switch. Уроки программирования для чайников.Язык Си.

      Прочитайте улучшенную версию этого урока "Оператор выбора switch".

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

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

      Добрый день друзья.
      Вот и подошло время очередного занятия. Оно будет посвящено инструкции switch.  Это еще одна из инструкций управления программой. В качестве вступления вспомним опять пример с дорогами. Представьте, что у нас развилка не из двух, а из трех дорог. Тут уже одной конструкцией if-else не отделаешься. Можно конечно использовать несколько конструкций if-else, но представьте если у нас будет 10 вариантов, например, для каждой цифры от 0 до 9 нужно выполнять какое-то своё действие? Тогда нам придется написать несколько вложенных конструкций if-else, но это не очень удобно. Для этих целей и служит инструкция switch, о которой мы и поговорим в сегодняшнем занятии.

      Инструкция switch.
      Как уже упоминалось выше, данная инструкция служит для выбора одного из многих путей. Рассмотрим её формат.
      Листинг 6.1
      switch (выражение) {
          caseконстное выражение: операторы
          caseконстное выражение: операторы
          default: операторы
      }

      Как видите, инструкция switchсостоит из двух частей: заголовок switch, тело инструкции, записанное в составном операторе (фигурных скобках). В заголовке нас интересует только выражение в скобках. Именно от значения этого выражения зависит, какая из ветвей программы будет выполняться. Для этого выражения существует одно ограничение.
      • Там может быть записана любое выражение, или переменная символьного или целочисленного типа.

      Ниже приведены примеры правильного и неправильного заголовков.

      Листинг 6.2.
      int c,a;
      char s;
      double g;

      switch (c)        //Правильно (целая переменная)
      switch ((a+c)+2)  //Правильно (выражение целого типа)
      switch (g)        //Неправильно (вещественная переменная)
      switch (s)        //Правильно (символьная переменная)

       В фигурных скобках записаны несколько (не обязательно две) ветвей case. Каждая такая ветка соответствует одному из вариантов выбора. Каждая из таких веток состоит из слова case, после которого через пробел записано константное выражении, или другими словами одно из значений выражения в заголовке. Именно с этим выражением сравнивается выражение в заголовке оператора switch (инструкция и оператор это одно и то же, поэтому не удивляйтесь, что иногда я пишу инструкция switch, а иногда оператор switch). Как только выражение в заголовке совпадает с одним из константных выражений в какой-либо ветке  case, начинает выполнять операторы следующие в данной ветке после двоеточия. 
      • Тут тоже есть ограничение,  константные выражения каждой из ветки case должны быть разными между собой.

       Т.е. следующий пример ошибочен (так как для двух веток (первой и третей) константные выражения совпадают :
      Листинг 6.3
      {
      case 10: a+10; break;
      case 34: a+34; break;
      case 10: a-23; break;
      }

      В теле оператора switchможет быть еще одна ветка default. Она необязательна. Её операторы выполняются, если выражение в заголовке оператора switchне совпало ни с одним из константных выражений в ветках  case. Если же такой ветки не будет, а ни одно из константных выражений не подходит, то просто ничего не будет делаться. И программа продолжит свое выполнение.

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

      Для лучшего усвоения понимая работы оператора switch, и иллюстрации некоторых особенностей, давайте напишем программу которая реализует управление в какой-то гипотетической игре, потом при изучении циклов и функций мы переделаем это меню. Оно будет оболочкой для всех остальных программ. А пока, что примем следующие клавиши управления: W– вперед, A – влево, S – вниз, D – вправо.  Так как это символы для их хранения потребуется переменная типа char.

      Листинг6.4
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'w': printf("\nVpered\n");
                  case 'a': printf("\nVlevo\n");
                  case 's': printf("\nVniz\n");
                  case 'd': printf("\nVpravo\n");
                  default: printf("\nNeizvestnaya komanda\n");
            }
            return (0);
      }

      На рисунке ниже вы видите, как работает программа при нажатии клавиши a.

      Рис. 6.1 Иллюстрация сквозного выполнения инструкции switch.

      Как видите, на экране появилось, не то, что предполагалось. Эта программа иллюстрирует одну из особенностей инструкции switch – сквозное выполнение. Т.е. после того, как нашлось совпадение в одном из case, если явно не указан выход из оператора switch, то программа выполняет последовательно все остальные ветки записанные ниже той, с которой выполнено совпадение, пока не закончится оператор switch или пока не будет явно указан выход из оператора. В нашем случае мы нажали  клавишу a, программа выполнила ветку с выражение a, и продолжила выполнять последовательно все ветки, которые записаны в коде после этой, т.е. ветки s,d,w и ветку default. Эта особенность может играть как  отрицательную роль, как в нашем случае, так и положительную (мы применим её чуть позже). 
      Для выхода из оператора switchиспользуется оператор безусловного выхода break.Он так же применяется и в других конструкциях, например, в циклах, но об этом мы еще будем говорить. Как только программа встретит данный оператор, она закончит выполнение инструкции switch. Поэтому, нам нужно в каждую веточку дописать этот оператор выхода. Я настоятельно рекомендую писать break во все без исключения  ветки. С учетом внесенных изменений программа примет следующий вид:

      Листинг 6.5
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'w': printf("\nVpered\n"); break;
                  case 'a': printf("\nVlevo\n"); break;
                  case 's': printf("\nVniz\n"); break;
                  case 'd': printf("\nVpravo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
            }
            return (0);
      }
      Теперь если запустить программу она будет работать  так, как и предполагалось.
      Сейчас поговорим об еще одной особенности оператора switch. Внутри тела оператора, порядок написания caseи default не важен. Т.е. Сначала можно написать ветку default, а затем ветки case. Или же ветку default можно пометить между других веток case. Программа Листинг 6.6  работает так же как и программа Листинг 6.5:

      Листинг6.5
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'w': printf("\nVpered\n"); break;
                  case 'a': printf("\nVlevo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
                  case 's': printf("\nVniz\n"); break;
                  case 'd': printf("\nVpravo\n"); break;
            }
            return (0);
      } 
      Теперь разберемся с ситуацией когда сквозное выполнение оператора switch играет полезную роль. Представим ситуацию,  что у пользователя нажата клавиша CapsLock. Поэтому все вводимы буквы будут в верхнем регистре. Но компьютер различает буквы в верхнем и нижнем регистре, и поэтому если в нашей программе написать W, то мы увидим на экране надпись о неизвестной команде.  Для того чтобы исправить эту оплошность, надо добавить еще 4 ветки case. Перепишем программу.

      Листинг 6.7
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'W': printf("\nVpered\n"); break;              
                  case 'w': printf("\nVpered\n"); break;
                  case 'A': printf("\nVlevo\n"); break;
                  case 'a': printf("\nVlevo\n"); break;
                  case 'S': printf("\nVniz\n"); break;
                  case 's': printf("\nVniz\n"); break;
                  case 'D': printf("\nVpravo\n"); break;
                  case 'd': printf("\nVpravo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
            }
            return (0);
      }
      Сейчас она будет работать так, как надо. А вот теперь вспомним о сквозном выполнении оператора switch. Рассмотрим на примере команды «Вперед».
      Имеем^

      Листинг6.8
      case 'W': printf("\nVpered\n"); break;              
      case 'w': printf("\nVpered\n"); break;

      Если в верхней строчке Листинг 6.8 убрать оператор break, то из-за свойства сквозного выполнения, выполнится сначала одна функция printf, а затем вторая из ветки с маленькой w. Потом программа встретит breakи закончит выполнение оператора. Теперь уберем первую функцию printf.

      Листинг 6.9
      case 'W':              
      case 'w': printf("\nVpered\n"); break;

      Теперь программа будет работать независимо от того в каком регистре введена буква. Т.е. мы как бы для одной ветки сделали два условия. Если какое-либо из них выполнится, то эта ветка выполнится. Т.е. если мы нажмем W то программа выполнит сначала операторы ветки W. Там их нет и оператор breakотсутствует,  программа начнет выполнять следующую ветку w. И потом встретив оператор break выйдет из инструкции switch. Таким же образом поступим с остальными ветками. Программа приобретет следующий вид:

      Листинг 6.10
      #include <stdio.h>

      int main(void) {
            char c;

            printf("Vvedite komandu: ");
            c=getchar();

            switch (c) {
                  case 'W':        
                  case 'w': printf("\nVpered\n"); break;
                  case 'A':
                  case 'a': printf("\nVlevo\n"); break;
                  case 'S':
                  case 's': printf("\nVniz\n"); break;
                  case 'D':
                  case 'd': printf("\nVpravo\n"); break;
                  default: printf("\nNeizvestnaya komanda\n"); break;
            }
            return (0);
      }

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

      Резюме урока:
      • Узнали об операторе множественного выбора switch
      • Разобрались с нюансами его работы.
      • Научились использовать оператор безусловного выхода break.
      • Поговорили о области применимости инструкций switch и if-else.


      Задание для практической работы:
            Написать программу простейший  калькулятор для следующих действий  +,-,*,/. На вход программе подается два числа и знак действия. Например: 4 23.5 *. Программа должна вывести результат арифметического действия. При недопустимой арифметической команде вывести ERROR.


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

      Занятие 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. Между числом и пробелом должен стоять ровно один пробел.
      Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом  Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них. 

        Занятие 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. Между числом и пробелом должен стоять ровно один пробел.
        Если Вам понравился этот урок, расскажите о нем вашим друзьям. В этом  Вам могут помочь кнопки основных социальных сетей, расположенные ниже. Вам остается всего лишь кликнуть по любой из них.