Die bedingte Auswertung in C [] (Die bedingte Auswertung in C), Lektion, Seite 723250
https://www.purl.org/stefan_ram/pub/bedingte_auswertung_c (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C-Kurs

Der Wert  des ternären Ausdrucks in C 

Ein ternärer Ausdruck hat auch einen Wert. Es handelt sich um den Wert des zuletzt ausgewerteten Operanden.

Wir sehen jeden der beiden Werte »0« oder »0.0« als Null  an. Wir sagen auch, daß ein Wert ungleich Null ist, wenn er nicht gleich »0« oder »0.0« ist; der Wert eines Zeichenfolgenliterals ist immer  ungleich Null.

Auswertung eines ternären Ausdrucks
Bei der Auswertung eines ternären Ausdrucks wird zuerst der erste Operand  ausgewertet.
▶ Wenn der bei der Auswertung des ersten Operanden erhaltene Wert ungleich Null ist, dann  wird der zweite  Ausdruck ausgewertet, und der dritte Ausdruck wird nicht  ausgewertet, der Wert  des gesamten ternären Ausdrucks ist dann der Wert des zweiten  Operanden,
sonst  wird der dritte  Ausdruck ausgewertet, und der zweite Ausdruck wird nicht  ausgewertet, und der Wert  des gesamten ternären Ausdrucks ist der Wert des dritten  Operanden.

So ergibt sich als Wert des Ausdrucks »( 3 ? 4 : 5 )« der Wert »4«, denn da der Wert des ersten Ausdrucks der Wert »3« ist und dieser Wert ungleich  Null ist, ist der Wert des gesamten Ausdrucks der Wert des Operanden links vom  Doppelpunkt »:«, also »4«.

Als Wert des Ausdrucks »( 0 ? 1 : 2 )« ergibt sich der Wert »2«, denn da der Wert des ersten Ausdrucks der Wert »0« ist und dieser Wert nicht  ungleich Null ist, ist der Wert des gesamten Ausdrucks der Wert des Operanden rechts vom  Doppelpunkt »:«, also »2«.

main.c

#include <stdio.h>

int main( void )
{ printf( "%d\n", 3 ? 4 : 5 );
printf( "%d\n", 0 ? 1 : 2 ); }

stdout
4
2

Bezeichnungen für Teilausdrücke

Wir nennen die drei Operanden des ternären Ausdrucks entsprechend ihrer Bedeutung auch Bedingung, Konsequenz  und Alternative .

Der ternäre Ausdruck
    .-----------.     .-.     .------------.     .-.     .-------------.
--->| Bedingung |--->( ? )--->| Konsequenz |--->( : )--->| Alternative |--->
'-----------' '-' '------------' '-' '-------------'

Die Konsequenz und die Alternative werden zusammen auch als Zweige  des ternären Ausdrucks bezeichnet.

Wahrheitswerte und Wahrheitskontexte

Falls sich ein Ausdruck an einer Stelle eines Programms befindet, in der es nur darum geht, ob der Ausdruck ungleich Null ist, so wird diese Stelle auch als ein Wahrheitskontext  bezeichnet. Der erste Operand des ternären Operators befindet sich beispielsweise in einem Wahrheitskontext.

Man kann Werte ungleich Null in einem Wahrheitskontext als eine Repräsentation des Wahrheitswertes „wahr“ ansehen, und den Wert Null als eine Darstellung des Wahrheitswertes „falsch“. Wenn man einen Zahlenwert auf diese Weise interpretiert, so nennt man ihn auch einen Wahrheitswert.

Wir sagen auch, daß eine Bedingung erfüllt  sei, wenn sie ungleich Null ist. Mit den neuen Begriffen können die Regeln zur Auswertung eines ternären Ausdrucks etwas anschaulicher formuliert werden:

Auswertung eines ternären Ausdrucks
Bei der Auswertung eines ternären Ausdrucks wird zuerst die Bedingung  ausgewertet.
▶ Wenn die Bedingung  erfüllt ist, dann  wird die Konsequenz  ausgewertet, die Alternative wird nicht  ausgewertet, und der Wert  des gesamten ternären Ausdrucks ist der Wert der Konsequenz,
sonst  wird die Alternative  Ausdruck ausgewertet, der zweite Ausdruck wird nicht  ausgewertet, und der Wert  des gesamten ternären Ausdrucks ist der Wert der Alternative.

Symbolische Darstellung der Verzweigung
    .---------------.     .-.      .-.
