Ветвления и логические операторы 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Ветвления и логические операторы



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

В си ветвления организуются с помощью конструкции

 

if (условие) {

<Действия, если условие выполняется>

} else {

<Действия, если условие не выполняется>

}

 

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

 

#include<stdio.h>

#include<conio.h>

 

int main() {

int pass;

 

prinf("Enter password: ");

scanf("%d", &pass);

 

if (pass == 1234) {

printf("Welcome");

} else {

prinf("Access denied!");

}

getch();

}

 

В си используется несколько логических операторов:

· > больше

· < меньше

· >= больше или равно

· <= меньше или равно

· == равно

·!= не равно

·! отрицание выражения

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

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

Например.

 

#include<conio.h>

#include<stdio.h>

 

int main() {

if (1) {

printf("TRUE");

} else {

printf("FALSE");

}

getch();

}

 

В этом примере будет выведено TRUE.

Вот пример, где ошибочно используется оператор присваивания вместо равно.

 

#include<conio.h>

#include<stdio.h>

 

int main() {

int i = 0;

 

if (i = 1) {

printf("i equals to 1");

} else {

printf("i equals to 0");

}

 

getch();

}

 

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

Оператор if может содержать всего одну ветвь, в этом случае вторая просто опускается, например.

 

#include<conio.h>

#include<stdio.h>

 

int main() {

float number;

 

printf("Enter number");

scanf("%f", &number);

 

if (number < 0.0f) {

number = -number;

}

 

printf("%.6f", number);

getch();

}

 

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

 

#include<conio.h>

#include<stdio.h>

 

int main() {

float number;

 

printf("Enter number ");

scanf("%f", &number);

 

if (number < 0.0f)

number = -number;

 

printf("%.6f", number);

getch();

}

 

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

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

 

#include<conio.h>

#include<stdio.h>

 

int main() {

unsigned day;

 

printf("Enter day ");

scanf("%d", &day);

 

if (day > 7) {

day = day % 7;

}

 

if (day == 0) {

printf("Sunday");

} else if (day == 1) {

printf("Monday");

} else if (day == 2) {

printf("Tuesday");

} else if (day == 3) {

printf("Wednesday");

} else if (day == 4) {

printf("Thursday");

} else if (day == 5) {

printf("Friday");

} else if (day == 6) {

printf("Saturday");

}

 

getch();

}

 

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

 

#include <stdio.h>

#include <conio.h>

 

int main() {

unsigned month, year;

printf("Enter month");

scanf("%d", &month);

printf("Enter year");

scanf("%d", &year);

if (month < 13) {

if (month == 1 ||

month == 3 ||

month == 5 ||

month == 7 ||

month == 8 ||

month == 10 ||

month == 12) {

printf("31 days");

} else if (month == 2) {

if (year % 4 == 0) {

printf("29 days");

} else {

printf("28 days");

}

} else {

printf("30 days");

}

} else {

printf("No such month");

}

}

 

Оператор Switch

Рассмотрим пример из темы "ветвления". Программа выводит название дня недели по порядковому номера

 

#include<conio.h>

#include<stdio.h>

 

int main() {

unsigned day;

 

printf("Enter day ");

scanf("%d", &day);

 

if (day > 7) {

day = day % 7;

}

 

if (day == 0) {

printf("Sunday");

} else if (day == 1) {

printf("Monday");

} else if (day == 2) {

printf("Tuesday");

} else if (day == 3) {

printf("Wednesday");

} else if (day == 4) {

printf("Thursday");

} else if (day == 5) {

printf("Friday");

} else if (day == 6) {

printf("Saturday");

}

 

getch();

}

 

Этот код состоит из семи идущих друг за другом операторов if. Его код можно упростить с помощью оператора switch.

 

#include<conio.h>

#include<stdio.h>

 

int main() {

unsigned day;

 

printf("Enter day ");

scanf("%d", &day);

 

if (day > 7) {

day = day % 7;

}

 

switch (day) {

case 0:

printf("Sunday");

break;

case 1:

printf("Monday");

break;

case 2:

printf("Tuesday");

break;

case 3:

printf("Wednesday");

break;

case 4:

printf("Thursday");

break;

case 5:

printf("Friday");

break;

default:

printf("Saturday");

}

 

getch();

}

 

Оператор switch принимает в качестве аргумента число, и в зависимости от его значения выполняет те или иные команды.

 

switch (<переменная>) {

case <значение 1>:

<ветвь 1>

[case <значение 2>:

<ветвь 2>]

[default:

<действия по умолчанию>]

}

 

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

