установить 2 значения в троичной операции — C

#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 };