--->| Bedingung |--->( ? )--->( : )
'---------------' '-' .'-'.
.' '.
.' '.
.' '.
.' '.
.-------------. .-------------.
| Konsequenz | | Alternative |
'-------------' '-------------'
Symbolische Darstellung der Verzweigung (für eine erfüllte Bedingung)
    .---------------.     .-.      .-.
--->| ungleich Null |--->( ? )--->( : )
'---------------' '-' .'-'
.'
.'
.'
.'
.-------------. .-------------.
| Konsequenz | | Alternative |
'-------------' '-------------'
Symbolische Darstellung der Verzweigung (für eine nicht erfüllte Bedingung)
    .---------------.     .-.      .-.
--->| Null |--->( ? )--->( : )
'---------------' '-' '-'.
'.
'.
'.
'.
.-------------. .-------------.
| Konsequenz | | Alternative |
'-------------' '-------------'

Beispiele

Beispiel Darstellung der Auswertungen

main.c

#include <stdio.h>

int vfalse(){ puts( "false" ); return 0; }
int vtrue(){ puts( "true" ); return 1; }

int v2(){ puts( "#2" ); return 2; }
int v3(){ puts( "#3" ); return 3; }
int v4(){ puts( "#4" ); return 4; }
int v5(){ puts( "#5" ); return 5; }

int main( void )
{ printf( "%d\n", vfalse() ? v2() : v3() );
printf( "%d\n", vtrue() ? v4() : v5() ); }

transcript
false
#3
3
true
#4
4

Beispiel Verhindern der Division durch Null

Das folgende Beispiel zeigt, wie eine Division durch Null zu einer Fehlermeldung führt

main.c

#include <stdio.h>

int tausendfacher_kehrwert( int const i ){ return 1000 / i; }

int main( void )
{ printf( "%d\n", tausendfacher_kehrwert( 2 ));
printf( "%d\n", tausendfacher_kehrwert( 0 )); }

Konsole
500
(Fehlermeldung)

Das folgende Beispiel zeigt, wie der ternäre Operator verwendet werden kann, um eine Division durch 0 zu vermeiden.

main.c

#include <stdio.h>

int tausendfacher_kehrwert( int const i ){ return i ? 1000 / i : 0; }

int main( void )
{ printf( "%d\n", tausendfacher_kehrwert( 2 ));
printf( "%d\n", tausendfacher_kehrwert( 0 )); }

stdout
500
0

Es ist nicht immer sinnvoll, wie oben, als Ergebnis für eine Division durch 0 die Zahl 0 festzulegen. Ob dies in einem bestimmten Fall sinnvoll ist, muß von Fall zu Fall entschieden werden.

Beispiel Verwendung mit Texten 

Das folgende Beispiel zeigt, wie Texte  als Operanden des ternären Operators verwendet werden können.

Dies erlaubt es uns erstmals, Zahlen in willkürliche Texte umzuwandeln.

main.c

#include <stdio.h>

char * deutsch( int const i ){ return i ? "Eins" : "Null"; }

int main( void )
{ puts( deutsch( 0 ));
puts( deutsch( 1 )); }

stdout
Null
Eins

Beispiel Verwendung mit Arithmetik

main.c

#include <stdio.h>

/** @brief Gibt aus, ob zwei int-Werte gleich sind.
@param x ein beliebiger int-Wert
@param y ein beliebiger int-Wert */

void pruefe_gleichheit( int const x, int const y )
{ printf
( "%d ist %sgleich %d.\n",
x,
y - x ? "nicht " : "",
y ); }

int main( void )
{ int x = 2;
int y = 3;
int z = 2;
pruefe_gleichheit( x, y );
pruefe_gleichheit( x, z ); }

stdout
2 ist nicht gleich 3.
2 ist gleich 2.

Beispiel Darstellung mathematischer Terme

In der Mathematik werden Funktionen machmal in einer Schreibweise mit einer großen geschweiften Klammer definiert. (Im folgenden soll „|=“ die Bedeutung „ungleich“ haben.)

Mathematische Schreibweise
          .-
|
| 4 , falls x |= 0,
f( x ):= <
| 2 sonst.
|
'-

In der Mathematik soll diese Schreibweise bedeuten, daß der Wert des Terms »f( x )« gleich »4« ist, wenn x ungleich Null ist, und gleich »3« sonst.

Mit Hilfe des ternären Ausdrucks kann diese mathematische Schreibweise nun relativ direkt in C  dargestellt werden.

