Кроме условных операторов if, else и else if также существует ещё и тернарный оператор.
Данный оператор порой бывает удобен в случаях, если при выполнении какого-то условия или его невыполнении нам нужно присвоить строго определённое значение какой-либо переменной. Хотя такая ситуация и не столь частая, но в случае её возникновения тернарный оператор намного удобнее и читабельнее нежели конструкция IF.
Тернарный оператор (от латинского слова ternarius — тройной)- это оператор, состоящий из двух символов ? и :, который формирует условную тернарную операцию, возвращающую свой второй или третий операнд в зависимости от выполнения или невыполнения определённого условия, или другими словами от результата логического выражения.
Прежде чем посмотреть, как выглядит конструкция с применением тернарного оператора, я хотел бы привести следующий пример с использование конструкции IF ELSE
if (x > y)
{
z = x;
}
else
{
z = y;
}
Вроде бы незатейливая у нас конструкция. В случае если x>y, то z будет равен x, а если не так, то z будет равен y.
Тем самым мы определяем максимальное значение из двух возможных чисел и присваиваем его переменной z.
Теперь посмотрим вот такой вариант записи исходного кода, имеющий тот же результат
z = (x > y) ? x : y;
Не правда ли, запись намного упростилась.
После всего этого попробуем всё это красиво нарисовать
Теперь, глядя на диаграмму, попытаюсь ещё раз объяснить поподробнее. В случае использования условной тернарной операции, когда заданное условие выполнятся, то переменной присваивается значение выражения 1, а если не выполняется, то значение выражения 2.
Теперь, надеюсь, всё стало понятно. Если нет, то отработаем понимание в практической части.
Также возможна вложенность условий, правда это используется нечасто, так как очень сильно страдает читабельность кода.
Например, напишем вот такой код
avg = (x > y) ? (x > z) ? (z > y) ? z : y : x : (y > z) ? (z > x) ? z : x : y;
Данный код вычисляет среднее значение (не средне-арифметическое, а именно среднее по значению из возможных) из трёх чисел — x, y и z.
Согласитесь, что такой код даже не хочется читать, мало того, он испугает читателя. Хотя код верный и всё правильно работает.
Так или иначе, такая конструкция имеет право на существование и подчёркивает возможность вложенности тернарных операций.
Только если мы напишем её вот так
if (x > y)
{
if (x > z)
{
if (z > y)
{
avg = z;
}
else
{
avg = y;
}
}
else
{
avg = x;
}
}
else
{
if (y > z)
{
if (z > x)
{
avg = z;
}
else
{
avg = x;
}
}
else
{
avg = y;
}
}
То она станет гораздо читабельнее, хотя и будет громоздкой.
Тем не менее мы сегодня в практической части небольшую вложенность применим.
Давайте к ней и приступим.
Проект сделаем из проекта MYPROG10 прошлого занятия и имя ему было присвоено MYPROG11.
Откроем файл main.c и в функции main(), как обычно, удалим весь код тела кроме возврата нуля, останется от него вот это
int main()
{
return 0; //Return an integer from a function
}
Добавим в тело функции main() следующий код
1 2 3 4 5 6 7 8 9 |
int main() { int n, m, res; printf("Please enter an integer (n)\r\n"); scanf("%d", &n); printf("Please enter an integer (m)\r\n"); scanf("%d", &m); res = (n > m) ? n : m; printf("The maximum number of entered: %d", res); |
Мы объявили три переменных. Две для выражений и одну для результата.
Затем мы просим пользователя ввести целое число и запишем его в одну переменную. Потом просим ввести ещё одно число и присвоим его другой переменной.
Далее мы используем тернарный оператор для того, чтобы вычислить максимальное из введенных число. Если n больше m, то в результат занесём n, а если нет — то m.
Кто-то скажет, что везде используется один и тот же пример для объяснения работы тернарного оператора, я это тоже знаю, просто лучшего примера для этого я придумать не смог. Поэтому остановимся в этот раз на классике.
Испытаем наш код в консоли
Всё отлично работает. По-хорошему, надо бы обработать случай ввода одинаковых значений, но мы этого не будем делать, чтобы не отвлекаться на мелочи.
Закомментируем введённый код и добавим следующий
1 2 3 4 5 6 |
*/ int n, res; printf("Please enter an integer\r\n"); scanf("%d", &n); res = (n >= 0) ? n : -n; printf("The modulus of the entered number is %d", res); |
Данный код вычисляет модуль введённого числа. Число записывается в переменную n, затем тернарная операция спрашивает, больше ли нуля наше число или равно, если больше, то возвращает это число, а если нет, то возвращает модуль, используя знак минус.
Проверим работу нашего кода
Отлично! И этот код работает.
Добавим теперь вот такой код, закомментировав, конечно, сначала предыдущий
1 2 3 4 5 |
*/ int n; printf("Please enter an integer\r\n"); scanf("%d", &n); printf("The number entered is %s than 10\r\n", (n > 10) ? "greater" : "less than or equal"); |
Здесь мы уже используем нашу тернарную операцию внутри вызова функции prinf, то есть результат тернарной операции будет аргументом функции (или параметром).
Мы проверяем введённое значение и присвоенного его переменной a, чтобы оно было больше 10. Если это так то возвращаем одну строку, а если нет, то другую. Затем возвращённая строка подставится в строку, стоящую в первом аргументе вместо модификатора %s.
Проверим работу кода
Закомментируем наш код и немного его усовершенствуем
1 2 3 4 5 |
*/ int n; printf("Please enter an integer\r\n"); scanf("%d", &n); printf("The number entered is %s10\r\n", (n > 10) ? "greater than " : (n == 10) ? "" : "less than "); |
Здесь происходит всё наподобие, как и в предыдущем примере, только мы уже применили вложенность, которая дала нам возможность отследить случай равенства 10 значения нашей переменной. В этом случае мы уже вставляем пустую строку, останется только «is». То есть мы сначала исследуем на «больше», если больше, то выдаём строку, если нет, то продолжаем исследовать на равенство, если равно, то пустая строка, если нет, то значит «меньше» и возвращаем соответствующую строку.
Проверим, как это работает
Всё работает.
Подключим ещё одну стандартную библиотеку в наш исходный файл
1 2 |
#include <string.h> #include <stdlib.h> |
Теперь, закомментировав предыдущий код в функции main(), ещё усложним наш код. данный код число, введённое пользователем в диапазоне от 0 до 10 прописью
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
*/ int n=0; char *strnum = (char*) malloc(10);; while((n>=0) && (n<=10)) { printf("Please enter an integer\r\n"); printf("To exit the program, enter a number greater than 10 ...\r\n"); scanf("%d", &n); strnum = n == 0 ? "zero": n == 1 ? "one": n == 2 ? "two": n == 3 ? "three": n == 4 ? "four": n == 5 ? "five": n == 6 ? "six": n == 7 ? "seven": n == 8 ? "eight": n == 9 ? "nine": n == 10 ? "ten": "greater than 10 or less than 0"; printf("The number entered is %s.\r\n", strnum); } |
Вот такая вот вложенность получилась. Если писать в такой столбик, то получается вполне нормально. Выходит конструкция, похожая на switch, только у нас появляется прекрасная возможность использовать не константы в кейсах, а уже условия.
Мы обернули наш оператор в цикл типа while, который проверит, входит ли введённое число в нужный диапазон, если нет, то выведется соответствующее сообщение заcчёт последнего выражения в тернарной конструкции и мы выйдем из цикла.
Также мы здесь использовали выделение памяти в количестве 10 байт с помощью функции стандартной библиотеки malloc. Так как мы использовали указатель, то память под массив строк, на который он будет указывать, не каждый компилятор выделит автоматически.
Попробуем работу нашего кода
Всё правильно работает.
На этом, думаю, пора завершать нашу практическую часть, а также и урок. Что-то мы даже, я бы сказал, слишком увлеклись практической проработкой. Но, по большому счёту, это же неплохо!
Итак, на данном уроке мы познакомились с тернарным оператором, узнали как работает конструкция с его применением и, по нашей сложившейся традиции, закрепили наши знания на практике.
Всем спасибо за внимание!
Предыдущий урок Программирование на C Следующий урок
Смотреть ВИДЕОУРОК (нажмите на картинку)
Отлично объясняете! Спасибо Вам! С нетерпением жду продолжения.
avg = (x > y) ? (x > z) ? (z > y) ? z : y : x : (y > z) ? (z > x) ? z : x : y;
никак не могу разобраться в вашем примере. какая здесь последовательность? как программа понимает, какая переменная является средней?
Не всё сразу.
может такая запись поможет для понимания:
avg = (x > y) ? ((x > z) ? ((z > y) ? z :y) : x) : ((y > z) ? ((z > x) ? z : x) : y);
Cпасибо большое!
после использования malloc не надо использовать free?
Си сам не чистит память, то есть это обязательно делать вручную на каждой точке выхода из программы, во всех ветвлениях по завершении использования выделенной памяти. Иначе будут утечки. Если у тебя массив на несколько элементов и текут какие-то считанные килобайты, можно и забить согласно чьей-то логике, но лучше сразу вырабатывать привычку делать правильно. Иначе потом тебя никто не поймет с таким подходом, при котором программа течёт.