D-Programmierung: Konstanten Variablen

Aus Wikibooks

Konstanten und Variablen[Bearbeiten]

Zuerst erkläre ich in diesem Kapitel was Konstanten und Variablen sind. Und da beide viele gemeinsame Eigenschaften haben, werde ich diese auch wenn möglich an einer Stelle erklären.

Als nächstes lernen Sie, wie man mit D rechnen kann und außerdem weitere Möglichkeiten etwas auf dem Bildschirm anzuzeigen.

Konstanten[Bearbeiten]

Konstanten sind Ihnen sicherlich schon aus der Schulzeit bekannt. Das waren Zahlen, die immer gleich waren und deswegen eine besondere Bedeutung hatten. Die Kreiszahl π ist beispielsweise so eine Konstante. In Programmierer-Kreisen muss eine Konstante nicht unbedingt eine Zahl sein. Es kann auch eine Zeichenkette sein, wie das "Hello World" aus meinem ersten Beispiel. Natürlich können Sie den Text ins Deutsche übersetzten und ihn dann hinschreiben. Das ändert aber nichts an der Tatsache, dass es eine Konstante ist. Denn Du bearbeitest den Quelltext. Sie können aber keinen Befehl schreiben um diesen Ausruf vom Programm aus zu manipulieren.

Im Allgemeinen gibt es zwei Typen von Konstanten:

  1. Unbenannte Konstanten
  2. Benannte Konstanten

Unbenannt sind die, die keinen Namen haben. Der String "Hello World" aus deinem ersten D-Programm ist so eine unbenannte Konstante. Der passende Fachausdruck ist Literal.

Im Gegensatz dazu haben benannte Konstanten einen Namen; π wäre solch eine Konstante. Natürlich kann man aber die Zahl π durch deren Namen nicht ohne weiteres im Quelltext verwenden. Die Regel ist, dass alles was in D einen Namen hat, muss irgendwo auf einen Inhalt gesetzt werden.

Anmerkung: Ab jetzt werde ich benannte Konstanten einfach Konstanten nennen. Unbenannte Konstanten aber Literale.

Literale[Bearbeiten]

Das Stringliteral haben Sie schon verwendet, wahrscheinlich ohne dass es Ihnen bewusst war. Nämlich als Sie Text in die Konsole geschrieben haben. Diese wurden durch doppelte Anführungsstriche eingegrenzt. Es gibt aber noch mehr Arten von Literalen. Hier stelle ich nur ein paar vor. Die anderen finden Sie am Ende dieses Kapitels, in der Übersicht.

Zahlen[Bearbeiten]

Zahlen können Sie wie gewohnt schreiben. Zum Beispiel: 123 432 1 0 -13

Der einzige Unterschied ist, dass die Nachkommastellen, wie im Englischen, durch einen Punkt getrennt werden: 1.023 0.1234

Wenn Sie befürchten bei riesigen Zahlen die Übersicht zu verlieren, dann können Sie einzelne Blöcke durch einen Unterstrich trennen. Also 123_456_678 ist eine gültige Zahl. Wo Sie die Unterstriche schreiben ist im Grunde genommen egal, nur am Anfang sollten keine stehen, denn Unterstriche am Anfang werden als Buchstaben verstanden. Somit ist _123 keine Zahl sondern ein Wort (eigentlich Bezeichner). Aber dazu weiter unten mehr.

Zahlen können Sie nicht nur in der Dezimaldarstellung schreiben. Es ist auch möglich sie binär, oktal oder auch hexadezimal zu schreiben. Um zu unterscheiden, wie die Zahl vom Compiler interpretiert werden soll, muss man vor der Zahl eine Art Hinweis schreiben. Für die binären Zahlen ist das 0b bzw. 0B. Zum Beispiel: 0b1001. Für oktale Zahlen ist es hingegen einfach die Zahl 0. Also 012 ist nicht die dezimale Zahl 12, sondern 12 als oktale Zahl, die gleich der dezimalen 9 ist. Für hexadezimale Zahlen schreiben Sie am Anfang 0x oder auch 0X. Bei hexadezimalen Zahlen werden wie üblich auch die Buchstaben A bis F bzw. a bis f für 10 bis 15 verwendet.

Variablen[Bearbeiten]

Variablen sind eigentlich so etwas wie Konstanten (oder andersrum). Der einzige Unterschied ist, wie man der Bezeichnung "Variable" schon ansieht, dass die Variablen auch verändert werden können. Oder anders gesagt, Sie können einer Variable verschiedene Werte beliebig oft zuweisen. Konstanten kann man den Wert aber nur ein mal angeben. Danach lässt er sich sich nicht mehr verändern.