В примере выше каждая ветвь оканчивается оператором break. Это важно. Когда компьютер видит оператор break, он выходит из оператора switch. Если бы он отсутствовал, то программа "провалилась" бы дальше, и стала выполнять следующие ветви.

 

#include<conio.h>

#include<stdio.h>

 

int main() {

unsigned day;

 

printf("Enter day ");

scanf("%d", &day);

 

if (day > 7) {

day = day % 7;

}

 

switch (day) {

case 0:

printf("Sunday");

case 1:

printf("Monday");

case 2:

printf("Tuesday");

case 3:

printf("Wednesday");

case 4:

printf("Thursday");

case 5:

printf("Friday");

default:

printf("Saturday");

}

 

getch();

}

 

Введите значение, например 3, и вы увидите, что программа выведет

WednesdayThursdayFridaySaturday

то есть все ветви, после найденной.

Операторы каждой из ветвей могут быть обрамлены фигурными скобками (и так даже лучше). Тогда каждая из ветвей будет отдельным блоком, в котором можно определять свои переменные. Пример программы, которая запрашивает у пользователя число, оператор и второе число и выполняет действие.

 

#include <conio.h>

#include <stdio.h>

#include <stdlib.h>

 

int main() {

float a, b, c;

char op;

 

scanf("%f %c %f", &a, &op, &b);

switch (op) {

case '+': {

c = a + b;

break;

}

case '-': {

c = a - b;

break;

}

case '/': {

if (b!= 0.0) {

c = a / b;

} else {

printf("Error: divide by zero");

getch();

exit(1);

}

break;

}

case '*': {

c = a * b;

break;

}

default:

printf("No operation defined");

getch();

exit(1);

}

 

printf("%.6f", c);

getch();

}

 

Если ввести

1 + 2

то будет выведен результат операции 1 + 2 = 3

Хочу обратить внимание, что литеры типа '+' и т.п. воспринимаются в качестве чисел, поэтому их можно использовать в операторе switch. В этой программе использовалась функция exit из библиотеки stdlib. Функция останавливает работу программы и возвращает результат её работы. Если возвращается истина (ненулевое значение), то это значит, что программа была выполнена с ошибкой.

Ветвь default может располагаться в любом месте, не обязательно в конце. Этот код также будет нормально работать.

 

switch (day) {

case 0:

printf("Sunday");

break;

case 1:

printf("Monday");

break;

case 2:

printf("Tuesday");

break;

case 3:

printf("Wednesday");

break;

case 4:

printf("Thursday");

break;

default:

printf("Saturday");

break;

case 5:

printf("Friday");

break;

}

 

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

Возможные значения аргумента оператора switch могут располагаться в любом порядке, но должны быть константными значеними. Это значит, что следующий код не заработает

 

#include<conio.h>

#include<stdio.h>

#include<stdlib.h>

 

int main() {

//Это, конечно, константа, но не может быть использована как

//значение для оператора switch

const int monday = 0;

unsigned day;

 

printf("Enter day ");

scanf("%d", &day);

 

if (day > 7) {

day = day % 7;

}

 

switch (day) {

case monday:

printf("Sunday");

break;

case 1:

printf("Monday");

break;

case 2:

printf("Tuesday");

break;

case 3:

printf("Wednesday");

break;

case 4:

printf("Thursday");

break;

default:

printf("Saturday");

break;

case 5:

printf("Friday");

break;

}

 

getch();

}

 

Логические операторы

Логические операторы – это операторы, которые принимают в качестве аргументов логические значений (ложь или истину) и возвращают логическое значение. Как и обычные операторы, они могут быть одноместными (унарными, т.е. принимать один аргумент), двуместными (бинарные, принимают два аргумента), трёхместными и т.д.

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

 

#include <conio.h>

#include <stdio.h>

 

void main() {

char boolValue = -71;

if (boolValue) {

printf("boolValue is true");

} else {

printf("boolValue is false");

}

_getch();

}

 

Логические значения обычно порождаются операторами сравнения:

· ==

·!=

· >

· <

· >=

· <=

В языке си представлено три логических оператора: И, ИЛИ и НЕ. Начнём с самого простого.

Логическое отрицание

Оператор НЕ (NOT) используется для того, чтобы инвертировать значение аргумента. То есть, если ему передали истину, то он вернёт ложь, если получил ложь в качестве аргумента, то вернёт истину.

 

X NOT X
   
   

 

В си отрицание представлено оператором!. Например.

 

#include <conio.h>

#include <stdio.h>

 

void main() {

int i = 0;

if (i) {

printf("i is true\n");

}

if (!i) {

printf("i is not true\n");

}

if (!!i) {

printf("i is not not true\n");

}

if (!!!i) {

printf("i is not not not true\n");

}

_getch();

}

 

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

Логическое И

