====== Werte verarbeiten ====== * Werte und Ausdrücke auf den Bildschirm ausgeben * Werte merken * Wie merkt sich ein Computer Werte? ===== Werte und Ausdrücke auf den Bildschirm ausgeben ===== Nachdem wir in der [[c:tutorial:expression|letzten Lektion]] eher theoretisch betrachtet haben, wie man Werte und Datentypen unterscheidet, wollen wir in dieser Lektion wieder etwas praktischer am Computer arbeiten. Wir kennen bisher nur die Funktion [[c:lib:stdio:printf()]] und wissen, wie man einfache Ausdrücke formulieren kann. Weiterhin können wir Werte und Datentypen unterscheiden. Die Funktion [[c:lib:stdio:printf()]] erlaubt uns Werte auszugeben, aber wir müssen ihr mitteilen, wie sie diese Werte interpretieren soll, schließlich sind für den Computer alles nur Zahlen. Nach unserem Kenntnisstand unterscheiden wir derzeit zwischen den Datentypen Ganzzahl ([[c:type:int]]) und Fließzahl ([[c:type:float]], [[c:type:double]]). Unser bisheriges Beispielprogramm gab den Text "Hello proggen.org" aus ((das ist auch ein Wert eines Datentyp, aber um diesen kümmern wir uns später ausführlich)): printf( "Hello proggen.org\n" ); In diesen Text kann man [[c:lib:stdio:formatstring|Sonderzeichen]] einfügen, an diese Stelle werden dann Werte eingefügt. Für Integer fügt man ein ''%d'' (wie Dezimalzahl) ein, für Floats ein ''%f''. Anschließend führt man den Wert, der eingefügt werden soll, durch ein Komma getrennt hinter dem Text auf: #include int main( void ) { printf( "4 + 3 ist %d\n", 4+3 ); printf( "4.0 + 3.0 ist %f\n", 4.0f+3.0f ); return 0; } Dabei lassen sich beliebig viele Ausgaben einfügen: printf( "%d + %d ist %d\n", 4, 3, 4+3 ); printf( "%f + %f ist %f\n", 4.0f, 3.0f, 4.0f+3.0f ); Auch einzelne Buchstaben lassen sich so mit dem Sonderzeichen ''%c'' (wie Character) ausgeben: printf( "Der ASCII-Code %d entspricht dem Zeichen '%c'\n", 48, 48 ); Die erste 48 wird für ''%d'' eingesetzt, die dahinterstehende wird für ''%c'' eingesetzt. Bei ''%d'' wird sie als Dezimalzahl interpretiert und ausgegeben, bei ''%c'' wird die 48 stattdessen als [[theory:encoding:ascii|ASCII-Zeichen]] interpretiert und entsprechend eine '0' ausgegeben. Das ganze funktioniert auch umgekehrt: printf( "Das Zeichen '%c' besitzt den ASCII-Code %d\n", 48, 48 ); printf( "Das Zeichen '%c' besitzt den ASCII-Code %d\n", '0', '0' ); Hier wird die gleiche Zeile nun zweimal ausgegeben. Der Wert von '0' ist 48, man sieht, wie wichtig der Datentyp ist, denn er bestimmt, wie 48 interpretiert wird. Möchte man übrigens ein Prozentzeichen einfügen, so verwendet man zwei Prozentzeichen: ''%%''. ===== Werte merken ===== Wenn wir den Computer Aufgaben wie 4+3 lösen lassen, so lösen wir nur dieses absolute und unveränderliche Problem (eben 4+3). Computer sollen jedoch meistens Probleme lösen, die sich in einer Rechenvorschrift beschreiben lassen, einem sogenannten Algorithmus. Man möchte die Zahlen auswechseln können, um auch andere Aufgaben rechnen zu können. Hierfür benötigen wir einen [[glossary:identifier|Identifikator]] ("Identifier") für Werte, ohne zu wissen, welchen Wert des [[glossary:Identifier]] hat - wie in der Mathematik, wo Werte durch Buchstaben gekennzeichnet werden. s = a + b Genauso machen wir es beim Programmieren. Die Buchstaben sind die Identifier, zusätzlich müssen wir dem Computer jedoch sagen, um welchen Datentyp es sich handelt, also wie der Identifier die Daten verarbeiten soll. Schauen wir uns an, wir man sich in C eine Zahl merkt und sie anschließend auf dem Bildschirm ausgibt. #include int main( void ) { int natuerlicheZahl = 4711; // Neuen Variable bekanntgeben // und gleich initialisieren float reelleZahl; // Variable bekanntgeben // ohne einen Wert zuzuweisen reelleZahl = 3.1415f; // Variable einen neuen Wert zuweisen printf( "Ich habe mir folgende Zahlen gemerkt: \n" ); printf( "natürliche Zahl: %d\n", natuerlicheZahl ); printf( " reelle Zahl: %f\n", reelleZahl ); return 0; } Wir sehen, dass die Definition von ''natuerlicheZahl'' fast aussieht, wie die Definition von ''main'', lediglich die runden Klammern fehlen. Die zeigen den Unterschied zwischen ''natuerlicheZahl'' und ''main'' auf: ''natuerlicheZahl'' merkt sich einfach einen Wert entsprechend des vorangestellten Datentyps, den es auf Anfrage zurückliefert. ''main'' als Funktion muss erst seine Funktion ausführen, bevor es einen Wert zurück liefern kann. Auf ''natuerlicheZahl'' wird stattdessen mit dem '='-Operator ein Wert zugewiesen, den der [[glossary:Identifier]] ab jetzt haben soll. Diese erstmalige Zuweisung eines Wertes nennt man Initialisierung. Die Initialisierung sorgt dafür, dass ''natuerlicheZahl'' einen definierten Wert besitzt. C selbst kümmert sich darum nämlich nicht (es weiß ja auch nicht, welcher Wert für uns sinnvoll ist) und so ist ''reeleZahl'' einen kurzen Moment bis zur Zuweisung in einem undefinierten Zustand. Wir wissen einfach nicht, welchen Wert ''reelle Zahl'' besitzt, bis wir erstmals ("initial") einen Wert zugewiesen haben. Hier sehen wir einen kleinen Unterschied von C zur Mathematik: Während die Identifikatoren in der Mathematik einen festen, unveränderlichen Wert besitzen, der anhand der Aufgabe zu bestimmen ist, sieht man das bei vielen Programmiersprachen etwas lockerer: Hier können [[glossary:Identifier]] für einen späteren Zweck überschrieben werden oder zum Zählen verwendet werden. Der Wert von ''natuerlicheZahl'' ist also nicht konstant, sondern variabel. Daher nennt man solche veränderlichen Identifikatoren auch **Variablen**. Die unnatürliche Schreibweise (ue statt ü) von ''natuerlicheZahl'' hat zwei einfache Gründe: Zunächst sind Leerzeichen innerhalb von [[glossary:Identifiern]] (also unabhängig davon, ob man eine Funktion oder eine Variable benennt) nicht erlaubt. Gleiches gilt für Umlaute (ä, ü, ö) oder dem 'scharfen S' (ß). [[glossary:Identifier]] müssen mit einem Buchstaben oder Unterstrich ('_') beginnen. Diesem ersten Zeichen dürfen weitere Buchstaben und Unterstriche folgen, sowie auch Zahlen. Es dürfen große und kleine Buchstaben verwendet werden. Der Unterstrich zu Beginn darf aber nur von den Compiler-Herstellern verwendet werden. **Gültige [[glossary:Identifier]]-Namen:** a b _a zahl index Summand1 Summand2 ein_ganz_langer_name einGanzLangerName **Ungültige [[glossary:Identifier]]-Namen:** 1ZweiDrei // beginnt mit einer Zahl natürlicheZahl // ungültiges Zeichen: ü nicht erlaubter Name // Leerzeichen enthalten, wird als // drei Identifikatoren verstanden. Eine Variable oder eine Funktion steht immer für einen beliebigen Wert, entsprechend seines Datentyps. Die Variable ''natuerlicheZahl'' besitzt also immer einen Integer-Wert, wie die ''reelleZahl'' immer einen reellen Wert besitzt. Der Funktion ''printf()'' darf man Werte geben, die entsprechend des [[c:lib:stdio:formatstring|Formatstrings]] interpretiert wird. Dabei spielt es keine Rolle, ob dieser Wert direkt angeben wurde, durch eine Variable zurückgegeben wird oder durch einen Ausdruck entstanden ist: #include int main( void ) { int natuerlicheZahl = 4711; /* Ausgabe als direkte Angabe, aus Variable oder Ausdruck */ printf( "Fester Wert: %d\n", 1234 ); printf( "Variable : %d\n", natuerlicheZahl ); printf( "Ausdruck : %d\n", 17 + 4 ); /* Neuzuweisen einer Variablen */ natuerlicheZahl = 17 + 4; printf( "Variable(1): %d\n", natuerlicheZahl ); /* Aufaddieren */ natuerlicheZahl = natuerlicheZahl + 5; printf( "Variable(2): %d\n", natuerlicheZahl ); return 0; } Die Variable ''natuerlicheZahl'' wird im Verlauf des Programms überschrieben mit dem Wert ''17+4'': natuerlicheZahl = 17 + 4; printf( "Variable(1): %d\n", natuerlicheZahl ); Dabei wird der Ausdruck erst ausgerechnet (21) und der ausgerechnete Wert anschließend der Variablen ''natuerlicheZahl'' zugewiesen. Weder kann man mit der Variablen herausfinden, dass der Wert über einen Ausdruck entstanden ist, noch kommt man an den alten Wert 4711 jemals wieder heran. Sie steht nun einfach für den Wert 21. Das sieht man noch deutlicher, an der Stelle, an der die Variable erneut überschrieben wird: natuerlicheZahl = natuerlicheZahl + 5; printf( "Variable(2): %d\n", natuerlicheZahl ); Hier wird erst der Ausdruck (''natuerlicheZahl + 5'') ausgewertet, wobei ''natuerlicheZahl'' den zuvor zugewiesenen Wert 21 besitzt. Der Ausdruck besitzt den Wert 21+5, also 26. Dieser Wert wird anschließend wieder ''natuerlicheZahl'' zugewiesen, also wird ''natuerlicheZahl'' nach dem Ausrechnen mit 26 überschrieben. \\ Übrigens: Auch ''natuerlicheZahl = 26'' ist ein Ausdruck, die Zuweisung gibt nämlich das Ergebnis zurück, das zugewiesen wurde. Damit lassen sich zum Beispiel mehrere Variablen in einem großen Ausdruck überschreiben: int a, b, c; a = b = c = 0; Die '='-Operation läuft von rechts nach links ab: Erst wird rechts ausgewertet (Wert 0), dann links (c =). c wird also überschrieben und das Ergebnis (also 0) zurückgegeben. Das Ergebnis von (c = 0) ist der rechte Teil von ''b = ...''. Wichtig ist das Verständnis, dass Ausdrücke immer weiter verknüpft werden können. Später im Tutorial werden wir auch noch Funktionen verwenden, die ja ebenfalls Werte zurückgeben können. ===== Ziel dieser Lektion ===== Du solltest nun in der Lage sein, einfache Aufgaben mit Variablen berechnen zu können und Dir das Ergebnis anzeigen zu lassen. Definiere zwei Variablen a und b und weise ihnen Werte zu. Berechne dann die Summe von a zum Quadrat und b zum Quadrat und lass Dir das Ergebnis auf dem Bildschirm ausgeben. Beginne damit, das Ergebnis erst in einer Variablen c zwischen zu speichern und optimiere dann die Variable c aus dem Programm hinaus, in dem du die den Ausdruck, um c zu bestimmen, direkt in die printf-Anweisung überträgst. Eine schöne Übung ist einen Budgetplaner zu schreiben. Berechne Deine monatlichen Einnahmen und monatlichen Ausgaben und ziehe Dein Gehalt davon ab. Multipliziere das Ergebnis mit 12. Addiere jährliche Einnahmen (Steuerrückzahlung, Weihnachtsgeld) und subtrahiere jährliche Kosten (Versicherung, KFZ-Steuer). In der [[c:tutorial:decisions|kommenden Lektion]] werden wir lernen Entscheidungen zu treffen.