Sowohl Konstanten als auch Variablen (ab jetzt durch K&V abgekürzt) werden im Computer als ein Speicherbereich abgebildet, da der Speicher begrenzt ist. Eine Folge davon ist, dass man keine unendlich großen Zahlen verwenden kann. Die sind auch in 99,9 % aller Fälle auch nicht notwendig.

Wie viel Speicher K&V bekommen hängt von ihrem Typen ab. Da für den PC der Speicher, den er verwendet, bzw. der ihm zur Verfügung steht, nur aus 1 und 0 besteht, bestimmt der Typ den Verwendungszweck also als was ein Bereich verstanden werden soll. Viele höhere Programmiersprachen haben deswegen Typen, die festlegen, ob ein Bereich als eine Zahl oder als ein Buchstaben interpretiert werden soll. Der Typ bestimmt auch wie viel Speicher die Konstante bzw. Variable braucht.

Was für K&V wichtig ist, ist dass man ihnen Namen gibt, bevor man sie verwendet.

Etwas ausführlicher werde ich hier nur zwei Typen erklären: Einen Ganzzahl- und ein Fließkomma-Typ. Der ganzzahlige Typ hat den Namen int, der Fließkomma-Typ float. Zeichenketten sind keine "einfachen" Datentypen. Andere einfache Datentypen werden am Ende aufgelistet. Zeichenketten werden in einem späteren Kapitel in aller Tiefe und Breite behandelt.

Verwendung[Bearbeiten]

Genug der Theorie jetzt erkläre ich wie Du K&V benutzen kannst.

So definieren Sie eine Variable:

int zahl;

Zuerst steht der Typ, gefolgt vom Name der Variablen. Verwendet man die Variable ab diesem Zeitpunkt, so hat sie den Wert 0.

Um einen anderen Wert festzulegen schreibe:

int zahl = 100;

Natürlich können Sie den Wert danach auch jederzeit ändern.

Das Gleich-Zeichen dürfen Sie nicht mit dem mathematischen Gleich-Zeichen verwechseln. In D bedeutet es lediglich Zuweisung. Also, dass die linke Seite wird der Wert der rechten Seite zugewiesen. Es ist nicht dasselbe, wie dass auf der rechten Seite genau dasselbe steht wie auf der linken.

Beispiel:

int zahl = 10;
[viel Code]
zahl = 1;
[noch mehr Code]

Was Konstanten angeht so werden sie auf folgende Weise definiert:

const float PI = 3.14159;

Wie Sie sehen besteht der einzige Unterschied darin, dass ein const dem Datentypen vorausgeht.

Der Wert der Konstante sollte während der Definition festgelegt werden. Folgendes liefert einen Fehler:

const float PI;
PI = 3.14159;

Wollen Sie mehrere Variablen oder Konstanten mit dem selben Typen definieren und sind zu faul jedes Mal den Typen davor zu schreiben? Dafür gibt es eine einfache Lösung:

int a, b, c;

Wie Sie siehst, müssen die einzelnen Namen einfach durch Komma trennen werden. Natürlich können Sie auch andere Namen als a, b, c nehmen; d, e, f zum Beispiel ;). Es können auch mehr oder weniger als drei Variablen definiert werden.

Für Konstanten sieht das genauso aus, nur müssen Sie davor wieder ein const schreiben und für jede Konstante auch einen Wert zuordnen (außer Sie wollen 0-Konstanten).

const int a = 1, b = 2, c = 3;

Rechenknecht[Bearbeiten]

Sie können auch Programme erstellen, die komplizierte Rechnungen anstellen und die Werte in Variablen speichern oder sie in der Konsole ausgeben.

int zahl;
zahl = zahl + 100;
zahl = 1 - zahl;
zahl = zahl / 99;
zahl = zahl * 100;
//zahl sollte -100 sein. 

Tipp

Anstatt <Variable> = <Variable> <Operator> <Irgendwas> zu schreiben, können Sie auch <Variable> <Operator> = <Irgendwas> schreiben. Das obere Beispiel umgeschrieben sieht dann so aus:

int zahl;
zahl += 100;
zahl = 1 – zahl; 
zahl /= 99;
zahl *= 100;

Klammern können ebenfalls verwendet werden:

int zahl = (13 + 5) / 6 - 2;
int a = (zahl + zahl * 10) / 7;

Jedoch können nur runde Klammern () verwendet werden um die Reihenfolge zu bestimmen. Andere Klammern wie {} oder [] haben ihre eigene Bedeutung. Generell werden die Rechenregeln (Punkt vor Strich) angewendet und die Rechnung von Links nach Rechts ausgewertet


