Kolmiosainen ehdollinen operaatio ( latinasta ternarius - "kolmio") on monilla ohjelmointikielillä toteutettu operaatio, joka palauttaa toisen tai kolmannen operandinsa riippuen ensimmäisen operandin antaman loogisen lausekkeen arvosta. Matemaattisen logiikan ja Boolen algebran ternaarisen ehdollisen operaation analogi on ehdollinen disjunktio , joka on kirjoitettu muotoon ja toteuttaa algoritmin: "jos , niin , muuten ".
Tyypillisesti kolmiosainen ehdollinen operaattori liittyy C:n kaltaisissa ohjelmointikielissä ?:käytettyyn operaattoriin. Itse asiassa samanlaisia toimintoja eri syntaksilla on monissa ohjelmointikielissä, jotka ovat kaukana C :stä syntaksissa . Suosittuja kieliä, joiden syntaksiin on sisäänrakennettu kolmiosainen ehdollinen operaattori, ovat C , C++ , JavaScript , Objective-C , C# , D , Java , ECMAScript , Perl , PHP , Python , Tcl , Ruby , Verilog , Turbo Basic . Tämä operaatio johtuu esiintymisestä suoraan kolminumeroisessa infix-muodossa Algol-60- kielelle , jossa sillä oli syntaksi , ja sitten BCPL -kielelle ( ) [1] tutun sijaan . Tämän toiminnon prototyyppi on puolestaan Lisp-kielen ehdollinen funktio , joka on kirjoitettu Lisp-kielen sääntöjen mukaan etuliitemuodossa ja jolla on mielivaltainen määrä argumentteja. if o1 then o2 else o3o1 -> o2, o3o1 ? o2 : o3cond
Yleensä toiminnon toteutus sisältää ehdon laskennan ja vain yhden lausekkeen, joka joissakin tapauksissa tarjoaa laajennetut ominaisuudet, esimerkiksi lauseke x > 0 ? 0 : sqrt(x)katsotaan oikeaksi huolimatta siitä, että juuria ei oteta negatiivisista luvuista.
Lukujen a ja b vähimmäismäärä:
min = (a < b) ? a : bVoidaan käyttää muussa kuin toimeksiantotilanteessa:
sprintf ( otsikko , "%s %s" , tv_system == TV_PAL ? PAL : SECAM , tv_input ? Tv_Name [ tv_input - 1 ] : "TESTATA" );- tässä tapauksessa vastaava rakenne, jossa käytetään if-then-else, vaatisi funktiokutsun kirjoittamisen sprintfneljä kertaa.
Basic C : llä ei ole loogista tietotyyppiä ( C99 esitteli loogisen _Bool-tyypin), joten ensimmäisen operandin tulee olla numero ( kokonaisluku tai reaaliluku ) tai osoitin [2] ; Ensin sen arvo lasketaan ja sitä verrataan nollaan , ja jos se ei ole yhtä suuri kuin nolla, lasketaan ja palautetaan toinen operandi, yhtäläisyyden tapauksessa kolmas. Toinen ja kolmas operandi voivat olla erityyppisiä (mukaan lukien void ).
C++ :ssa kolmiehtoisella operaattorilla on sama syntaksi kuin C:ssä [3] , mutta alustuksen ja osoituksen välisen eron vuoksi on tilanteita, joissa operaatiota ?:ei voida korvata konstruktilla if-then-else, kuten esimerkiksi seuraavassa tapaus:
#include <iostream> #include <fstream> #sisällytä <merkkijono> käyttäen nimiavaruutta std ; int main ( int argc , char ** argv ) { merkkijonon nimi ; _ outstream fout ; if ( argc > 1 && argv [ 1 ]) { nimi = argv [ 1 ]; fout . open ( name.c_str ( ), ios :: out | ios :: app ) ; } ostream & sout = nimi . tyhjä () ? cout : fout ; paluu 0 ; }Tässä muuttuja sout alustetaan sillä hetkellä, kun kolmiosaisen operaation tulos ilmoitetaan. Samanlaista vaikutusta ei voitu saavuttaa yksinkertaisella toimeksiannolla yhdessä tai toisessa.
Lisäksi kolminkertaista ehdollista operaattoria voidaan käyttää osoituskäskyn vasemmalla puolella:
#include <iostream> int main () { int a = 0 , b = 0 ; const bool cond = ...; ( cond ? a : b ) = 1 ; std :: cout << "a=" << a << ',' << "b=" << b << '\n' ; }Tässä esimerkissä, jos looginen muuttuja cond rivillä 5 sisältää arvon tosi, muuttujalle a annetaan arvo 1, muuten se annetaan muuttujalle b.
C# : ssa kolmiosaisella operaattorilla on lisärajoituksia, jotka liittyvät tyyppiturvallisuuteen. Lausekkeiden 1 ja 2 on oltava samaa tyyppiä. Tämä johtaa seuraavaan:
int a = 1 ; kaksinkertainen b = 0,0 ; int nMax = ( a > b ) ? a : b ;Sellaista lähdekoodia ei käännetä huolimatta siitä, että nMax on lopulta . Koska a :n ja b :n on oltava samaa tyyppiä, a ylennetään kaksinkertaiseksi vastaamaan b :tä . Kolmiosaisen operaation tuloksena olevan arvon tyyppi on kaksinkertainen, ja tämä tyyppi on alaspäin int: [4]
int a = 1 ; kaksinkertainen b = 0,0 ; int nMax ; // Voit tehdä tämän: nMax = ( int ) (( a > b ) ? a : b ) ; // ...tai niin nMax = ( a > b ) ? a : ( int ) b ;Python käyttää avainsanasyntaksiaif-else :
a = 42 b = 41 tulos = a jos a > b muuten b vahvista tulos == 42Se voidaan toteuttaa myös listalla:
[ < lauseke 1 > , < lauseke 2 > ][ < ehto > ]- lausekkeen 1 tulos palautetaan, jos ehto on epätosi; ja lauseke 2, jos ehto on tosi. Jos ehto ei ole boolen lauseke, on mahdollista ylivoittaa luettelo poikkeuksella.
PHP käyttää C :n kaltaista syntaksia:
$a = $b == 1 ? "ensimmäinen arvo" : ( $b == 2 ? "toinen arvo" : ( $b == 3 ? "tulosarvo" : "oletusarvo" ));Kolmiosainen operaattori PHP:ssä vastaa pidempää if-else-rakennetta. Seuraavat kaksi esimerkkiä ovat vastaavia:
//Ensimmäinen esimerkki $result = isset ( $a ) ? $a : 'DefaultValue' ; //Toinen esimerkki if ( isset ( $a )) { $tulos = $a ; } else { $tulos = 'Oletusarvo' ; }Tällaisia rakenteita käytetään usein kuitenkin muuttujan alustamiseen myöhempiä laskelmia varten (muuten PHP antaa E_NOTICE-tason virheen).
Versiosta 5.3 alkaen tuli mahdolliseksi olla määrittämättä toiminnan toista parametria. Esimerkiksi seuraavat kaksi merkintää ovat vastaavia:
$Variable = $_GET [ 'Parametri' ] ? $_GET [ 'Parametri' ] : 'DefaultValue' ; $Variable = $_GET [ 'Parametri' ] ?: 'Oletusarvo' ;Visual Basicin klassisessa versiossa kolmiosainen operaattori on olemassa funktiona IIf(Expr, TruePart, FalsePart). Tällä funktiolla on ominaisuus: lauseketta Exprarvioitaessa lasketaan myös TruePartja FalsePartlausekkeen tuloksesta riippumatta: tosi vai epätosi. Tämä voi johtaa odottamattomiin tuloksiin ja joskus hitaaseen koodin suorittamiseen, jos palautusarvot ovat pitkiä operaatioita sisältävien funktioiden kutsuja.
Himmeä iCount As Long Julkinen Sub Main ( ) iCount = 1 MsgBox IIf ( 1 = 1 , FuncYes , FuncNo ) "Muuttuja iCount sisältää "3", koska molemmat toiminnot suoritetaan MsgBox iCount End Sub Julkinen funktio FuncYes () Merkkijonona iCount = iCount + 1 FuncYes = " Kyllä" Lopeta funktio Julkinen funktio FuncNo () Merkkijonona iCount = iCount + 1 FuncNo = " Ei " LoppufunktioVoit korvata funktion IIfkirjoittamalla lausekkeen uudelleen yhdelle riville, mutta tämä ei ole funktion analogi, vaan se on vain lyhyt muoto haaraoperaattorista
Jos Laus sitten TruePart Else FalsePartVB.NETin myötä tuttu kolmiosainen operaattori sisällytettiin kielen syntaksiin ja kirjoitetaan muodossa If(Expr, TruePart, FalsePart). Tämä operaattori käyttää supistettuja laskelmia, toisin kuin toiminto IIf, joka on myös kehittäjän käytettävissä aiempien versioiden kanssa yhteensopivuuden vuoksi. [5]
1C:Enterprise - alustan määrityskielessä kolmiosaisella operaattorilla on syntaksi:
?(boolen lauseke, lauseke 1, lauseke 2)Laajalti käytetty lyhenteenä konstrukteille Alustaversiossa Если <логическое выражение> Тогда ... Иначе ... КонецЕсли
7.7 oli mahdollista käyttää kolmiosaista operaattoria osoitusoperaattorin oikealla puolella [6] .
Haskellissa if -haara-operaattori on ehdollinen lauseke: else-lauseke vaaditaan ja sen on oltava samaa tyyppiä kuin then-lauseke. Myös vakiokirjastossa Data.Bool [7] on bool-funktio, joka palauttaa yhden kahdesta lausekkeesta riippuen predikaatin arvosta.
Kolmiosainen operaatio tavallisessa muodossaan voidaan määritellä infix-funktioksi kuviosovituksen avulla (tyypit ovat valinnaisia):
( ? ) :: Bool -> a -> a -> a ( ? ) Totta a _ = a ( ? ) Epätosi _ b = btai minkä tahansa haarautumistoiminnon kautta, esimerkiksi jos:
( ? ) predikaatti thenLaus elseLaus = jos predikaatti sitten Laus else elseLaus ( ? ) predikaatti thenLaus elseLaus = { True - > thenExpr ; _ _ _ -> elseLaus }Koska (?) on infix-funktio (binäärifunktio), se ottaa kaksi ensimmäistä argumenttia ja palauttaa yhden argumentin funktion. Sen soveltamiseksi kolmanteen argumenttiin käytetään sovellusta ($):
totta ? "sitten" $ "muu" > "sitten" Väärää ? "niin" $ "muu" > "muu"