2016-10-17 2 views
3

У меня возникли проблемы с установкой двух ints с использованием тернарных операторов в C. Я не могу найти ответ, поскольку большинство вопросов относятся к нескольким тернарным условиям.установить 2 значения в тройной операции - 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 условия?

спасибо,

+0

C не является Python. – Olaf

+2

Почему бы не придерживаться инструкции if - читать, ремонтировать и т. Д. Тернарный оператор - это просто синтаксический сахар. Держите код прост для понимания. Легче отлаживать. Легче исправить. .... –

+0

@Olaf - Это будет хорошая идея в Python? –

ответ

3

Это невозможно. В отличие от 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; 

EDIT:

Если вы хотите использовать что-то немного уродливый, это будет работать:

x = (i == 5) ? (y = foo + 1, foo) : (y = bar + 1, bar); 

С помощью оператора запятой оценивается левая сторона оператора (в данном случае назначение y) и отбрасывается, а правая сторона становится значением выражения, которое впоследствии присваивается x.

Обратите внимание, что круглые скобки строго необходимы для части «если», но они необходимы для части «else».

Это, однако, злоупотребление языками. Лучше придерживаться чего-то более читаемого.

+0

Интересное использование оператора запятой ... моя проще, но все же не рекомендуется. – chqrlie

+0

@chqrlie Что вы работаете в конкретном случае OP, где значения 'x' и' y' связаны. Вышеупомянутое будет работать в целом. – dbush

+0

Сначала я воспользовался этим отношением, но ваш подход вдохновил более общую альтернативу: '(i == 5)? (x = foo, y = foo + 1): (x = bar, y = bar + 1); 'столь же уродливое, но легко распространяемое на любое количество назначений. – chqrlie

1

Вы можете использовать функцию:

void setAndIncrement(int val, int *x, int *y) { 
    *x = val; 
    *y = val + 1; 
} 

.... 

(i == 5) ? setAndIncrement(foo, &x, &y): setAndIncrement(bar, &x, &y); 

Но это не будет делать ничего лучше и проще в обслуживании. Вы действительно должны просто придерживаться if и else. Его легко читать, ремонтировать и все вокруг так, как вы должны это делать.

1

Как @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 и другие более тонкие смысловые точки. Да, вы правы, что полный ответ не должен делать этого. :))

1

Хотя я бы не рекомендовал использовать для этого одну тройную операцию, это можно сделать. Если это просто вызов, вот некоторые решения:

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; 
+0

спасибо, да, в конце 2 заявления предлагают немного большую гибкость –

1

Различные способы достижения цели установления двух значений:

Конечно, первый чистый и легко читать.

if (i == 5) { 
    x = foo; 
    y = foo + 1; 
} else { 
    x = bar; 
    y = bar + 1; 
} 

Другой установить N поля одного объекта и присвоить, что с помощью С11 составных литералов. Это работает с ?:, так как код устанавливает один объект.

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 }; 
Смежные вопросы