Тернарный оператор и оператор запятая
Тернарный оператор и оператор запятая
Название «тернарный» произошло от латинского ternarius – тройной. Оператор принимает три аргумента. Если первый аргумент истина, то возвращается второй аргумент, если ложь, то возвращается третий.
Синтаксис оператора
<условие> ? <аргумент 2> : <аргумент 3>
Например, пользователь вводит два числа. Присвоить переменной значение наименьшего.
#define _CRT_SECURE_NO_WARNINGS #include <conio.h> #include <stdio.h> void main() { int a, b, c; scanf("%d %d", &a, &b); c = (a > b) ? b : a; printf("%d", c); _getch(); }
Другой пример: вывести модуль числа
#define _CRT_SECURE_NO_WARNINGS #include <conio.h> #include <stdio.h> void main() { int a; scanf("%d", &a); printf("%d", a > 0 ? a : -a); _getch(); }
Здесь тернарный оператор используется вместо аргумента функции printf.
Оператор ? может быть вложенным. Например, найдём среднее из трёх чисел:
#include <conio.h> #include <stdio.h> void main() { int a = 1; int b = 2; int c = 3; int mid; mid = (a > b) ? (a > c) ? (c > b) ? c : b : a : (b > c) ? (c > a) ? c : a : b; printf("%d", mid); _getch(); }
Видно, что в этом примере тернарный оператор становится нечитаемым. Поэтому не используйте вложенные тернарные операторы и заменяйте их на обычные ветвления
#include <conio.h> #include <stdio.h> void main() { int a = 1; int b = 2; int c = 3; int mid; if (a > b) { if (a > c) { if (c > b) { mid = c; } else { mid = b; } } else { mid = a; } } else { if (b > c) { if (c > a) { mid = c; } else { mid = a; } } else { mid = b; } } printf("%d", mid); _getch(); }
Для тернарного оператора определён порядок выполнения. Все значение и побочные эфекты, связанные с первым выражением реализуются перед тем, как будут реализованы значения и побочные эффекты для второго и третьего выражений.
#include <conio.h> #include <stdio.h> void main() { int x = 0; //Выведет 200, так как ++ постфиксный printf("%d\n", x++ ? 100: 200); //Выведет 1, так как после проверки x был увеличен printf("%d\n", x); x = 0; //Выведет 100, так как сначала будет увеличен x printf("%d\n", ++x ? 100 : 200); printf("%d\n", x); x = 0; printf("%d\n", ++x ? x++ : x++); //Выведет 2, так как будет выполнено первое условие //и x будет инкрементирован повторно printf("%d\n", x); _getch(); }
Оператор '?' в некоторых случаях можно компактно записать как оператор switch:
#define _CRT_SECURE_NO_WARNINGS #include <conio.h> #include <stdio.h> int main(int argc, char **argv) { unsigned day_of_week; char const * name; printf("day of week: "); scanf("%u", &day_of_week); name = day_of_week == 1 ? "Monday" : day_of_week == 2 ? "Tuesday" : day_of_week == 3 ? "Wednesday" : day_of_week == 4 ? "Thursday" : day_of_week == 5 ? "Friday" : day_of_week == 6 ? "Saturday" : day_of_week == 7 ? "Sunday" : "Wrong day of week"; printf("%s", name); _getch(); }
Оператор запятая.
Оператор «,» принимает два аргумента, выполняет первый, после этого выполняет второй и возвращает его значение. Например:
#include <conio.h> #include <stdio.h> void main() { int a, b, c; c = (a = 3, b = 4); printf("%d", c); _getch(); }
В данном примере c будет равно 4. Выражение
(a = 3, b = 4)
вернёт 4. Очевидно, что если убрать скобки, то c станет равным 3, так как запятая в этом случае будет разделять c = a = 3 и b = 4, с присвоится значение 3, а 4 будет возвращено оператором запятая, но потеряется. То есть выражение
c = a = 3, b = 4;
эквивалентно
(c = a = 3), (b = 4);
Если написать
c = (a = 3, b = 4, d = 5);
то будет возвращено значение 5.
В выражении
#include <conio.h> #include <stdio.h> void main() { int c; c = 1, 2, 3, 4, 5; printf("%d", c); _getch(); }
с будет равно 1, так как этот код эквивалентен такому
((((c = 1), 2), 3), 4), 5;
Такое поведение оператора запятая часто приводит к следующей ошибке. Вместо десятичной точки
a = 1.5;
пишут
a = 1,5;
Таким образом, переменная a будет иметь значение 5.
Для оператора «,» гарантированно выполнение по порядку, слева направо. Оператор запятая поэтому используется в условиях, когда нужно выполнить несколько действий или получить значение. Например
#include <conio.h> #include <stdio.h> int foo(int a) { return a % 5 + a*a; } void main() { int i = 0; int mod; while (mod = foo(i), mod < 100) { printf("%d ", i); i++; } _getch(); }
Часто запятая используется в цикле for, так как позволяет задавать несколько значений или выполнять несколько значений за раз. Пример – переворачивание массива.
#include <conio.h> #include <stdio.h> #define SIZE 10 void main() { int arr[SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; int i, j, tmp; for (i = 0, j = SIZE - 1; i < SIZE / 2; i++, j--) { tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } for (i = 0; i < SIZE; i++) { printf("%d ", arr[i]); } _getch(); }