Оператор И (AND, логическое умножение) возвращает истину тогда и только тогда, когда оба аргумента являются истиной.

 

X Y X AND Y
     
     
     
     

 

В си логическое умножение представлено оператором &&. Например, задача – в кружок военных сапёров допускаются только совершеннолетние граждане мужского пола. То есть, претендентом может стать только тот, для которого одновременно два условия являются истиной.

 

#include <conio.h>

#include <stdio.h>

 

void main() {

char gender;

unsigned int age;

 

printf("Enter gender ('M' or 'F')\n");

scanf("%c", &gender);

printf("Enter age\n");

scanf("%u", &age);

 

if (gender == 'M' && age > 17) {

printf("Wellcome");

} else {

printf("Go away");

}

_getch();

}

 

Оператор И может применяться последовательно к нескольким аргументам. Для него действует ассоциативный[3] и коммутативный[4] законы. Усовершенствуем программу, будем также вводить рост:

 

#include <conio.h>

#include <stdio.h>

 

void main() {

char gender;

unsigned int age;

unsigned int height;

 

printf("Enter gender ('M' or 'F')\n");

scanf("%c", &gender);

printf("Enter age\n");

scanf("%u", &age);

printf("Enter height\n");

scanf("%u", &height);

 

if (gender == 'M' && age > 17 && height >= 180) {

printf("Wellcome");

} else {

printf("Go away");

}

_getch();

}

 

Также условие могло быть записано

 

(gender == 'M' && age > 17) && height >= 180

 

или

 

gender == 'M' && (age > 17 && height >= 180)

 

или

 

(age > 17 && height >= 180) && gender == 'M'

 

Логическое ИЛИ

Оператор логическое ИЛИ (логическое сложение, OR) истинен тогда, когда истиной является хотя бы один его аргумент.

 

X Y X OR Y
     
     
     
     

 

В си ИЛИ представлен оператором ||. Например, усовершенствуем программу: теперь пол можно вводить как большой, так и маленькой буквой

 

#include <conio.h>

#include <stdio.h>

 

void main() {

char genderInput;

char gender;

unsigned int age;

unsigned int height;

 

printf("Enter gender ('M' or 'F')\n");

scanf("%c", &genderInput);

printf("Enter age\n");

scanf("%u", &age);

printf("Enter height\n");

scanf("%u", &height);

 

if (genderInput == 'M' || genderInput == 'm') {

gender = 1;

} else {

gender = 0;

}

 

if ((age > 17 && height >= 180) && gender) {

printf("Wellcome");

} else {

printf("Go away");

}

_getch();

}

 

Как и в случае оператора И, ИЛИ коммутативен[5] и ассоциативен[6].

Операторы можно перемешивать друг с другом, создавая сложные операторы.

 

#include <conio.h>

#include <stdio.h>

 

void main() {

char gender;

unsigned int age;

unsigned int height;

 

printf("Enter gender ('M' or 'F')\n");

scanf("%c", &gender);

printf("Enter age\n");

scanf("%u", &age);

printf("Enter height\n");

scanf("%u", &height);

 

if ((age > 17 && height >= 180) && (gender == 'M' || gender == 'm')) {

printf("Wellcome");

} else {

printf("Go away");

}

_getch();

}

 

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

Пример: закон де-Моргана.

Чтобы сменить И на ИЛИ (или наоборот), необходимо инвертировать значения всех операндов, заменить И на ИЛИ (или ИЛИ на И) и инвертировать конечный результат. В случае с нашим условием.

 

(age > 17 && height >= 180) && (gender == 'M' || gender == 'm')

 

Рассмотрим сначала кусок

 

(age > 17 && height >= 180)

 

Меняем все значения на обратные

 

(!(age > 17) &&!(height >= 180))

 

заменяем оператор && на ||

 

(!(age > 17) ||!(height >= 180))

 

и инвертируем ответ

 

!(!(age > 17) ||!(height >= 180))

 

Как видим, результат тот же. Очевидно, что

 

!(age > 17)

 

эквивалентно

 

age <= 17

 

Таким образом, изменим условие

 

!(age <= 17 || height < 180)

 

Поменяем таким же образом вторую скобку

 

(gender == 'M' || gender == 'm')

 

на

 

!(gender!= 'M' && gender!= 'm')

 

получим

 

!(age <= 17 || height < 180) &&!(gender!= 'M' && gender!= 'm')

 

Теперь можно применить это же правило и для всего выражения

 

!((age <= 17 || height < 180) || (gender!= 'M' && gender!= 'm'))

 



Поделиться:


Последнее изменение этой страницы: 2017-01-20; просмотров: 394; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.118.0.240 (0.242 с.)