я % 2 == 0 ? обр[я] = 0 : обр[я] = 1; Тернарная ошибка оператора

О тернарном операторе. Я переписывал оператор if-else на C, используя более чистый тернарный оператор. Вот код:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int arr[10];
    int i;

//    for ( i = 0; i < 10; i++ )
//    {
//        if ( i % 2 == 0 )
//        {
//            arr[i] = 0;
//        }
//
//        else arr[i] = 1;
//    }

    for ( i = 0; i < 10; i++ )
    {
         i % 2 == 0 ? arr[i] = 0 : arr[i] = 1;//Line in question
    }

    /* Just to check the result */
    for ( i = 0; i < 10; i++ )
    {
        printf ( "%d ", arr[i] );
    }

    return 0;
}

Закомментированный код работал, но, к моему удивлению, когда я скомпилировал файл с тернарным оператором, я получил следующее:

C:\Users...\main.c|21|ошибка: в качестве левого операнда присваивания требуется lvalue|

Это простой код для проверки того, является ли позиция в массиве четной или нечетной. Выполнил поиск, и единственное, что я прочитал, связанное с этим кодом, это то, что lvalue является переменной. Если это правда, я приведу пример, на который по сей день у меня нет ответа:

printf ( "%d", 23 + 4 );

Заполнитель будет заменен буквальным значением 27. Здесь не задействована никакая переменная, она работает жестко. Спасибо.


person mxajd    schedule 19.05.2015    source источник
comment
троичный должен быть variable = condition ? true_result : false_result. выполнение заданий внутри блоков результатов довольно неприятно/уродливо. например arr[i] = i % 2 == 0 ? 0 : 1   -  person Marc B    schedule 19.05.2015
comment
Тернарный оператор не более чистый, чем if-else. Ваша удивительная ошибка является демонстрацией этого факта.   -  person    schedule 19.05.2015
comment
По крайней мере, в этом случае тернарный оператор не более понятен, чем оператор if/else. Это просто делает код трудным для чтения (и, как вы видели, синтаксически неправильным).   -  person Keith Thompson    schedule 19.05.2015
comment
@Hurkyl Это может быть чище, если использовать его, как предложил Марк Б.   -  person juanchopanza    schedule 19.05.2015
comment
Я с Хёркилом и Китом Томпсоном. Глазу легче следить за if...else, чем расшифровывать троичную, и по этой причине я никогда не использую ее.   -  person Weather Vane    schedule 19.05.2015
comment
Не используйте тернарный оператор в качестве управляющей структуры (т. е. для выполнения одного или нескольких операторов в зависимости от условия); это не то, для чего он предназначен. Это приводит к тому, что код становится труднее читать и, как вы уже заметили, имеет некоторые проблемы с приоритетом.   -  person John Bode    schedule 19.05.2015
comment
@JohnBode: Как вы подразумеваете, тернарный оператор имеет свое место. Например, x = cond ? this : that; позволяет избежать повторения x, что особенно полезно, когда x равно foo->bar[baz].thud. Это также полезно в определениях макросов, когда вы хотите, чтобы макрос расширился до выражения.   -  person Keith Thompson    schedule 19.05.2015
comment
@KeithThompson Правда, это было синтаксически неправильно. Я долгое время не занимался программированием из-за болезни и пытаюсь встать на ноги. Сейчас очень тяжело иметь идею и не иметь возможности записать ее, даже если это простое упражнение. Тем не менее я нахожу тернарный оператор действительно более чистым, особенно в случаях, когда сравниваются значения двух переменных (по крайней мере, для меня это был первый раз, когда мне представили эту управляющую структуру). Просто из любопытства, можете ли вы подробнее остановиться на обоих случаях, которые вы предлагаете?   -  person mxajd    schedule 19.05.2015
comment
Я думаю, что большинство программистов на C согласятся с тем, что использование тернарного оператора when и if/else делает то же самое, просто делает код более неясным. Использование его в выражении может быть полезным, если это означает, что другие части одного и того же выражения не должны повторяться.   -  person Keith Thompson    schedule 20.05.2015
comment
@KeithThompson У меня был учитель, у которого была противоположная идея. В этом конкретном случае цель (о которой я забыл сказать, но я только что написала об этом в сводке по редактированию) состояла в том, чтобы написать все это в одной строке кода. Так что я вспомнил эту структуру управления.   -  person mxajd    schedule 20.05.2015
comment
@mxajd: Пожалуйста, не принимайте всерьез совет своего учителя, по крайней мере, не в этом конкретном вопросе. Выяснение того, как написать сложный код в одну строку, может быть забавным, но результат трудно читать и сложно поддерживать. Любой заданный фрагмент кода будет прочитан гораздо больше раз, чем написан, и, вероятно, также несколько раз изменен. Оптимизируйте для ясности, а не для краткости.   -  person Keith Thompson    schedule 20.05.2015


Ответы (4)


Изменять:

i % 2 == 0 ? arr[i] = 0 : arr[i] = 1;

к этому:

i % 2 == 0 ? (arr[i] = 0) : (arr[i] = 1);

Условный оператор имеет более высокий приоритет, чем оператор присваивания.

Как было предложено в комментариях, вы можете получить тот же результат с помощью:

arr[i] = (i % 2 == 0 ? 0 : 1);

или просто:

arr[i] = i % 2;
person ouah    schedule 19.05.2015
comment
Или arr[i] = <ternary op expression> может быть понятнее. - person juanchopanza; 19.05.2015
comment
@KeithThompson Да, этот определенно выигрывает. - person juanchopanza; 19.05.2015
comment
@ouah Ваше объяснение мне непонятно: условный оператор имеет более высокий приоритет, чем оператор присваивания. Это была моя мысль; сначала оценивается условие, а затем выполняется присваивание. Хотя я согласен с некоторыми решениями пользователей (намного лучше моего), я помню, как несколько лет назад, когда мне впервые показали тернарный оператор, парентис имел значение. Только не помните, когда и в данном случае почему. - person mxajd; 20.05.2015
comment
@mxajd это означает, что такое выражение, как x ? y = a : y = b, анализируется как (x ? (y = a) : y) = b, а не как (x ? (y = a) : y) = b - person ouah; 20.05.2015
comment
@mxajd сначала оценивается условие, а затем выполняется назначение. - вы путаете порядок оценки с приоритетом. - person The Paramagnetic Croissant; 20.05.2015

Вы можете просто это :)

arr[i] = i%2;
person P.P    schedule 19.05.2015
comment
Или еще лучше i & 1 для правильной обработки отрицательных значений, которые, по общему признанию, не являются проблемой в исходном примере кода. - person doynax; 19.05.2015

Я полагаю, что из-за проблем с приоритетом операторов ваш код анализируется следующим образом: (i % 2 == 0 ? arr[i] = 0 : arr[i]) = 1;. Тернарный оператор создает rvalue, которому в C нельзя присвоить значение. Вы должны изменить его на i % 2 == 0 ? (arr[i] = 0) : (arr[i] = 1);

В любом случае, вся эта конструкция лишняя, и ее лучше заменить чем-то вроде arr[i] = i % 2;

person Mints97    schedule 19.05.2015

Почему бы нет:

for (i=0; i < 10; i+=2)  {
    arr[i]   = 0;
    arr[i+1] = 1;
}
person Ingo    schedule 19.05.2015
comment
Задача состояла в том, чтобы сделать все это в одной строке - person mxajd; 20.05.2015