C Kurs - if I was a rich man,
düdeldüdeldüdeldideldum
Bis jetzt haben Sie gelernt was eine Variable ist und welche Typen
von Variablen es gibt und wie man Variablen deklariert und wie man sie verändert.
In diesem Kapitel geht es darum sie zu vergleichen. Es gibt in C drei verschiedene
conditional statements nämlich if, den ? Operator
und switch. In diesem Kapitel wird die if
Abfrage behandelt, ? und switch kommt im nächsten.
1. if Abfragen
allgemein
If Abfragen funktionieren folgendermaßen:
if(Abfrage)
Anweisung1
else
Anweisung2
Jetzt mal ausführlich, man stellt eine Frage, z.B.
if(x > 42), ist die Antwort ja, dann wird
Anweisung1 ausgeführt, wenn nicht dann erstaunlicher Weise der else
Teil mit Anweisung2. Sind mehrere Anweisungen auszuführen, bildet man einen
Block mit geschweiften Klammern:
if(Abfrage)
{
Anweisung1
Anweisung2
Anweisung3
}
else
{
Anweisung4;
Anweisung5;
}
Der Teil mit else, also die Behandlung der nicht
wahren if Abfrage, ist natürlich optional:
if(Abfrage)
Anweisung1;
Anweisung2; // keine else Teil
Hier jetzt mal ein kleines Beispielprogramm:
#include
<stdio.h>
int main(void)
{
int magic = 42;
int guess;
printf("Finde
die magische Zahl:\n");
scanf("%d", &guess); // einlesen
über die Tastatur, wird später erklärt
if(guess == magic) // == sind zwei hintereinander
stehende Gleichheitszeichen
{
printf("OK, Du hast es!\n");
}
else
{
if(guess < magic)
{
printf("zu klein\n";
}
if(guess > magic)
printf("zu groß\n";
}
return 0;
}
Einrückungen und neue Zeilen sind auch optional, erhöhen
die Lesbarkeit des Codes immens. Einige Programmierer bezweifeln dass, etwa
mit dem bewußten oder unbewußten Argument: bei meinem IQ kann ich
es mir leisten, sloppy formatierten Code zu schreiben, ich blick da schon noch
durch. Ich weiß auch nicht, aber die guten Programmierer liefern immer
sauber bis penibel formatierte Programme ab. Also als Tip, gewöhnen Sie
gleich an, Ihre Programme mit Leerzeichen, Einrückungen und Zeilenumbrüchen
möglichst einheitlich und gut lesbar zu gestalten. Man kann das Programm
auch in eine 2 Zeilen quetschen:
int main(void){int
magic = 42;int guess;printf("Finde die magische Zahl:\n");scanf("%d",
&guess);
if(guess = = magic){printf("Du
hast es!\n");}else{if(guess
< magic){printf("zu
klein\n";}else{printf("zu
groß\n";}}}
Dem C Compiler ist dass egal, er ist ja schließlich nur
ein Computerprogramm, aber wenn ein Mensch das bearbeiten soll... Es gibt jedes
Jahr einen internationalen Wettbewerb für das unverständlichste C
Programm "The International Obfuscated
C Code Contest", wenn Sie meinen auf Neuzeilen und Einrückungen
verzichten zu können, dann machen Sie dort doch mal mit.
2. Vergleichsoperatoren
Einige Vergleiche hatten wir in dem Beispiel schon gesehen:
den Vergleich auf Gleichheit: == (zwei hintereinander stehende
Gleichheitszeichen) Dieser Vergleich ergibt wahr, wenn beide Seiten gleich
sind. Einige Beispiele:
if(x == y) ...// wenn x gleich y ...
if(z + 100 == 666) ... // wenn z + 100 gleich 666 ...
if(c == 'A') ... // wenn c gleich 'A'
if(hansi) ... // wenn hansi nicht Null ist ergibt es wahr,
wenn hansi Null ist falsch
if(! hansi) ... // wenn hansi falsch( Null) ist, dann ergibt
nicht hansi, ! hansi, wahr -> if wird ausgeführt
//
ist hansi wahr dann ergibt nicht hansi falsch -> else wird ausgeführt
if(var == MyFunction(a, 68) ) // hier wird var mit dem
Rückgabewert der Funktion MyFunction verglichen
if( AnotherFunction() ) ... // Hier wird nur abgefragt,
ob der Rückgabewert der Funktion AnotherFunction nicht Null ist.
Ein sehr populärer Fehler von C Anfängern ist folgender,
statt:
if(x == y)
schreibt man gerne versehentlich:
if(x = y) // nur ein Gleichheitszeichen
der Compiler interpretiert dies als Zuweisung, so steht es ja
auch da, es wird also erst x = y; ausgeführt, dann wird
geguckt ob x denn nicht Null ist, in diesem Fall ergibt die Abfrage wahr,
oder x ist Null dann ergibt die Abfrage falsch. Meistens ist dies nicht das,
was Sie eigentlich tun wollten, deshalb gibt es auch bei den meisten C Compilern
eine Warnung beim kompilieren. Wenn es sich um den Vergleich einer Variablen mit einer Zahl handelt, kann man sich folgenden kleinen Trick angewöhnen:
statt if(x == 1)
schreibt man if(1 == x) das gibt auf jeden Fall eine Fehlermeldung vom Compiler, wenn man nur ein Gleichheitszeichen tippt.
Eine weitere Falle ist der Vergleich
von reellen Zahlen, kompilieren Sie doch bitte mal folgendes Programm:
#include<stdio.h>
#include<stdlib.h>
void main(void)
{
if(18.61 + 2.01 == 20.62)
printf("Alles OK\n");
else
printf("Hier ist was faul, im Staate
Dänemark\n");
}
und raten Sie mal welche Meldung angezeigt wird? Genau, hier ist was faul...
Warum eigentlich - 18.61 + 2.01 ist doch gleich 20.62 ??? Nun, das ganze hängt
damit zusammen, dass reelle Zahlen von C Compilern in der Form Mantisse -
Exponent gespeichert werden.18.61 + 2.01 ergibt bei meinem Compiler 20.620000839233,
das ist zwar fast 20.62 aber leider nicht ganz genau gleich. Beim Vergleich
reller Zahlen, egal ob sie vom Typ float, double oder long double sind, muß
man deshalb immer auf Gleichheit innerhalb eines sehr kleinen Intevalles,
meist epsilon genannt, prüfen, hier ein Beispiel:
#include<stdio.h>
#include<stdlib.h>
void main(void)
{
float epsi;
epsi = 10e-18; // sehr kleiner Wert
if( abs(18.61 + 2.01 - 20.62) < epsi )
printf("Alles OK\n");
else
printf("Hier ist immer noch was faul\n");
}
Jetzt sollte "Alles OK" als Antwort kommen. Die Funktion
abs ist in der StandardLibrary stdlib.h
definiert, sie gibt den Absolutwert der Eingabe zurück z.B. bei abs(-1)
wird 1 zurückgegeben. Dies ist nötig, da niemand voraussehen kann
ob 8.61 + 2.01 = 20.620000839233 ergibt oder etwa 8.61 + 2.01 = 20.6199999993472
Außer == gibt es noch folgende andere Vergleiche die genauso
funktionieren, deshalb nur in Kürze:
if(a < b) ... // wenn a kleiner b ist dann
...
if(a > b) ... // wenn a größer b ist dann ...
if(a <= b) ... // wenn a kleiner oder gleich b ist dann
...
if(a >= b) ... // wenn a größer oder gleich
b ist dann ...
if(a != b) ... // wenn a ungleich b ist dann ...
3. komplexe Abfragen
Die Abfrage kann mit den im vorigen Kapitel beschriebenen logischen
Operatoren && - AND, || - OR und !
- NOT beliebig komplex gestaltet werden. Hier mal ein Beispiel über mehrere
Zeilen, wie man sieht stören Zeilenumbrüche nicht:
if( ( (a == b) && (a > 0) ) ||
( (a == c) && (a > 42) ) ||
( (a == 42) && (b && c) ) )
{
Anweisung;
}
Dies bedeutet
wenn a gleich b ist und a größer Null ist oder
wenn a gleich c ist und a größer 42 ist oder
a gleich 42 ist und sowohl b als auch c nicht Null sind, dann führe Anweisung
aus.
3.
verschachtelte Abfragen
If Abfragen können natürlich auch veschachtelt
sein. Hiermit ist gemeint, daß if Abfragen weitere if
Abfragen enthalten dürfen. Das nennt man dann eine if - else Leiter.
Hier ein Beispiel:
if(a && x)
if(b > 42)
if(c == 'X')
var1 = 666;
else
if(! c)
var2 = 666;
else
var1 = 999;
Hier sieht man auch wie sinnvoll es ist,seinen Kode durch Einrückungen
und Neuzeilen gut lesbar zu formatieren, sonst überlegt man ständig,
bei welcher if Abfrage man eigentlich ist. Die selbe if
Abfrage wird durch das einfügen geschweifter Klammer noch mal klarer, obwohl
sie nicht zwingend sind:
if(a && x)
{
if(b > 42)
{
if(c == 'X')
{
var1 = 666;
}
else
{
if(! c)
var2
= 666;
else
var1
= 999;
} //if(c == 'X') else ...
} // if(b > 42)
} // if(a && x)
Ja welche else gehört eigentlich zu welchem
if? Die Antwort ist: immer zum nächstdrüberliegenden.
Bei diesem bewusst schlecht formatierten Beispiel gehört der else
Abzweig zu der darüberliegende if Abfrage, if(b)... :
if(a)
if(b)
Anweisung1;
else
Anweisung2;
Will man das ändern, muß man geschweifte Klammern einsetzen.
Jetzt bezieht sich else auf das obere if,
if(a) ... :
if(a)
{
if(b)
Anweisung1;
}
else
Anweisung2;
|