Ausgabe in die Konsole[Bearbeiten]

Wenn Sie komplizierte Rechenaufgaben anstellen, wollen Sie vielleicht auch mitbekommen was für ein Ergebnis errechnet wurde. Verwende dazu die Funktion writef(), die Sie schon einmal kennengelernt haben.

Sie kann als Parameter nicht nur Strings annehmen, sondern auch andere Datentypen. Außerdem ist es möglich mehr als nur einen Parameter anzugeben. Die einzelnen Parameter werden auch durch Kommas getrennt.

Beispiel:

import std.stdio;

void main()
{
   int zahl = (13 + 5) / 6 – 2;
   writefln("Das Ergebnis der Berechnung ist: ", zahl);
}

writefln() tut im Grunde genommen genau dasselbe wie writef(). Der einzige Unterschied ist, dass writefln() am Ende automatisch einen Zeilenumbruch ausgibt. Das hat den Vorteil, dass Du ihn nicht selbst anzugeben brauchst.

Der entsprechende Aufruf mit writef() würde dann aber so aussehen:

[...]
writef("Das Ergebnis der Berechnung ist: ", zahl, "\n");
[...]

Die Funktion writef() (und writefln()) kann aber viel mehr. Wollen Sie, dass eine Variable, eine Konstante oder ein Literal bei der Ausgabe mitten in einem String steht, so schreiben Sie folgendes:

const int a = 10;
writef( "Das %s Ergebnis von %d + %d ist %d\n", 
             "richtige", a, 2, (a+2) );

Der erste Parameter der Funktion writef() ist immer ein Format-String, so wie in dem Beispiel. Die einzelnen Formatierbefehle werden mit Hilfe von %-Zeichen angegeben.

Format-Zeichen Beschreibung
%s Sagt dass an diese Stelle ein String eingefügt werden soll.
%d Hier steht eine ganze Zahl.
%f Hier steht eine Gleitkommazahl.
%% Schreibt das Prozentzeichen als solches.

Alle Parameter, die nach dem Format-String folgen, müssen den Typ der Formatierer entsprechen. Und zwar in der Reihenfolge, wie sie im Format-String auch auftauchen. Was für Ergebnisse Du ansonsten bekommst, können Sie selbst herausfinden.

Das ist aber noch nicht alles. Sie können z.B. auch angeben wie viele Stellen hinter dem Komma bei einer Dezimalzahl ausgegeben werden soll. Aber das erkläre ich zu einem späteren Zeitpunkt.

Typumwandlung[Bearbeiten]

D behandelt die Typen ziemlich streng. Damit kannst Du z.B. einer int-Zahl keine float-Zahl zuweisen, auch wenn die float-Zahl keine Nachkomma-Stellen hat.

Der Versuch das Beispiel zu kompilieren schlägt fehl.

void main()
{
   int a = 1.0;
}

Der Grund dafür ist, dass die Zahlen unterschiedlich im Speicher abgebildet werden, auch wenn beide Typen 32 Bit belegen. Um eine Dezimalzahl in eine ganze Zahl umzuwandeln (und umgekehrt), muss der Compiler zusätzlichen Code erzeugen. Außerdem, würde man eine float-Zahl in eine int-Zahl umwandeln, so gehen Nachkommastellen verloren. Das ist nicht immer erwünscht. Und oft will der Programmierer das gar nicht. Doch das ist bei großen Programmen nicht immer so offensichtlich, wie bei dem kleinen Beispiel oben.

Damit die Umwandlung trotzdem funktioniert wird eine explizite Typumwandlung erwartet. Explizit bedeutet, dass der Programmierer dem Compiler selbst sagt, dass er an einer bestimmten Stelle die Umwandlung haben möchte. Dazu gibt einen sogenannten cast-Operator. Das Beispiel erklärt wie es benutzt wird:

import std.stdio;

void main()
{
   float dezimal = 1.96;
   int ganzzahlig = cast(int)dezimal;
   writefln("Dezimal: %f, Ganzzahlig: %d", dezimal, ganzzahlig);
}

Anmerkung: Ich habe den Wert 1.96 mit Absicht gewählt, damit Sie sehen, dass eine Typumwandlung die Zahlen nicht rundet. Der Dezimalanteil wird einfach abgeschnitten.

Wie Sie vielleicht bemerkt haben, schreibt man zunächst das Wort cast, dann in Klammern den Zieltypen, gefolgt von irgendeinem Ausdruck (hier eine Variable).