#c #if-statement #ternary-operator
#c #оператор if #троичный оператор
Вопрос:
У меня возникли проблемы с установкой двух целых чисел с использованием троичных операторов в C. Кажется, я не могу найти ответ, поскольку большинство вопросов относятся к нескольким троичным условиям.
Принимая во внимание, что я хочу проверить одно условие и установить 2 значения соответственно.
Ie:
if ( i == 5 ) {
x = foo;
y = foo 1;
} else {
x = bar;
y = bar 1;
}
до сих пор я пробовал следующее, но, похоже, это не работает.
x, y = ( i == 5 ) ? foo, foo 1 : bar, bar 1;
возможно ли установить два значения в троичном после проверки 1 условия?
Спасибо,
Комментарии:
1. Почему бы не придерживаться оператора if — читаемый, поддерживаемый и т. Д. Троичный оператор — это просто синтаксический сахар. Держите код простым для понимания. Легче отлаживать. Легче исправить. ….
2. @Olaf — Было бы это хорошей идеей в Python?
3. Нет, в C. нет поддержки кортежей. Если бы ваш пример был реальным кодом, правильным ответом было бы использовать троичный оператор для set
x
, а затемy=x 1
.4. в python обычной практикой является возврат нескольких параметров. так что я бы сказал, да.
5. @EdHeal: не этот (и не тот же синтаксис, конечно). Но да, вы можете использовать троичный оператор таким образом. Столько, сколько вы можете прибить пианино к колену 🙂
Ответ №1:
Это невозможно. В отличие от python или perl, которые поддерживают присвоение списку чисел, C не поддерживает этот синтаксис.
Для этого вам понадобятся две отдельные троичные операции:
x = (i == 5) ? foo : bar;
y = (i == 5) ? foo 1 : bar 1;
В случае, если вы хотите, чтобы условие выполнялось только один раз (например, это вызов функции или какая-либо другая дорогостоящая операция):
int result = (i == 5);
x = result ? foo : bar;
y = result ? foo 1 : bar 1;
Редактировать:
Если вы хотите использовать что-то немного уродливое, это сработает:
x = (i == 5) ? (y = foo 1, foo) : (y = bar 1, bar);
С помощью оператора запятой левая часть оператора вычисляется (в данном случае присваивается y
) и отбрасывается, в то время как правая часть становится значением выражения, которому впоследствии присваивается x
.
Обратите внимание, что скобки строго не нужны для части «if», но они необходимы для части «else».
Однако это злоупотребление языком. Лучше придерживаться чего-то более читаемого.
Комментарии:
1. Интересное использование оператора запятой … мои проще, но все же не рекомендуются.
2. @chqrlie То, что у вас есть, работает в конкретном случае OP, где значения
x
иy
связаны. В целом все вышеперечисленное будет работать.3. Сначала я воспользовался отношением, но ваш подход вдохновил на более общую альтернативу:
(i == 5) ? (x = foo, y = foo 1) : (x = bar, y = bar 1);
такую же уродливую, но легко распространяемую на любое количество назначений.
Ответ №2:
Вы можете использовать функцию:
void setAndIncrement(int val, int *x, int *y) {
*x = val;
*y = val 1;
}
....
(i == 5) ? setAndIncrement(foo, amp;x, amp;y): setAndIncrement(bar, amp;x, amp;y);
Но это не сделает ничего лучше или проще в обслуживании. Вы действительно должны просто придерживаться if
and else
. Он прост в чтении, удобен в обслуживании и полностью соответствует тому, как вы должны это делать.
Ответ №3:
Как говорит @dbush, вы не можете этого сделать в C. В C вы можете использовать различные типы кортежей, но это выходит за рамки вопроса.
Так почему бы и нет? В Python и многих новых языках оператор запятой объединяет значения (грубо говоря) вместе, чтобы их можно было рассматривать как единое целое. Это то, что делает Python и что позволяет x,y = 1,2 if a else 3,4
работать.
Однако в C оператор запятой разделяет выражения или операторы, а не значения. a,b
вычисляет a
, отбрасывает результат, вычисляет b
и предоставляет результат вычисления b
как результат запятой. Ни в коем случае a
b
не рассматриваются вместе.
(Мастера C и юристы по языку: для удобства чтения OP я намеренно исключаю соображения lvalue / rvalue и другие более тонкие семантические моменты. Да, вы правы, что полный ответ не должен этого делать. :))
Ответ №4:
Хотя я бы не рекомендовал использовать для этого одну троичную операцию, это можно сделать. Если это просто проблема, вот несколько решений:
y = 1 (i == 5 ? (x = foo) : (x = bar));
поочередно:
y = 1 (x = i == 5 ? foo : bar);
Или более общий:
(i == 5) ? (x = foo, y = foo 1) : (x = bar, y = bar 1);
Как вы можете видеть, все они несколько искажены и не очень удобочитаемы.
Если вы можете написать 2 оператора, я бы рекомендовал:
x = (i == 5) ? foo : bar;
y = x 1;
Комментарии:
1. спасибо, да, в конце 2 оператора предлагают немного больше гибкости
Ответ №5:
Различные способы достижения цели установки двух значений:
Конечно, первое чистое и легко читаемое.
if ( i == 5 ) {
x = foo;
y = foo 1;
} else {
x = bar;
y = bar 1;
}
Другой способ — установить N
поля одного объекта и назначить его с помощью составных литералов C11. Это работает с ?:
тем, как код устанавливает один объект.
int i = rand(), foo = rand(), bar = rand();
typedef struct {
int x;
int y;
int z;
} xyz_T;
xyz_T xyz = (i == 5) ?
(xyz_T ) { .x = foo, .y = foo 1, .z = 1 } :
(xyz_T ) { .x = bar, .y = bar 1, .z = 2 };