C -Schreibweise
double f( double const x ){ return x ? 4 : 2; }

Beispiel Verwendung mit Prädikaten

Das folgende Programmbeispiel zeigt eine Verwendung des ternären Operators mit einem Prädikat. Ein Prädikat ist eine deterministische Funktion, deren Aufruf als Aussage  interpretiert wird. Der Aufruf »isalpha( c )« ist beispielsweise die Aussage, daß die Kennzahl »c« zu einem Buchstaben gehört.

Die Auswertung einer Aussage soll einen Wert ungleich Null ergeben, wenn die Aussage wahr ist, und Null sonst. Die Werte von Aussagen werden also als Wahrheitswerte interpretiert.

Prädikate und die erste Operandenstelle des ternären Operators sind wie für einander gemacht, denn ein Prädikat ergibt einen Wahrheitswert und die erste Operandenstelle des ternären Operators bildet einen Wahrheitskontext.

Das Prädikat »isalpha« ergibt, ob eine Kennzahl zu einem Buchstaben gehört, indem es nur dann einen Wert ungleich Null zurückgibt. Das folgende Programm stellt diese Information in deutscher Sprache dar.

main.c

#include <stdio.h>
#include <ctype.h>

void check( int const c )
{ printf
( "Das Zeichen '%c' ist %sein Buchstabe.\n",
c, isalpha( c )? "" : "k" ); }

int main( void )
{ check( 64 );
check( 65 ); }

stdout
Das Zeichen '@' ist kein Buchstabe.
Das Zeichen 'A' ist ein Buchstabe.

Beispiel Verschachtelung ternärer Operatoren

Das folgende Beispiel zeigt, wie zwei ternäre Operatoren ineinander verschachtelt  werden können.

Wir nehmen an, daß die Funktion »deutsch« nur für ein Argument mit Werten aus der Menge {0, 1, 2} gedacht ist.

main.c

#include <stdio.h>

char * deutsch( int const i )
{ return i ? i - 1 ? "Zwei" : "Eins" : "Null"; }

int main( void )
{ puts( deutsch( 0 ));
puts( deutsch( 1 ));
puts( deutsch( 2 )); }

stdout
Null
Eins
Zwei

Das folgende Programm zeigt eine Darstellung der Interpretation der obigen Verschachtelung mit Hilfe runder Klammern.

main.c

#include <stdio.h>

char * deutsch( int const i )
{ return i ?( i - 1 ? "Zwei" : "Eins" ): "Null"; }

int main( void )
{ puts( deutsch( 0 ));
puts( deutsch( 1 ));
puts( deutsch( 2 )); }

stdout
Null
Eins
Zwei

Das folgende Programm zeigt eine Darstellung der Interpretation des Ausdrucks »i ? i - 1 ? "Zwei" : "Eins" : "Null"« mit Hilfe von Funktionsaufrufen.

main.c

#include <stdio.h>

char * positiv( int const i )
{ return i - 1 ? "Zwei" : "Eins"; }

char * deutsch( int const i )
{ return i ? positiv( i ): "Null"; }

int main( void )
{ puts( deutsch( 0 ));
puts( deutsch( 1 ));
puts( deutsch( 2 )); }

stdout
Null
Eins
Zwei

Übungsfragen

?   Werte von Ausdrücken

Welchen Wert hat der Ausdruck »1 ? 3 : 4«?

Welchen Wert hat der Ausdruck »0 ? 12.2 : 9.1«?

Welchen Wert hat der Ausdruck »2 ? 3 : 4«?

Welchen Wert hat der Ausdruck »-12 ? "alpha" : "gamma"«?

Welchen Wert hat der Ausdruck »2 ? 0 ? 12.2 : 9.1 : 4«?

?   Gattung von Quelltexten

Welche der folgenden beiden Zeilen ist eine Anweisung?

putchar( 65 )

{}

Übungsaufgaben

/   Eine Wirkfunktion

Schreiben Sie eine Funktion »put_deutsch«, die für den Argumentwert »0« den Text »Null«, für den Argumentwert »1« den Text »Eins« und für den Argumentwert »2« den Text »Zwei« ausgibt. Verwenden Sie dabei die folgende Definition der Funktion »deutsch«, ohne diese Definition zu verändern. („Verwenden“ bedeutet so viel wie, die untenstehende Definition der Funktion »deutsch« zu kopieren und die Funktion »deutsch« dann aufzurufen.)

Die Definition der Funktion »deutsch«
char * deutsch( int const i )
{ return i ? i - 1 ? "Zwei" : "Eins" : "Null"; }

