i % 2 == 0? arr[i] = 0 : arr[i] = 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|грешка: lстойност се изисква като ляв операнд на присвояване|

Това е прост код за проверка дали позицията в масива е нечетна или четна. Направих търсене и единственото нещо, което прочетох, което е свързано с този код, е, че 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 Може да е по-чисто, ако се използва, както е предложено от Marc B.   -  person juanchopanza    schedule 19.05.2015
comment
Аз съм с Hurkyl и Keith Thompson. За окото е по-лесно да следва 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