×
Вы действительно хотите открыть доступ к тестированию по курсу C# 5.0 Стартовый на 40 дней?
ВИДЕОУРОК №4. Условные конструкции в C#
Здравствуйте! Тема сегодняшнего урока: «Условные конструкции». Н этом уроке мы рассмотрим операторы языка C#, операторы ветвления, которые будут использоваться для построения условных конструкций. Давайте перейдем к первому слайду и посмотрим что же это такое – условная конструкция вообще, как в естественном языке, так и в языке программирования. Обратите внимание, мы на этом слайде видим зелеными три слова: Если, То, Иначе. Кому-то эта запись напомнит РАЮ – Русский Алгоритмический язык академика Ершова, который мы раньше изучали в школе. Сейчас его в школе не изучают. Но он очень удобный именно для описания алгоритмов, в том числе и условных конструкций, то есть операторов ветвления. Как у нас бывает в жизни? Самый известный пример условной конструкции – это сказка. Едет Илья Муромец И вот он стоит на распутье. Пойдешь налево – смерть свою найдешь. Пойдешь направо – любовь найдешь. Пойдешь прямо – коня потеряешь. И вот он стал и думает по какому пути ему пойти. Какие еще бывают условия уже более приближенные к программированию. Если пользователь нажал такую-то клавишу, то выполняем первую серию инструкций, иначе выполняем другую серию инструкций. Вот этот блок можно настроить таким образом, чтобы узнать нажал ли пользователь клавишу А на клавиатуре, либо какую-то другую. У нас в языке C# имеется всего лишь три разновидности условных конструкций. Первая – это оператор if else, далее тернарный оператор и оператор многозначного выбора swich case. If else – самый сложный, потом тернарный, а самая простая – это конструкция swich case. Но мы с вами начнем разбирать с самого тяжёлого, чтобы нам потом было легче. Главное запомнить, что у нас имеется только три разновидности условных конструкций в языке C#. Давайте посмотрим на следующий слайд и посмотрим как работают условные конструкции. Дело в том что формальных представлений алгоритма очень много. Это идут диаграммы Бэкуса-Наура, Насси-Шнейдермана, различные гостовские блок-схемы. Тот же Русский Алгоритмический язык. Но это все лишь формализм представления алгоритмов. Вот здесь мы будем использовать простейшие раскрашенные блок-схемы. Представьте, что вот идет работа процессора и процессор останавливается перед условием. Интересно, где вот этот ромбик у нас. Давайте посмотрим, мы здесь создаем две целочисленные переменные а и b. а присваиваем значение 1, b присваиваем значение 2. И далее мы создаем условную конструкцию if. Обратите внимание, условная конструкция if состоит их трех частей. Первая – это ключевое слово if, которое говорит о типе этой конструкции. Что это за конструкция? Мы говорим, что это условие – распутье. Далее сразу же идет бок условия в круглых скобках. То есть сначала идет ключевое слово if, которое определяет тип условной конструкции, далее после него сразу в круглых скобках находится выражение. В условной конструкции if мы указываем выражение а меньше b. Если условие удовлетворяет истинности, то есть это действительно так, а условие может и удовлетворять истинности и не удовлетворять. Все остальное – это просторечье. Значит в условной конструкции if мы указываем выражение а меньше b. Если условие удовлетворяет истинности то мы входим в тело условной конструкции, которое представлено операторными скобками. Значит условная конструкция состоит их трех частей: ключевое слово if, определяющее тип конструкции, далее после него сразу же идет блок условия и тело условной конструкции. Мы в тело можем попасть только если выражение в условии будет удовлетворять истинности. Значит смотрим на той же блок-схеме. Мы идём на условие, если оно удовлетворяет истинности, мы возвращаем true и попадаем на серию команд. То есть серия команд – это и есть тело условной конструкции. Если же тело не удовлетворяет истинности, мы обходим тело и идем дальше по программе. Обратите внимание, условие не удовлетворяет истинности – значит в результате выполнения вот этой операции сравнения, которая возвращает либо true либо false. Если условие не удовлетворяет истинности то этот оператор меньше возвращает false и соответственно if нас не пустит в это тело. Давайте мы сейчас посмотрим как это выглядит в программном коде.
1: using System; 2: 3: // Условная конструкция - if (с одной ветвью). 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: int a = 1, b = 2; // создаем две целочисленные переменные 12: 13: // На 15-й строке создаем условную конструкцию if, в условии которой проверяем: a меньше b 14: 15: if (a < b) // Если условие удовлетворяет истинности, выполняем тело условной конструкции. 16: { 17: Console.WriteLine("a < b"); // Ветвь 1 18: } 19: 20: // Delay. 21: Console.ReadKey(); 22: } 23: } 24: }
Мы заходим в первый пример и смотрим. На 11 строке мы создаем две целочисленные переменные а и b и присваиваем им значения 1 и 2. На 15 строке мы с вами создаем условную конструкцию if в условие которой указываем выражение a < b. Если условие удовлетворяет истинности то мы входим в тело условной конструкции и выполняем ту серию команд, которая там находится. Если условие не удовлетворяет истинности то мы сразу же переходим дальше не заходя в тело цикла. Давайте попробуем посмотреть на работу этой программы. Попробуем ее пошагать через F11. Давайте посмотрим чему равна переменная а = 1, b = 2, наведем на оператор меньше. Смотрите что он нам выдает. Справа от сравнения true. Заходим и выводим на экран. Если мы посмотрим сейчас на консоль, то увидим, что у нас тело условной конструкции отработало. Давайте попробуем теперь не пустить. Поменять знак? Нет! Никогда так не делайте. Смотрите, возможно этот код писал другой программист. У нас есть переменные. Мы можем работать только с переменными. Не меняйте чужие программные коды. Для того, чтобы условие не удовлетворяло истинности нам нужно изменить переменные, например, переменной а присвоить 10. Давайте попробуем сейчас пройтись. F11. А равна 10, b равна 2. И оператор меньше возвращает нам false. Вы видите, мы не вошли в тело условной конструкции и не выполнили определенную серию команд, потому что условие не удовлетворяет истинности. Давайте вернемся в нашу презентацию и посмотри еще какие есть варианты использования конструкции if. Смотрим, конструкция if – else.Мы создаем две целочисленные переменные а и b и присваиваем им значения 1 и 2. И обратите внимание, теперь мы создаем условную конструкцию if – else. Else идет сру же после блока if. Если условие удовлетворяет истинности то мы выполняем первую серию команд. Если же условие не удовлетворяет истинности мы выполняем серию команд обозначенную в блоке else. Блок else не обязателен, это просто альтернативная ветвь. И теперь в этой конструкции у нас имеется две ветви: Ветвь1 и Ветвь2. Давайте посмотрим на диаграмме. Значит здесь у нас идет условие, если условие удовлетворяет истинности, то мы выполняем первую серию команд. Если условие не удовлетворяет истинности мы выполняем вторую серию команд. В данном случае мы выполним тело блоке else. Давайте посмотрим как это выглядит в программном коде.
1: using System; 2: 3: // Условная конструкция - if - else (с двумя ветвями). 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: int a = 3, b = 2; 12: 13: if (a < b) // Если условие удовлетворяет истинности, выполняем тело блока if. 14: { 15: Console.WriteLine("a < b"); // Ветвь 1 16: } 17: else // Иначе, выполняем тело блока else. 18: { 19: Console.WriteLine("a не меньше b"); // Ветвь 2 20: } 21: 22: // Delay. 23: Console.ReadKey(); 24: } 25: } 26: }
На 11 строке мы создаем две целочисленные переменные а и b и присваиваем им значения 1 и 2. На 13 строке мы создаем условную конструкцию if в условии которой указываем выражение a < b. И мы понимаем, что если здесь условие будет удовлетворять истинности то мы выполним вот эту серию команд, если условие не будет удовлетворять истинности то мы выполним блок else. Давайте пошагаем F11. А равно 1, b равно 2. Ага, a < b = true. Выполняем первую серию команд и дальше мы перепрыгнули через тело конструкции else. Мы ее не выполнили. То есть понятно, что при выполнении этой программы. Может выполнится только одна ветвь, либо первая, либо вторая. Невозможно сделать так, чтобы выполнились две ветви, только лишь одна ветвь. И смотрим на вывод в консоли. Действительно a < b. Видим что у нас сработала первая ветвь, то есть мы вошли в тело блока if. А теперь давайте попробуем не пустить в блок if а зайти блок else. Для этого нужно изменить значение переменной. Теперь а присваиваем 10. Шагаем, F11. Наводим на знак меньше. Нам возвращает false. И вот мы зашли в блок else. И пошли по второй ветви, выполнили вот эту серию команд, которая должна была быть в этом блоке. И теперь мы видим: а не меньше b. Давайте пойдем дальше, посмотрим. Заходим в третий пример.
1: using System; 2: 3: // Условная конструкция - if-else (с двумя ветвями). 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: int a = 1, b = 2; 12: 13: // Если тело блока if или else состоит из одного выражения, то операторные скобки можно опустить 14: 15: if (a < b) 16: Console.WriteLine("a < b"); // Ветвь 1 17: else 18: Console.WriteLine("a не меньше b"); // Ветвь 2 19: 20: // Delay. 21: Console.ReadKey(); 22: } 23: } 24: }
На 11 строке мы создаем две целочисленные переменные а и b и присваиваем им значения 1 и 2. На 15 строке мы создаем условную конструкцию if – else. Но что мы видим? Здесь нет операторных скобок. Правило следующее, если у вас ветвь состоит только их одного оператора языка C#. Мы помним, что любой оператор языка заканчивается точкой с запятой. Мы уже с вами рисовали пустые операторы. То тогда мы можем упустить операторные скобки. Но code convention многих компаний говорят о том, что так поступать не следует. Почему? Потому что легко допустить ошибку. Представьте себе, что я забыл это и решил дописать в одну с ветвей несколько строк кода. Решил вывести еще восклицательные знаки, чтобы подтвердить, что а действительно меньше b. Я сейчас думаю, что вот эти два оператора входят в блок else. На 15 строке условие удовлетворяет истинности. Шагаем. А меньше b – это true. И я выполняю кусок другой ветки, хотя моя голова думала, что вот этот оператор относится к блоку else и не должен быт выполнен. И вот такие мелочи, встречающиеся в коде могут приводить к логическим ошибкам и в итоге мы будем долго сидеть, отлаживать, шагать нашу программу, находить эти ошибки. Это значит, что мы будем тратить наше дорогое время. Поэтому многие code convention компаний говорят, что так не надо делать, хоть так и код кажется чище и проще, но все-таки ставьте операторные скобки. Мы с вами знаем, что так сделать возможно. И по сути, так как у нас учебные примеры, то мы можем себе это позволить. Иногда у нас будут встречаться вот такие конструкции. Хорошо. А мы идем дальше.
1: using System; 2: 3: // Условная конструкция - if-else (с несколькими ветвями). Каскад условных операторов. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: int a = 1, b = 2; 12: 13: if (a < b) // каскад условных операторов 14: { 15: Console.WriteLine("a < b"); // Ветвь 1 16: } 17: else if (a > b) // идем на новую проверку 18: { 19: Console.WriteLine("a > b"); // Ветвь 2 20: } 21: else 22: { 23: Console.WriteLine("a == b"); // Ветвь 3 24: } 25: 26: // Delay. 27: Console.ReadKey(); 28: } 29: } 30: }
Тоже интересная конструкция. Это разновидность конструкции if – else, а точнее каскад условных операторов if. На 11 строке мы создаем две целочисленные переменные а и b и присваиваем им значения 1 и 2. На 13 строке мы создаем условную конструкцию if в условии которой указываем выражение a < b. Если условие удовлетворяет истинности, то мы входим в тело условной конструкции и выполняем ветвь1. Если же условие не удовлетворяет истинности, смотрите, что у нас происходит. На 17 строке сразу после else у нас пристроилась еще одна условная конструкция. Получается, что если не это, то возможно второе условие сработает. А если и оно не сработает, то только тогда мы пойдем в третью ветвь. Такая конструкция называется каскадом условных операторов. Еще раз, на 13 строке мы создаем условную конструкцию if – else – if – else, в первом условии которой мы указываем a < b. Если условие удовлетворяет истинности мы идем в тело условной конструкции if и выполняем его, если условие не удовлетворяет истинности, то мы идем на другое условие на 17 строку и проверяем, если условие удовлетворяет истинности здесь, то мы выполняем вот этот блок, вторую ветвь. Если и здесь условие не удовлетворяет истинности, тогда мы в идем в блок else и выполняем третью ветвь. Еще раз, каскад условных оператором. В некоторых языках есть даже такое ключевое слово elseif. У нас такого нет. Нем приходится его составлять, но это тоже по-своему интересно. Давайте теперь пошагаем вот это программу. Давайте посмотрим. Переменной а присваиваем ей значение 1. Переменной b присваиваем значение 2. Идем на первое условие – оно true. Значит мы зайдем в первую ветвь и выполним серию операторов. Смотрите, мы перепрыгнули через все остальные ветви. Останавливаем нашу программу. И как мне зайти во вторую ветвь. Вот хочу пойти прямо. Ни налево, ни направо – прямо. Нужно поменять значение переменной а = 10. F11. Проинициализировали переменные. Первая проверка. Смотрите, оператор меньше возвращает false, оператор больше возвращает true и пускает нас в тело условной конструкции и мы его выполняем, а затем выходим за ее пределы. А теперь нужно зайти в блок else. Нужно 10 заменить на 2. Давайте попробуем. Шагаем, F11. Проверяем первое условие – false, второе – false. В итоге, если не меньше и не больше, то они равны. И вот мы выполняем вот этот блок. Мы прошли по третей ветви. Думаю, что здесь достаточно понятно. Теперь рассмотрим маленький пример использования условных конструкций. Представьте себе, что это у нас идет небольшая система аутентификации.
1: using System; 2: 3: namespace Authentication 4: { 5: class Program 6: { 7: static void Main() 8: { 9: string login = "Admin"; 10: string password = "P@ssw0rd"; 11: 12: Console.Write("Введите login: "); 13: 14: // На 17 строке создаем строкову локальную переменную с именем usersLogin 15: // и принимаем в нее ввод от пользователя 16: 17: string usersLogin = Console.ReadLine(); 18: 19: if (login == usersLogin) 20: { 21: Console.Write("Введите password: "); 22: string usersPassword = Console.ReadLine(); 23: 24: if (password == usersPassword) 25: { 26: Console.WriteLine("Здравствуйте {0}, Вы вошли в систему.", usersLogin); 27: } 28: else 29: { 30: Console.WriteLine("Вы ввели неверный пароль."); 31: } 32: } 33: else 34: { 35: Console.WriteLine("Нет пользователя с таким именем."); 36: } 37: 38: // Delay. 39: Console.ReadKey(); 40: } 41: } 42: }
На 9 строке мы создаем строковую переменную login, на 10 строке мы создаем строковую переменную password. И вот они хранят в себе такие постоянные значения. На 12 строке мы предлагаем пользователю ввести свой логин. На 17 строке мы переменной userLogin присваиваем значение введенное пользователем. Мы здесь вызываем метод ReadLine. Далее на 19 строке в условной конструкции if мы проверяем действительно ли логин, тот что ввел пользователь совпадает с тем, что у нас хранится в переменной login. Если условие удовлетворяет истинности, то мы входим в тело условной конструкции и снова же сразу предлагаем пользователю ввести пароль. На 22 строке мы создаем переменную userPassword типа string и присваиваем ей возвращаемое значение метода ReadLine, которое представляет собой строку – пароль, который ввел пользователь. Далее мы проверяем если, хранящийся у нас в базе данных пароль, совпадает с тем что ввел пользователь, то мы выводим ему приветствие. Иначе говорим, что был введен неверный пароль. А если здесь я введу логин отличный от Admin, то мне скажут, что нет пользователя с таким именем в системе. Давайте пошагаем, чтобы проверить действительно она правильно работает. F11. Инициализация переменных. Предлагаем пользователю ввести… Смотрите, переменная userLogin пока равна null – об этом значении мы позже поговорим, это – ничего. Активизировалась консоль. Давайте я введу свое имя – Alex. Login = Admin, userLogin = Alex. Смотрите меня бросило в блок else. Меня не пустило в систему. F11. Нет пользователя с таким именем. Давайте попробуем еще раз. Инициализация переменных, предлагаем пользователю ввести логин, пишем Admin. Смотрим, пустило. Теперь мы предлагаем пользователю ввести пароль, смотрим. Пароль… Какой у нас тут пароль? Я возьму и введу драгой пароль. Вот видите, пароли не совпали и системы выводи – вы ввели неверный пароль. Хорошо, давайте попробуем правильно пройти эту программу. F11. Инициализация, предлагаем ввод, вводим Admin. Дальше. Введите пароль. Так, вводим правильный пароль. Пустит? Пускает. Здравствуйте Admin, вы вошли в систему. Выполняемся и выходим. Вот такой простейший пример. Этот пример показывает, что условные конструкции могут использоваться не только в таком контексте. Смотрите, что мы здесь видим. Мы еще видим, что условные конструкции могут быть вложены в другие условные конструкции. Одна конструкция вложена в другую конструкцию. Такое допустимо. Ну и здесь мы можем вкладывать еще условные конструкции, можем делать каскадом эти конструкции. Мы с вами сейчас разобрали только лишь первую условную конструкцию, это условный оператор if – else. Мы уже понимаем, что if может использоваться самостоятельно либо с блоком else, который образует вторую ветвь, либо мы можем сделать каскад условных операторов. И также мы видели, что мы можем условные конструкции вкладывать внутрь других условных конструкций организуя более гибкую логику. А мы переходим дальше.
И следующая условная конструкция - это тернарный, или третичный, или троичный оператор. Обратите внимание, как она обозначается ?:. Давайте посмотрим на диаграмму. Если условие удовлетворяет истинности мы выполняем одну серию команд. Иначе, мы выполняем другую серию команд. Смотрим в код. Мы создаем три целочисленные переменные a, b, c и присваиваем значение 1 2 0 соответственно. И обратите внимание, переменной с мы присваиваем значение этой конструкции. Вот эта выделенная конструкция и называется тернарным оператором. Она нам что-то должна вернуть. Из чего же она состоит? Она состоит из трех частей. Первая часть – это блок условия. Мы даже здесь не используем ключевое слово if. Смотрите, какая она простая. Получается если условие а больше b, удовлетворяет истинности, знак вопроса можно заменить словом ТО. То мы переменной с присваиваем значение переменной а. Если условие удовлетворяет истинности то мы переменной с присваиваем значение переменной а, которая стоит после знака вопроса. Двоеточие можно заменить словом ИНАЧЕ. Иначе мы переменной с присваиваем значение переменной b. Еще раз, мы переменной присваиваем возвращаемое значение тернарного оператора, в условии которого указываем выражение а больше b. Если условие удовлетворяет истинности, то мы переменный с присваиваем значение переменной а. Иначе если условие не удовлетворяет истинности, то мы переменной с присваиваем значение переменной b, то есть 2. Думайте, что мы увидим здесь на экране после вывода. Обратите внимание, тернарный оператор обязательно должен возвращать значение, иначе будет ошибка. Тернарный оператор обязательно должен вернуть либо одно значение, либо другое значение. Давайте теперь зайдем в код и посмотрим на работу тернарного оператора. Заходим в 6 пример.
1: using System; 2: 3: // Тернарная условная операция. 4: 5: // Тернарный (троичный) оператор [?:] . 6: // Тернарный оператор [?:], является сокращенной формой конструкции if ... else. 7: // [?:] - включает в себя три операнда - ( условие ? Если условие ИСТИННО : Если условие ЛОЖНО ) 8: 9: // Алгоритм работы тернарной операции: (логическое выражение) ? выражение 1 : выражение 2 10: // 1. Вычисляется логическое выражение (условие). 11: // 2. Если логическое выражение истинно, то вычисляется значение выражения выражение 1, в противном случае — значение выражения выражение 2. 12: // 3. Вычисленное значение возвращается. 13: 14: namespace Condition 15: { 16: class Program 17: { 18: static void Main() 19: { 20: int a = 1, b = 2, max = 0; 21: 22: // Переменной max, присваиваем возвращаемое значение тернарного оператора. 23: 24: max = (a > b) ? a : b; // ЕСЛИ: (a > b) ТО: вернуть a ИНАЧЕ: вернуть b; 25: 26: Console.WriteLine(max); 27: 28: // Delay. 29: Console.ReadKey(); 30: } 31: } 32: }
На 20 строке мы создаем три целочисленные переменные a, b, max и присваиваем им значения 1, 2, 0. И на 24 строке мы переменной max присваиваем возвращаемое значение тернарного оператора в условии которого указывается выражение a > b. Если условие удовлетворяет истинности, то переменной max присваиваем значение переменной а, то есть 1. Max будет равна 1. Если же условие не удовлетворяет истинности, то мы переменной max присваиваем значение переменной b. Еще раз, на 24 строке мы переменной max присваиваем возвращаемое значение тернарного оператора в условии которого указывается выражение a > b. Если условие удовлетворяет истинности, то переменной max присваиваем значение переменной а. Если же условие не удовлетворяет истинности, то мы переменной max присваиваем значение переменной b. Это еще проще чем условные конструкции if – else. Заметьте, здесь нет ничего лишнего. И на 26 строке что мы выведем? Давайте попробуем пошагать эту программу. Увидим, как шагается тернарный оператор. Теперь смотрим, а больше b = false. Значит сейчас переменной max, которая сейчас равна 0, значение переменной b. В результате 2. А как теперь мне присвоить значение переменной а. Изменить b на 0. Хорошо, давайте попробуем так. Смотрим, ага, a > b = true. И теперь переменная max равна 1. То есть мы переменной max присваиваем значение переменной b. Видите, я навожу на красный квадратик, а там подсказка – stop debugging (Shift+F5). Отменяем все изменения, чтобы не портить программные коды, хотя вы всегда можете скачать их с сайта видео уроков. Хорошо. Давайте посмотрим следующий пример тернарного оператора.
1: using System; 2: 3: // Тернарная условная операция. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: int a = 1, b = 2, c = -5, max = 0; 12: 13: max = a > b ? c = a : c = b; // сначала с = а, а только потом max = c 14: 15: Console.WriteLine(max); 16: Console.WriteLine(c); 17: 18: // Delay. 19: Console.ReadKey(); 20: } 21: } 22: }
На 11 строке мы создаем 4 целочисленных переменных a, b, c, max и присваиваем им значения 1, 2, -5, 0. На 13 строке мы переменной max присваиваем возвращаемое значение тернарного оператора. Обратите внимание, знак вопроса – звучит ТО, двоеточие – звучит ИНАЧЕ. Смотрите, мы здесь даже можем не указывать круглые скобки в условии. На 13 строке мы переменной max присваиваем возвращаемое значение тернарного оператора в условии которого указываем выражение: a > b. Если условие удовлетворяет истинности, то мы входим в блок, который находится между знаком вопроса и двоеточием и переменной с присваиваем значение переменной а. Мы -5 заменяем на 1. С будет равна 1 и мы переменной max присваиваем значение переменной с. Заметьте, сначала переменной с присваиваем значение из а, а потом в max из с. Видите, 1 попала в с, а потом сразу же в max. Если же условие не удовлетворяет истинности мы идем в блок ИНАЧЕ. И переменной с присваиваем значение из переменной b, и только тогда переменной max присваиваем значение из с. Еще раз. Мы на 13 строке переменной max присваиваем возвращаемое значение тернарного оператора в условии которого указываем выражение a > b. Если условие удовлетворяет истинности тогда мы идем в блок ТО и переменной с присваиваем значение из переменной а, и только потом переменной max, присваиваем значение переменной с. Иначе, если условие не удовлетворяет истинности то мы идем в блок ИНАЧЕ. И переменной с присваиваем значение переменной b, и только потом переменной max присваиваем значение переменной с. Интересно, что же здесь у нас получится, что же здесь у нас будет. Давайте пошагаем. Так, прошла инициализация. Давайте угадывать. Я думаю что переменная max будет равна 0. Нет.. -5? Нет? Давайте смотреть. А = 1, b = 2. А больше b = false. Идем в блок ИНАЧЕ. Переменной с присваиваем значение переменной b. C равна уже двум. Если раньше она была -5, то теперь она равна 2. Получается, что если мы здесь, то скорее всего вот это значение присвоится max. C равно 2. Max равен 2. А как мне сделать так, чтобы у меня сработал первый блок. Нужно а присвоить значение 10. Смотрим F11. Проинициализировали переменные. А = 10, это больше двух. Переменная с равна 10. Потому что мы зашли в первый блок. Переменной с, которая была -5, переприсвоили 10 из переменной а. А дальше, когда с стала 10, мы ее переприсвоили в max. Идем в следующий пример.
1: using System; 2: 3: // Тернарная условная операция. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: string @string = "Hello "; 12: 13: Console.WriteLine("Введите свой логин:"); 14: 15: // На 17 строке создаем переменную с именем login типа string и принимаем в нее ввод от пользователя 16: 17: string login = Console.ReadLine(); 18: 19: // На 21 строке переменной @string присваиваем возвращаемое значение тернарного оператора 20: 21: @string += login == "Admin" ? "Administrator" : "User"; 22: 23: Console.WriteLine(@string); 24: 25: // Delay. 26: Console.ReadKey(); 27: } 28: } 29: }
А это небольшой пример, тоже такой игровой, использования тернарного оператора. Давайте посмотрим, на 11 строке мы создаем строковую переменную @string. Помните мы говорили, что так не нужно делать. Но нам же нужно вспомнить что нам встречался этот символ, потому что мы могли его уже забыть к этому уроку. На 11 строке мы создаем строковую переменную @string и присваиваем ей значение «Hello ». На 13 строке мы предлагаем пользователю ввести свой логин. На 17 строке мы создаем строковую переменную login и присваиваем ей возвращаемое значение функции ReadLine, которая и будет принимать ввод от пользователя. На 21 строке мы переменной @string… А что же это за значок? += Ага, это конкатенация – сцепление строк. На 21 строке переменной @string присваиваем с конкатенацией возвращаемое значение тернарного оператора. А что это означает, присвоить с конкатенацией возвращаемое значение тернарного оператора? Тернарный оператор видимо возвращает строку, либо Administrator либо User. Ага, в @string уже имеется «Hello ». Это значит, что к этому слову добавятся либо Administrator, либо User, в зависимости от того, что введет пользователь. Значит смотрим. На 21 строке переменной @string присваиваем с конкатенацией возвращаемое значение тернарного оператора в условии которого указываем выражение login == "Admin". Если условие удовлетворяет истинности, то мы возвращаем “Administrator”. Получается, что @string в себе будет содержать «Hello Administrator» Они сцепятся и будут вместе. А если мы введем что-то отличное от cлова Admin то в переменную @string присвоится с конкатенацией слово “User”. То есть здесь будет “Hello User”. И на 23 строке мы выведем результат на экран. Давайте пошагаем, посмотрим как это. Так, тут мне предлагается что-то ввести. Введу “Admin”. Нажимаем Enter. Смотрите, Hello Administrator. Конкатенация. Сцепилось предыдущее значение, которое хранилось в @string и то что вернул тернарный оператор. Давайте выведем это. Видите? Hello Administrator. А что будет если убрать знак присвоения с конкатенацией и оставить только присвоение. Еще раз выполняемся. F5 Нам выводит “Administrator”. “Hello” затерлась, она исчезла. Почему? Потому что раньше переменная @string была равна “Hello”, теперь в нее попало возвращаемое значение тернарного оператора «Administrator». «Hello» стерлось, а осталось «Administrator». А я хочу, чтобы еще Hello осталось. Тогда возвращаем знак конкатенации. А что будет если мы введем что-то отличное от слова «Admin». Давайте попробуем. Я свое имя сейчас введу. Я ввожу “Alex”. Обратите внимание! «Hello User». Потому что все что отличное от «Admin» не удовлетворяет истинности и мы идем в блок ИНАЧЕ. Смотрите как просто работает тернарный оператор, еще проще чем работает конструкция if – else. Хорошо. А мы переходим к следующему примеру.
1: using System; 2: 3: // Тернарная условная операция. Ограничения связанные с типобезопасностью. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: int a = 1; 12: double b = 0.0; 13: int max; 14: 15: // Выражения [?] и [:] - должны быть одного типа. 16: 17: max = (int)((a > b) ? a : b); 18: 19: // ... или так 20: 21: max = (a > b) ? a : (int)b; 22: 23: Console.WriteLine(max); 24: 25: // Delay. 26: Console.ReadKey(); 27: } 28: } 29: }
Вопросы связанные с типобезопасностью. Обратите внимание, на 11 строке мы создаем переменную типа int и присваиваем ей значение 1. На 12 строке мы создаем переменную b типа double и присваиваем ей значение 0. На 13 строке мы создаем переменную max. И на 17 строке м переменной max присваиваем возвращаемое значение тернарного оператора, в условии которого a > b. Если условие удовлетворяет истинности, то мы переменной max присваиваем значение переменной а. Безопасно? Безопасно. Int приводится к int. Как это называется? Кастинг. А если условие не удовлетворяет истинности то в переменную max нам нужно присвоить значение double переменной b. В чем опасность? Потеря точности, то есть обрезание хвоста у дробного числа. Поэтому если мы не будем использовать вот эту подпись программиста, оператор явного преобразования значения типа. Давайте его уберем. Ошибка. Cannot implicity convert double to int. Смотрите, если а нормально конвертируется, то b не конвертируется. Поэтому давайте мы вернемся и посмотрим. Правило следующее. Если у нас разные блоки тернарного оператора, блок истинности и блок ложности содержат разнотипные переменные, и при чем возвращаемое значение тернарного оператора будет опасно конвертироваться, то нам нужно перед тернарным оператором указать оператор явного преобразования значения типа. А вот второй способ. То же самое, просто другой способ. Потому что не оптимально. Мы пытаемся а типа int преобразовать в int, это не красиво. На 21 строке мы переменной max присваиваем возвращаемое значение тернарного оператора в условии которого указано выражение a > b. Если условие удовлетворяет истинности, то мы переменной max присваиваем значение переменной а без кастинга, иначе, если условие не удовлетворяет истинности, то мы переменной max присваиваем значение переменной b предварительно преобразовывая значение. Идет преобразование к типу int. То есть мы здесь понимаем, что происходит отрезание дробной части числа, потеря точности числа, потому что дробная часть и определяет точность вещественного числа. Смотрите, как просто. Следующий пример.
1: using System; 2: 3: // Тернарная условная операция. Вложенные тернарные операторы. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: // Определение квадранта в котором лежит заданная точка. 12: // Для упрощения примера условимся, что точка не будет лежать в центре координат и на координатных осях, 13: // это значит, что x и y - не могут быть равны 0. 14: 15: int x = 10, y = -5; 16: 17: 18: // Не рекомендуется вкладывать тернарные операторы, так как это ухудшает чтение кода. 19: 20: 21: string quadrant = (x > 0) ? ((y > 0) ? "I квадрант" : "IV квадрант") : ((y > 0) ? "II квадрант" : "III квадрант"); 22: 23: // ... или так 24: 25: quadrant = x > 0 ? (y > 0 ? "I квадрант" : "IV квадрант") : (y > 0 ? "II квадрант" : "III квадрант"); 26: 27: // ... или вообще, вот так 28: 29: quadrant = x > 0 ? y > 0 ? "I квадрант" : "IV квадрант" : y > 0 ? "II квадрант" : "III квадрант"; 30: 31: 32: Console.WriteLine(quadrant); 33: 34: // Delay. 35: Console.ReadKey(); 36: } 37: } 38: }
На 15 строке мы создаем две переменных х и у типа int и присваиваем им значение 10 и -5. Представляете себе систему координат, такой перекресток. Помните, как против часовой считают первую четверть, вторую, третью, четвертую. У нас четверь называется четвертью, а у иностранцев она называется квадрант. И вот теперь мы здесь хотим посмотреть, когда мы здесь задаем какие-то координаты х и у, то мы хотим узнать в каком квадранте или четверти находится эта точка. В каком квадранте находится эта точка. Давайте посмотрим, на 21 строке создаем переменную quadrant типа string и присваиваем ей значение этого тернарного оператора. Мы сейчас разберемся. Обратите внимание, тернарный оператор содержит в себе еще несколько тернарных операторов. Помните, как мы if – else вкладывали в if – else. А здесь мы тернарные операторы вкладываем в тернарные операторы. Смотрим. Вот он наш внешний тернарный оператор. Вот его условие - (x > 0). Если условие удовлетворяет истинности, то выполняется вот этот блок - ((y > 0) ? "I квадрант" : "IV квадрант") А вот смотрите второй тернарный оператор, вложенный в блок ложности - ((y > 0) ? "II квадрант" : "III квадрант") Давайте посмотрим, если х больше 0, то мы переходим в первый блок, а здесь мы проверяем у больше 0? Если у больше 0 мы идем в первый блок вложенного тернарного оператора. Вот он вложенный тернарный оператор, вот его условие идет, вот его блок истинности и блок ложности. Х больше 0? Больше! А у больше 0? Нет! Значит мы возвращаем строку «IV квадрант». Если вы забыли, как выглядит система координат с абсциссой и ординатой, посмотрите, мы это изучали во втором классе. Смотрим дальше. Вот эта система с вложенными тернарными операторами будет определять положение точки в двумерном пространстве координат. Поиграйтесь с этим. Положите перед собой листик с системой координат, если забыли, и попробуйте. Здесь суть даже не в самом примере, здесь суть в удобстве чтения. Обратите внимание, программист, который не знаком с этим кодом. Да он знает, что такое тернарный оператор. Но ему придется долго сидеть и вникать в эту логику вложенности. Вам проще, потому что я подсказал. Поэтому вот такие сложные конструкции использовать не рекомендуется. Они ничего не говорят. Они не очевидные. Они не понятные. Но самое главное, такие конструкции требуют к себе большого внимания, времени на их разбор. Представляете, чтобы вникнуть в нее вам нужно несколько минут. Это не совсем красивая и удобная конструкция, с учетом того что программные коды мы пишет так, чтобы они в первую очередь легко читались другими программистами. Вот этот стиль, он не очень красивый. Давайте посмотрим альтернативные варианты. Та же самая строка, тот же самый пример и то же самое условие, только игра со скобками. Смотрим, на 25 строке мы переменной quadrant присваиваем возвращаемое значение тернарного оператора в условии которого указано выражение - (x>0). Идем в блок истинности, проверяем у больше 0? Нет! И значит, если здесь условие не удовлетворяет истинности мы идем в блок ИНАЧЕ, и переменной quadrant присваиваем значение «IV квадрант» Ага тут уже более менее проще читается. А давайте посмотрим 29 строку. Та же запись, только вообще без скобок. Смотрите на 29 строке мы переменной quadrant присваиваем возвращаемое значение тернарного оператора в условии которого указываем - (x > 0). Если условие удовлетворяет истинности, идем в блок истинности, попадаем на условие второго вложенного тернарного оператора, проверяем условие у больше 0. Оно ложно. Идем в блок ложности вложенного тернарного оператора и переменной quadrant присваиваем строковое значение «IV квадрант». Смотрите как просто. Но это дело вкуса. Конечно же, старайтесь писать коды так, чтобы другим программистам их было легче читать. Эти коды остаточно витиеваты. Они не очевидны. Вроде бы тернарный оператор, он самый простой оператор, но можно так накомбинировать тернарных операторов, что они просто будут сложночитаемыми неподготовленому программисту. Мы переходим к следующему примеру.
1: using System; 2: 3: // Тернарная условная операция. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: double quantity = 10; // Количество единиц товара. 12: double price = 100; // Цена за единицу товара. 13: double discount = 0.75; // Скидка на общую стоимость - 25%. 14: double cost; // Общая стоимость. 15: 16: // ЕСЛИ: Купили 10 единиц товара и больше. ТО: предоставить скидку в 25%. ИНАЧЕ: Скидку не предоставлять. 17: 18: cost = quantity >= 10 ? quantity * price * discount : quantity * price; 19: 20: Console.WriteLine("Общая стоимость товара составляет: {0} у.е.", cost); 21: 22: // Delay. 23: Console.ReadKey(); 24: } 25: } 26: }
Ага, у нас здесь идет маленький интересный пример. На 11 строке мы создаем переменную типа double – quantity - количество товаров 10. На 12 строке price = 100. Цена за единицу товара. На 131 строке мы даем скидку 25%. Мы помним, что чтобы сделать скидку мы можем указать только коэффициент 0,75, чтобы нам не делить на 100 и не умножать на 25 можно просто умножить на 0,75. И на 14 строке мы создаем переменную cost – общая стоимость. И теперь смотрим правило. Если в нашем магазине купили 10 или больше книг, то клиенту предоставить скидку 25%. А иначе, если клиент купил 9 книг, скидку не предоставлять. И смотрим, на 18 строке мы переменной cost присваиваем возвращаемое значение тернарного оператора, в условии которого указываем бизнес правило – количество купленных единиц товара должно быть либо больше, либо равно 10. И если условие удовлетворяет истинности, то мы входи куда? В блок истинности. Мы берем quantity – количество, умножаем на price. 10 книжек на 100 гривен и применяем к нему discount – скидку, умножаем на 0,75. И получается 10*100*0,75=750. Но если же я пришел в магазин и купил 5 книг. Если я купил 5 книг, то в итоге 5 больше либо равно 10? Нет, поэтому мы идем в блок ИНАЧЕ и берем quantity – 5 множим на price -100 и в итоге общая стоимость товара для меня составит 500 у. е. Смотрите, насколько удобная и простая конструкция, условная конструкция тернарный оператор. Правда намного проще условных конструкций if – else и их каскадов. Хорошо, а мы идем дальше.
Мы с вами переходим к последней условной конструкции, которая имеется в языке C#, это конструкция swich – case. Давайте посмотрим, как она выглядит. Эту конструкцию еще называют оператором многозначного выбора или просто переключателем. Мы создаем строковую переменную number и присваиваем значение «1». Далее мы создаем конструкцию swich. Смотрите, условие, но это условие мы будем называть выражением селектора. От слова select – выбор. Еще раз. Создаем строковую переменную number и присваиваем значение «1». Создаем конструкцию swich и в качестве выражения селектора передаем значение переменной number. Обратите внимание, конструкция swich состоит из вложенных операторов case – случай. Смотрите, возле case тоже имеются некие значения. Так вот эти значения принято называть постоянными выражениями, потому что они не меняются. Важно понимать, что если значение выражения селектора совпадет с одним из постоянных выражений операторов case? То как раз и выполнится тело того оператора case с каким постоянным выражение совпадет значение выражения селектора. Еще раз. Создаем строковую переменную number и присваиваем значение «1». Это будет нашим выражением селектора. Создаем конструкцию swich и в качестве выражения селектора передаем значение переменной number. И у нас выполнится тело того оператора case, чье постоянное значение совпадет со значением выражения селектора. Смотрим. Вот этот number чему равен? 1. Case – 2. 2 не равно 1. Это тело не выполнится. Значит в случае равенства у нас произойдет выполнение этой серии команд, которая принадлежит первому case. Смотрим, как это выглядит на диаграмме. У нас имеется выражение селектора. Идут case, у каждого case есть свое постоянное выражение. И если выражение селектора совпадает с одним из постоянных выражений операторов case, то выполняется именно то тело оператора case, чье постоянное выражение совпало с выражением селектора. Немножко запутанно, но это наоборот очень просто. Давайте сейчас мы с вами зайдем в программный код и посмотрим как это выглядит.
1: using System; 2: 3: // Оператор многозначного выбора - switch-case (переключатель). 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: // Предлагаем пользователю ввести число. 12: Console.WriteLine("Введите число 1 или 2: "); 13: 14: // Принимаем ввод от пользователя. 15: string number = Console.ReadLine(); 16: 17: 18: // На 21 строке создаем конструкцию многозначного выбора, переключатель - switch, 19: // которому в качестве выражения-селектора, передаем переменную - number. 20: 21: switch (number) // (number) — выражение-селектор. 22: { 23: // В теле переключателя switch-case, на 29 и 35 строках, 24: // создаем два оператора case, c постоянными выражениями равными "1" и "2" соответственно. 25: 26: // Если значение выражения-селектора совпадет с одним из значений постоянных выражений, 27: // то выполняется тело оператора case, постоянное выражение которого, совпало с выражением-селектора. 28: 29: case "1": // "1" — постоянное выражение. 30: { 31: Console.WriteLine("Один"); // Ветвь 1 32: // Выход из переключателя. 33: break; 34: } 35: case "2": 36: { 37: Console.WriteLine("Два"); // Ветвь 2 38: break; 39: } 40: 41: // На 44 строке создаем (необязательный) оператор default, тело которого выполняется в случае, 42: // если значение выражения-селектора не совпадет ни с одним из значений постоянных выражений. 43: 44: default: 45: { 46: Console.WriteLine("Вы ввели значение отличное от 1 и 2."); // Ветвь 3 47: break; 48: } 49: 50: // Если в переключателе отсутствует оператор default, то управление передается за пределы переключателя switch. 51: } 52: 53: // Delay. 54: Console.ReadKey(); 55: } 56: } 57: }
На 12 строке мы предлагаем пользователю ввести число 1 или 2. На 15 строке мы принимаем ввод от пользователя. Обратите внимание, в переменную number типа string мы принимаем ввод от пользователя. На 21 строке мы создаем конструкцию swich, которой в качестве выражения селектора передаем значение number. Далее в теле конструкции swich у нас имеется несколько операторов case. 29 строка – оператор case с постоянным выражением 1. Оператор case с постоянным выражением 2. Важно помнить, что именно тот case выполнится чье постоянное выражение совпадет с значением выражением селектора. Если же значение выражения селектора не совпадает ни с одним их постоянных выражений операторов case, которые имеются в swich, то у нас выполнится необязательный блок default. Если мы его закомментируем ничего страшного не произойдет. Программа будет работать. Этот блок считается необязательным. Он удобный, чтобы все-таки уведомить пользователя, что он ввел отличное значение от предлагаемого. Попробуйте еще. Чтобы скоординировать действия пользователя. Еще раз. На 15 строке мы принимаем ввод от пользователя. На 21 строке мы создаем переключатель swich, которой в качестве выражения селектора передаем значение переменной number. Именно тот case выполнится чье постоянное выражение совпадет с значением выражением селектора. Если же значение выражения селектора не совпадает ни с одним их постоянных выражений операторов case, то у нас выполнится необязательный блок default. Давайте пошагаем эту программу. Мне здесь предлагается ввести число 1 или 2. Что мы введем? Давайте введем 2. Number = 2. Смотрите куда мы попали, мы попали в блок case, чье постоянное выражение равно значению выражения селектора. Здесь важно запомнить нотацию. Swich – пересключатель. Select – выбирать. Помните, селекционеры, те кто выбирают лучшие растения. А есть переключатели. На одну или на две кнопки, которые рядышком переключаются. И вот этими кнопками, например у нас в офмсе идет насколько кнопок, мы можем включить только одну половину выключателя, могу делать некий такой выбор. Селектор – select – мы постоянно выбираем, например, то освещение, которое нам нужно. Swich – переключатель, выражение селектора – выбиратель, case – случаи, в каком случае мы оказываемся, их постоянные выражения и необязательный блок default, который выполнится только в том случае, если значение селектора не совпадет ни с одним из постоянных выражений операторов case. Смотрите как просто. Это самая простая условная конструкция. Никаких сложных проверок, все красиво и очевидно описано. Первый case, второй case, default – если ничего не получилось. Вот видите, как просто. А мы шагаем дальше. Так выводим на экран 2. Break – это оператор, который говорит, что нужно закончить выполнение конструкции swich. И нас сейчас выбрасывает вообще за его пределы. Когда попадается break на вообще выбрасывает из конструкции. Break используется не только с переключателем, а еще и с другими конструкциями, но мы познакомимся с ним еще на последующих уроках. Break – ломать. Все мы взяли и сломали выполнение конструкции переключателя. Мы выполнили свою работу. Хорошо. В итоге на экране мы что увидим – 2. Давайте попробуем еще раз выполнится. Введем что-то такое чтобы попасть в блок default. Я ввожу 33. Смотрим, number = 33. Мы видим? что не совпало, потому что 33 – это теперь выражение селектора. Не совпало ни с одним из постоянных выражений операторов case. И Куда мы перешли? В необязательный блок default. Если его не будет, то мы просто выйдем за пределы swich. Но здесь сейчас система уведомит нас с вами, что вы ввели значение отличное от 1 и 2. И break прерывает работу переключателя swich. Идем дальше. А теперь смотрите. Здесь у нас показан на слайде тот же самый пример, что и на предыдущем, только у нас присутствует блок default. Он не обязателен, он вводится лишь в том случае если этого требует наша логика. Ну если ничего не совпало то уведомить пользователя. Вам же не приятно, когда вы выполняете какие-то действия с программы, а она закрылась и ничего не сказала. И что? Как-то не очевидно. Надо предупредить пользователя, что вы ввели совсем не то, попробуйте еще вернутся и там сделать. Нужно предупреждать и уведомлять пользователя, потому что он выберет альтернативный продукт, которые более лояльно относится к пользователю. Сегодня это важно, потому что конкуренция большая. Среди разработчиков программного обеспечения. А мы возвращаемся обратно в Visual Studio и смотрим следующие примеры.
1: using System; 2: 3: // Оператор многозначного выбора - switch-case (переключатель). 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: Console.WriteLine("Введите номер дня недели: 1-2-3-4-5-6-7: "); 12: 13: string myDay = Console.ReadLine(); 14: 15: // Конвертируем значение строковой переменной myDay в целочисленное значение 16: // и записываем его в переменную с именем day типа int 17: 18: int day = Convert.ToInt32(myDay); 19: 20: switch (day) 21: { 22: case 1: 23: Console.WriteLine("Понедельник."); 24: break; 25: case 2: 26: Console.WriteLine("Вторник."); 27: break; 28: case 3: 29: Console.WriteLine("Среда."); 30: break; 31: case 4: 32: Console.WriteLine("Четверг."); 33: break; 34: case 5: 35: Console.WriteLine("Пятница."); 36: break; 37: case 6: 38: Console.WriteLine("Суббота."); 39: break; 40: case 7: 41: Console.WriteLine("Воскресенье."); 42: break; 43: default: 44: Console.WriteLine("Вы ввели несуществующий день недели."); 45: break; 46: } 47: 48: // Delay. 49: Console.ReadKey(); 50: } 51: } 52: }
На 11 строке мы предлагаем пользователю ввести номер дня недели. На 13 строке мы принимаем ввод от пользователя. Обратите внимание, на 18 строке мы берем и преобразовываем строковое представление в Int. Для этого мы пользуемся конвертером. Еще один объект – конвертер у которого есть функция преобразования. Посмотрите сколько мы знаем объектов: консоль – занимается вводом и выводом, Math – математика, у нас еще есть живой конвертер, который может конвертировать такие сложные форматы. Распознать, что это единица и преобразовать ее в int. Потому что на самом деле вот эта единица представляет собой просто картинку, состоящую из точечек, и мы не можем складывать две картинки, потому что если я возьму на одном листе напишу 1 и на втором тоже, то у нас получится 11. А для того чтобы получить 2 мне нужно глазами посмотреть, это все попадаем в мозг и мое арифметико-логическое устройство определенное нейронными связями уже преобразует картинки в какой-то свой формат складывает их. Так же и у процессора имеется свое АЛУ, которое не может сложить две картинки. Его нужно как-то преобразовать. А мы знаем, что каждая картинка, каждые символ имеет в кодовой таблице свой номер и свою кодировку. Кодировки чисел запомнить очень легко. У нуля – 0х30 и так далее по порядку. И поэтому преобразовать код 0х31 просто в 1 – это очень просто. Просто убрать лидирующую тройку и получится 1. На 18 строке мы обращаемся к конвертеру и говорим, чтобы он преобразовал нам в Int32 строку. Конвертер берет и преобразовывает. И далее это преобразованное значение, которое находится сейчас в day в формате int будет выступать в роли выражения селектора. На 20 строке мы создаем конструкцию swich, которой в качестве выражения селектора передаем значение переменной day. Если значение выражения селектора совпадет с одним из постоянных выражений, то выполнится именно то тело, того оператора case, чье постоянное выражение совпадет со значением выражения селектора. Если я введу какую-то абракадабру, то мне напишет, что вы ввели несуществующий день недели. Смотрите, как корректно обработает программа некорректный ввод. Давайте выполнимся и проверим. Мне предлагается, введите номер дня недели, введем 4 – четверг. И получим правильный результат. Смотрите, просто? Просто! Как красив и как понятно. А представьте если мы то же самое представили условными конструкциями. Это была бы абсолютно нечитаемая куча. А смотрите как красиво и элегантно здесь представлено. Переходим к следующему примеру.
1: using System; 2: 3: // Оператор многозначного выбора - switch-case (переключатель). Проваливание. 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: Console.WriteLine("Введите номер дня недели: 1-2-3-4-5-6-7: "); 12: 13: string day = Console.ReadLine(); 14: 15: switch (day) 16: { 17: // Для пустых операторов case разрешено "проваливание" от одного оператора к другому. 18: case "1": 19: case "2": 20: case "3": 21: case "4": 22: case "5": 23: Console.WriteLine("Этот день недели - Рабочий."); 24: break; 25: case "6": 26: case "7": 27: Console.WriteLine("Этот день недели - Выходной."); 28: break; 29: 30: default: 31: Console.WriteLine("Вы ввели несуществующий день недели."); 32: break; 33: } 34: 35: // Delay. 36: Console.ReadKey(); 37: } 38: } 39: }
Здесь у нас должно быть проваливание. А что значит проваливание? На 11 строке предлагается ввести номер дня недели. Мы принимаем ввод от пользователя. На 15 строке создаем конструкцию – переключатель, который в качестве выражения селектора принимает значение дня недели, введенное пользователем. И теперь мы видим, что если пользователь введет значение от 1 до 5, то у нас выполнится блок с 23 по 24 строку. Если я введу двойку, то у меня сработает case на 19 строке и дальше произойдет проваливание в этот блок. А дальше меня break выкинет из swich. Он не даст мне дальше проваливаться. И выведется, что этот день недели рабочий, если я выберу 6 или 7, то начальные case не сработают, сработает либо шестой, либо седьмой. И выведется, что сегодня день недели выходной. Если я введу, какую-то абрукадабру, или что-то отличное от этих чисел, то у меня сработает необязательный блок default? Который корректно меня уведомит, что я не правильно ввел день недели. Оператор swich с возможностью проваливания. Давайте перейдем в последний пример. В некий аналог игрушечного кофейного аппарата.
1: using System; 2: 3: // Оператор многозначного выбора - switch-case (переключатель). 4: 5: namespace Condition 6: { 7: class Program 8: { 9: static void Main() 10: { 11: // Предлагаем пользователю выбрать напиток. 12: Console.WriteLine("Размеры стаканчиков кофе: 1 = Маленький, 2 = Средний, 3 = Большой"); 13: Console.Write("Пожалуйста, сделайте свой выбор: "); 14: 15: // Принимаем ввод от пользователя. 16: string coffeeSize = Console.ReadLine(); 17: 18: int cost = 0; 19: 20: // Если оператор case имеет в своем теле код, то не поддерживается "проваливание". 21: // Для организации "проваливания" можно использовать оператор безусловного перехода - goto 22: switch (coffeeSize) 23: { 24: case "1": 25: cost += 25; 26: break; 27: case "2": 28: cost += 25; 29: goto case "1"; 30: case "3": 31: cost += 50; 32: goto case "1"; 33: default: 34: Console.WriteLine("Неверный выбор. Пожалуста выберите 1, 2, или 3."); 35: break; 36: } 37: 38: if (cost != 0) 39: { 40: Console.WriteLine("Внесите {0} копеек.", cost); 41: Console.WriteLine("Спасибо!"); 42: } 43: else 44: { 45: Console.Write("Пожалуйста, повторите выбор."); 46: } 47: 48: // Delay. 49: Console.ReadKey(); 50: } 51: } 52: }
Представьте, что мы стоим у кофейного аппарата. И вам сказали написать программу приема оплаты в кофейном аппарате. Вы видели, что стоят кофейные аппараты, где на предлагается выбрать кофе и бросить определенную сумму денег. И вот наш кофейный аппарат имеет всего три вида кофе. Маленький, средний и большой. На 13 строке нам предлагается сделать выбор. На 16 строке мы принимаем ввод от пользователя. То есть пользователь нажимает либо 1, либо 2, либо 3. Cost на 18 строке будет содержать в себе стоимость напитка. Разные размеры напитков по-разному стоят. Давайте проверим как работает эта программа. Мне предлагаются размеры стаканчиков кофе 1, 2, 3. Пожалуйста, сделайте свой выбор. Возьму средний. Внесите 50 коп. Спасибо! Давайте еще раз выполнимся. А если я введу маленький? Внесите 25 копеек. Нет, целый день на работе, нужно больше кофе. Потому что кто такой программист? Это машина, которая перерабатывает кофе в код. Берем 3. Внесите 75 копеек. Интересно, как работает логика этого автомата. Мы вводим размер кофе. Если введем не то, то будет сообщение о неверном выборе. Он нам не даст возможности что-то купить. Cost – это общая стоимость напитка. Как-то у нас он будет вычисляться своеобразно. На 22 строке мы создаем переключатель swich, которому в качестве выражения селектора мы передаем выбор пользователя. Если пользователь выбрал 1, то мы к общей стоимости прибавим 25 и прерываем работу. Проверяем, если cost не ноль, потому что если я ввел абракадабру, то у меня cost = 0 и мне не нужно просить пользователя ввести 0 копеек и благодарить. Мне нудно сказать, чтобы я повторил свой выбор. Потому что не сработал не один из case, я не сделал ни одного правильно выбора, потому что cost изменится только в том случае, если я введу 1, 2, 3. А иначе мне скажется – неверный выбор, я выхожу, условие не удовлетворяет истинности, потому что cost = 0. И дальше в блоке else мне говорится, чтобы я повторил выбор. Если я ввожу 1, мне в cost прибавляется 25. Выбрасывает меня сюда, cost уже не равен 0. Он равен 25. Мне говорится, чтобы я вне 25 копеек. Хорошо, если я ввожу 2. Срабатывает второй case, потому что значение выражения селектора совпало с постоянным выражением второго оператора case. У мен в cost добавляется 25. Присвоение со сложением. 0+25=25. И смотрите что происходит. Go to – иди туда. Куда идти? На первый case. Я прибавляю уже к тем что уже есть еще 25 копеек. Итого 50 копеек. А если выражение селектора содержит 3, я выбрал большой напиток. Тогда у мен срабатывает третий case, я cost прибавляю 50, и далее делаю goto на case 1 и к 50 добавляю еще 25. 75 копеек получается. Break – вышли. Зачем так сложно сделали? Если можно было здесь cost присвоить 25, здесь – 50, а здесь – 75. Можно было бы так сделать. А как бы мы с вами разобрали использование оператора goto в swich. А так мы с вами рассмотрели работу оператора goto. И вы при этом увидели еще и оптимизацию кода. Вы сами себе его оптимизировали. А мы с goto еще будем встречаться. Это спорный оператор. Использовать его или не использовать. Мы к нему еще подойдем. Но сейчас мы с ним уже познакомились. Пока иди на определенный case. Возвращаемся к нашей презентации. Нам нужно немножко повторить то, что мы с вами сегодня рассмотрели. Тема нашего сегодняшнего урока была – условные конструкции. И у нас условных конструкций бывает три. Условные операторы. Мы помним, что он может быть сам по себе, вместе с else, каскадом, а также условные конструкции могут быть вложены в другие конструкции. Тернарный оператор – еще проще. ? – ТО. : - ИНАЧЕ. Перед знаком вопроса – условие. После вопроса – истинность, а потом – ложность. И оператор многозначного выбора – переключатель swich – case. Мы знаем, что он работает с выражением селектора, а то что возле case – постоянное выражение, а также необязательный блок default. И правила следующие: для того, чтобы выполнилось тело какого-то оператора case, то его постоянное выражение должно совпасть со значением выражения селектора оператора swich. И если значение выражения селектора не совпадет ни с одним из постоянных выражений? то у нас выполнится необязательный блок default. Смотрите, какие у нас простые правила, какие простые условные конструкции. На этом наш урок закончен, спасибо за внимание, до новых встреч.