/   Eine Wirkfunktion (1)

Schreiben Sie eine Funktion »putl_deutsch«, die für den Argumentwert »0« die Zeile »Null«, für den Argumentwert »1« die Zeile »Eins« und für den Argumentwert »2« die Zeile »Zwei« ausgibt. Der Unterschied zur Funktion »put_deutsch« aus der vorigen Aufgabe besteht darin, daß dem ausgegebenen Wort nun ein Zeilenende folgen soll. Verwenden Sie in Ihrer Lösung die in der vorigen Übungsaufgabe geschriebene Definition der Funktion »put_deutsch«, ohne diese Definition zu verändern.

/   Eine willkürliche Funktion

Schreiben Sie eine Funktion, die 17 ergibt, falls ihr Argumentwert gleich 4 ist, und 12, falls ihr Argumentwert gleich 6 ist. Verwenden Sie dazu den ternären Operator.

/   Eine willkürliche Funktion (1)

Schreiben Sie eine Funktion, die den Text »alpha« für den Argumentwert 0 und den Text »gamma« für den Argumentwert 1 ergibt. Verwenden Sie dazu den ternären Operator.

/   Eine willkürliche Funktion (2)

Schreiben Sie eine Funktion, die den Text »alpha« für den Argumentwert 0, den Text »gamma« für den Argumentwert 1 und den Text »delta« für den Argumentwert 2 ergibt. Verwenden Sie dazu den ternären Operator.

/   Eine willkürliche Funktion (3)

Schreiben Sie eine Funktion, die den Text »3 Punkte« ausgibt, wenn sie mit einem Argumentwert von »3« aufgerufen wird; »2 Punkte«, wenn sie mit einem Argumentwert von »2« aufgerufen wird; »1 Punkt«, wenn sie mit einem Argumentwert von »1« aufgerufen wird; und »0 Punkte«, wenn sie mit einem Argumentwert von »0« aufgerufen wird

/   Normalisierung

Wir sagen, daß eine Funktion »f« einen Wert »x« „auf einen Wert »y« abbildet“, wenn die Funktion deterministisch ist und der Wert des Ausdrucks »f( v )« gleich »y« ist, wann immer der Wert des Ausdrucks »v« gleich »x« ist. Beispielsweise bildet die Funktion »sqrt« den Wert‑»4« auf den Wert‑»2« ab.

Definieren Sie eine Funktion, welche den Wert »0« auf den Wert »0« und alle anderen Werte auf den Wert »1« abbildet.

/   Verneinung

Definieren Sie eine Funktion, welche den Wert »0« auf den Wert »1« und alle anderen Werte auf den Wert »0« abbildet.

/   Und-Verknüpfung

Definieren Sie eine Funktion, die den Wert »1« ergibt, wenn beide Argumente ungleich Null sind, und den Wert »0« sonst.

/   Oder-Verknüpfung

Definieren Sie eine Funktion, die den Wert »0« ergibt, wenn beide Argumente gleich Null sind, und den Wert »1« sonst.

/   Exklusive oder-Verknüpfung

Definieren Sie eine Funktion, die den Wert »1« ergibt, wenn beide Argumente einander ungleich sind, und den Wert »0« sonst. Hierfür kann angenommen werden, daß als Argumentwerte nur der Wert »0« und der Wert »1« vorkommen.

/   Gleichheit

Definieren Sie eine Funktion, die den Wert »1« ergibt, wenn beide Argumente einander gleich sind, und den Wert »0« sonst. Hierfür kann angenommen werden, daß als Argumentwerte nur der Wert »0« und der Wert »1« vorkommen.

Zusatzanforderung: Schreiben Sie die Funktion so, daß sie auch für alle anderen Werte (deren Betrag kleiner als »10000« ist) das richtige Ergebnis liefert.

/   Negativ *

Definieren Sie eine Funktion, die den Wert »1« ergibt, wenn ihr Argument negativ ist (ohne bisher noch nicht behandelte Operatoren zu verwenden). (Es ist nicht sicher, ob das möglich ist.)

/   Kleiner *

Definieren Sie eine Funktion, die den Wert »1« ergibt, wenn das erste Argument kleiner ist als das zweite (ohne bisher noch nicht behandelte Operatoren zu verwenden). (Es ist nicht sicher, ob das möglich ist.)

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram723250 stefan_ram:723250 Die bedingte Auswertung in C Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd723250, slrprddef723250, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/bedingte_auswertung_c