Ternær betinget operation (fra latin ternarius - "tredobbelt") er en operation implementeret i mange programmeringssprog, der returnerer sin anden eller tredje operand afhængigt af værdien af det logiske udtryk givet af den første operand. En analog til den ternære betingede operation i matematisk logik og boolsk algebra er den betingede disjunktion , som er skrevet i formen og implementerer algoritmen: "hvis , så ellers ".
Typisk er den ternære betingede operator forbundet med den operator, der ?:bruges i C-lignende programmeringssprog. Faktisk findes lignende operationer med en anden syntaks i mange programmeringssprog, der er langt fra C i syntaks . Populære sprog, der har den ternære betingede operator indbygget i deres syntaks, er C , C++ , JavaScript , Objective-C , C# , D , Java , ECMAScript , Perl , PHP , Python , Tcl , Ruby , Verilog, Turbo Basic . Denne operation skylder sin optræden direkte i den ternære infiksform til Algol-60- sproget , hvor det havde en syntaks , og derefter til BCPL -sproget ( ) [1] i stedet for det nu velkendte . Prototypen af denne operation er til gengæld en betinget funktion af Lisp-sproget , skrevet i henhold til reglerne i Lisp i præfiksform og har et vilkårligt antal argumenter. if o1 then o2 else o3o1 -> o2, o3o1 ? o2 : o3cond
Normalt omfatter implementeringen af operationen beregningen af betingelsen og kun et af udtrykkene, hvilket i nogle tilfælde giver udvidede muligheder, for eksempel anses udtrykket x > 0 ? 0 : sqrt(x)for at være korrekt, på trods af at roden ikke er taget fra negative tal.
Minimum af tallene a og b:
min = (a < b) ? a : bKan bruges i en ikke-opgavesituation:
sprintf ( titel , "%s %s" , tv_system == TV_PAL ? PAL : SECAM , tv_indgang ? Tv_Name [ tv_input - 1 ] : "PRØVE" );- i dette tilfælde ville den ækvivalente konstruktion ved hjælp af if-then-else kræve, at funktionskaldet skrives sprintffire gange.
Basic C har ikke en boolesk datatype ( C99 introducerede den booleske _Bool-type), så den første operand skal være et tal ( heltal eller reelt ) eller en pointer [2] ; først beregnes dens værdi og sammenlignes med nul , og hvis den ikke er lig med nul, beregnes den anden operand og returneres, i tilfælde af lighed - den tredje. Den anden og tredje operand kan være af forskellige typer (inklusive void ).
I C++ har den ternære betingede operator samme syntaks som i C [3] , men på grund af forskellen mellem initialisering og tildeling er der situationer, hvor operationen ?:ikke kan erstattes af en konstruktion if-then-else, som for eksempel i det følgende sag:
#include <iostream> #include <fstream> #inkluder <streng> bruger navneområde std ; int main ( int argc , char ** argv ) { strengnavn ; _ udstrøms fout ; if ( argc > 1 && argv [ 1 ]) { navn = argv [ 1 ]; fout . åben ( navn.c_str ( ), ios :: ud | ios :: app ) ; } ostream & sout = navn . tom () ? cout : fout ; returnere 0 ; }Her initialiseres variablen sout i det øjeblik, resultatet af den ternære operation erklæres. En lignende effekt kunne ikke opnås ved en simpel opgave i det ene eller det andet tilfælde.
Derudover kan den ternære betingede operator anvendes i venstre side af en tildelingserklæring:
#include <iostream> int main () { int a = 0 , b = 0 ; const bool cond = ...; ( kond a : b ) = 1 ; _ std :: cout << "a=" << a << ',' << "b=" << b << '\n' ; }I dette eksempel, hvis den boolske variabel cond på linje 5 indeholder værdien sand, vil værdien 1 blive tildelt variabel a, ellers vil den blive tildelt variabel b.
I C# har den ternære operatør yderligere begrænsninger relateret til typesikkerhed. Udtryk 1 og 2 skal være af samme type. Dette resulterer i følgende:
int a = 1 ; dobbelt b = 0,0 ; int nMax = ( a > b ) ? a : b ;En sådan kildekode vil ikke kompilere på trods af, at nMax ender med at blive en . Da a og b skal være af samme type, vil a blive rykket op til dobbelt for at matche b . Typen af den resulterende værdi af den ternære operation er dobbelt, og denne type skal nedkastes til int ved tildeling: [4]
int a = 1 ; dobbelt b = 0,0 ; int nMax ; // Du kan gøre dette: nMax = ( int ) (( a > b ) ? a : b ) ; // ...eller så nMax = ( a > b ) ? a : ( int ) b ;Python bruger søgeordssyntaksif-else :
a = 42 b = 41 resultat = a hvis a > b andet b hævde resultat == 42Det kan også implementeres via en liste:
[ < udtryk 1 > , < udtryk 2 > ][ < betingelse > ]- resultatet af udtryk 1 vil blive returneret, hvis betingelsen er falsk; og udtryk 2, hvis betingelsen er sand. Hvis betingelsen ikke er et boolesk udtryk, er det muligt at overløbe listen med en undtagelse.
PHP bruger en C -lignende syntaks:
$a = $b == 1 ? "første værdi" : ( $b == 2 ? "anden værdi" : ( $b == 3 ? "resultatværdi" : "standardværdi" ));Den ternære operator i PHP svarer til den længere if-else-konstruktion. Følgende to eksempler er ækvivalente:
//Første eksempel $result = isset ( $a ) ? $a : 'DefaultValue' ; //Andet eksempel if ( isset ( $a )) { $result = $a ; } else { $result = 'DefaultValue' ; }Sådanne konstruktioner bruges ofte til at initialisere en variabel alligevel til efterfølgende beregninger (ellers vil PHP afgive en E_NOTICE-niveaufejl).
Fra version 5.3 blev det muligt ikke at angive den anden parameter for operationen. For eksempel er følgende to poster ækvivalente:
$Variable = $_GET [ 'Parameter' ] ? $_GET [ 'Parameter' ] : 'DefaultValue' ; $Variable = $_GET [ 'Parameter' ] ?: 'DefaultValue' ;I den klassiske version af Visual Basic eksisterer den ternære operator som en funktion IIf(Expr, TruePart, FalsePart). Denne funktion har en funktion: når udtrykket evalueres Expr, vil det også blive beregnet TruePartog FalsePart, uanset resultatet af udtrykket: sandt eller falsk. Dette kan føre til uventede resultater og nogle gange til langsom kodeudførelse, hvis returværdierne er opkald til funktioner med lange operationer.
Dim iCount As Long Offentlig underhoved ( ) iCount = 1 MsgBox IIf ( 1 = 1 , FuncYes , FuncNo ) 'Variablen iCount vil indeholde "3" fordi begge funktioner vil blive udført MsgBox iCount End Sub Offentlig funktion FuncYes () Som streng iCount = iCount + 1 FuncYes = "Ja " Slutfunktion Offentlig funktion FuncNo () Som streng iCount = iCount + 1 FuncNo = "Nej " SlutfunktionFor at erstatte en funktion IIf, kan du omskrive udtrykket i én linje, men dette vil ikke være en analog af funktionen, men vil kun være en kort form af grenoperatoren
If Expr Then TruePart Else FalsePartMed fremkomsten af VB.NET blev den velkendte ternære operator inkluderet i sprogets syntaks og er skrevet som If(Expr, TruePart, FalsePart). Denne operatør bruger reducerede beregninger i modsætning til funktionen IIf, som også er tilgængelig for udvikleren for kompatibilitet med tidligere versioner. [5]
I konfigurationssproget på 1C:Enterprise-platformen har den ternære operatør syntaksen:
?(boolesk udtryk, udtryk 1, udtryk 2)Udbredt som en stenografi for konstruktioner Если <логическое выражение> Тогда ... Иначе ... КонецЕсли
I platformversion 7.7 var det muligt at bruge en ternær operatør på højre side af en tildelingsoperatør [6] .
I Haskell er if-grenoperatoren et betinget udtryk: else-udtrykket er påkrævet og skal være af samme type som det daværende udtryk. Også i standardbiblioteket Data.Bool [7] er der en bool-funktion, der returnerer et af to udtryk afhængigt af prædikatets værdi.
En ternær operation i sin sædvanlige form kan defineres som en infix-funktion via mønstermatchning (typer er valgfri):
( ? ) :: Bool -> a -> a -> a ( ? ) Sandt a _ = a ( ? ) Falsk _ b = beller gennem enhver forgreningsoperation, såsom hvis eller tilfælde af:
( ? ) prædikat thenExpr elseExpr = hvis prædikat så thenExpr elseExpr _ ( ? ) prædikat thenExpr elseExpr = kasusprædikat af { True - > thenExpr ; _ -> andetUdtryk }Da (?) er en infix (binær) funktion, tager den de første 2 argumenter og returnerer en funktion af et argument. For at anvende det på det tredje argument, bruges applikationen ($):
sandt ? "så" $ "andet" > "så" Falsk ? "så" $ "andet" > "andet"