The Real Adok's Way to C
Folge 2
Begleit-Dateien:
+++ Einleitung +++
Hallo und herzlich willkommen zur zweiten Folge meines C-Kurses! Diesmal geht
es, wie bereits in der letzten Folge angekündigt, um Variablen und ihre
Brüderchen und Schwesterleins.
+++ Datentypen +++
In C gibt es nur wenige Datentypen, und zwar:
signed short int: Das short kann in Real-Mode-DOS auch weggelassen werden.
Bei short int handelt es sich um Ganzzahlen von -32768 bis
+32767. Der Datentyp belegt 16 Bit.
signed long int: Das long kann in 32-Bit-Betriebssystemen wie Windows und
den aktuellen UNIX-Versionen sowie in Protected-Mode-DOS
auch weggelassen werden. Eine Variable dieses Typs kann
ganze Zahlen von -2147483648 bis einschließlich +2147483647
enthalten. Dafür belegt sie aber auch 32 Bit.
signed char: Eigentlich auch eine Integervariable, die von -128 bis +127
reicht und dafür auch nur 8 Bit belegt. Aber sie hat noch
andere Bedeutungen! (Dieses Geheimnis werden wir BALD
lüften...)
UNTERBRECHUNG! Eine wichtige Meldung zu den Integer-Datentypen: Es gibt auch
"unsigned"-Datentypen, und zwar unsigned short, unsigned long und unsigned
char. Diese verbrauchen genauso viel Speicherplatz, können aber keine
negativen Werte darstellen. Dafür sind sie in der positiven "Richtung" doppelt
so lang! Beispielsweise reicht ein unsigned short von 0 bis 65535. Und nun
weiter...
float: Fließkommazahlen mit 8 Stellen Genauigkeit. Belegt 32 Bit.
double: Fließkommazahlen mit 15 Stellen Genauigkeit. Belegt 64 Bit.
Wie ihr seht, hat C nur sehr wenige Datentypen! Nicht einmal ein Datentyp für
Zeichenketten (Strings) ist vorhanden! Das hat einen einfachen Grund: Der
Computer selbst kennt ja auch keine Strings. Wozu gibt es denn den ASCII-Code?
Richtig, damit der Computer die Zeichen in Integer-Variablen speichern kann!
Diejenigen, die die Zeichen erkennen, sind erst die Textausgaberoutinen. Sie
sehen nach, welches Zeichen zu dem ASCII-Code gehört, und geben es dann aus.
Habt ihr schon überlegt, warum der Datentyp char so heißt, wie er heißt? Ganz
einfach: Er kann genau 256 Werte annehmen (signed char von -128 bis +127,
unsigned char von 0 bis 255), und der von PCs verwendete ASCII-Code codiert ja
auch 256 verscheidene Zeichen. Somit eignet sich ein unsigned char bestens zur
Speicherung von Zeichen. Und Strings erhält man einfach durch einen Array von
char-Variablen. Ich sehe, ihr seid ganz heiß auf das Thema, ja, ihr wollt
schon mit Strings herumjonglieren... doch STOP! Zuerst muß ich euch zeigen,
wie man Variablen definiert!
+++ Variablendefinitionen +++
Eine Variablendefinition sieht so aus:
Typ Bezeichner;
Mehr nicht! Um eine unsigned-char-Variable namens zeichen zu definieren,
schreibt man also einfach:
unsigned char zeichen;
Wenn man mehrere Variablen von ein und demselben Datentyp definieren will, so
kann man auch die Variablennamen durch Beistriche trennen. Statt
int multiplikand;
int multiplikator;
int produkt;
tippt man dann
int multiplikand, multiplikator, produkt;
Da C eine formatfreie Sprache ist und man an beliebigen Stellen - außer
natürlich in Strings oder Bezeichnern - Leerzeichen und Zeilenumbrüche
einfügen kann, geht es auch übersichtlicher:
int multiplikand,
multiplikator,
produkt;
Außerdem ist es möglich, Variablen bei ihrer Definition auch Werte zuzuweisen.
Etwa so:
int multiplikand=99,
multiplikator=111,
produkt=0; /* Hm, neunundneunzig mal einhundertelf macht...
ähhh... :-) */
+++ Zuweisung +++
Die Zuweisung erfolgt in C mit dem Operator =. Beispiel:
var=10;
Damit wird der Variablen var der Wert 10 zugewiesen.
Bei Variablen des Integer-Stamms gibt es noch eine zweite Möglichkeit:
var='C';
Damit wird der Variablen var der ASCII-Code des Zeichens C zugewiesen.
Familiär ausgedrückt, kann man sagen: Ein einzelnes Zeichen muß in C immer von
zwei Hochkommas bedrängt werden, damit diese den ASCII-Code aus ihm
'rausquetschen.
Eine Eigenheit von C liegt darin, daß die Zuweisung ein Operator ist, genau so
wie + oder -. Genauso, wie man
a=b+c;
schreiben kann, kann man also auch
a=b=c;
schreiben. Damit wird der Variablen b der Inhalt von c zugewiesen, und der
Variablen a wird das Ergebnis der Zuweisung zugewiesen. Und dieses Ergebnis
ist... nichts anderes als... der Inhalt der Variablen c! Wir merken uns: Das
Ergebnis einer Zuweisung ist immer der Wert, der rechts von der Zuweisung
steht. Wir hätten also auch Folgendes schreiben können:
b=c;
a=b;
Wir wollen uns als Nächstes mit Strings beschäftigen und auf diese Weise auch
die Funktionsweise von Arrays erläutern. Dazu aber wäre es recht nützlich,
einige wichtige Funktionen für die Ein-/Ausgabe von Zeichen zu kennen.
+++ getch +++
Diese Funktion wurde bereits in Teil 1 ausreichend besprochen; was folgt, ist
deshalb nur Wiederholung. Um das Programm zu veranlassen, auf einen
Tastendruck des Benutzers zu warten, schreiben wir:
getch();
Wollen wir den ASCII-Code des Zeichens, das der Benutzer eingab, zwecks
Weiterverarbeitung in der Variablen zeichen speichern, schreiben wir:
zeichen=getch();
zeichen sollte den Datentyp char haben.
+++ putchar +++
putchar, in stdio.h deklariert, dient zur Ausgabe eines Zeichens. Dieses muß
als Parameter angegeben werden.
+++ Beispielprogram: getch und putchar +++
// getch und putchar
#include <stdio.h>
#include <conio.h>
void main(void)
{
char zeichen;
printf("Gib ein Zeichen ein! ");
zeichen=getch();
printf("\nDu gabst folgendes Zeichen ein: ");
putchar(zeichen);
printf("\n");
}
Der Vollständigkeit halber noch zwei verwandte Funktionen aus stdio.h:
+++ getc +++
getc funktioniert genauso wie getch, nur wartet es nicht auf einen
Tastendruck, sondern fragt den Tastaturpuffer direkt ab. Wenn dieser nicht
leer ist, gibt getc den aktuellen Wert im Tastaturpuffers zurück, ohne den
Tastaturpuffer zu ändern.
+++ getchar +++
getchar ist beinahe identisch mit getch. Aber zusätzlich wird die Eingabe auf
dem Bildschirm angezeigt, und der Benutzer muß sie mit ENTER bestätigen. Für
die Praxis ist getchar meines Ermessens nach eher von geringer Bedeutung.
+++ Arrays und Strings +++
Arrays sind Felder, also eine endliche Anzahl von Variablen, die unter
demselben Bezeichner zusammengefaßt sind. In C wird ein Array folgendermaßen
definiert:
Typ Bezeichner[Anzahl_Elemente];
Beispiel:
int a[3];
definiert einen Array vom Datentyp int mit drei Elementen. Auf diese Elemente
kann in Zuweisungen, arithmetischen Operationen und Funktionsaufrufen als
a[0], a[1] und a[2] zugegriffen werden. Ein Beispiel:
a[0] = 3;
a[1] = a[0] + 2;
weist a[0] den Wert 3 und anschließend a[1] den Wert 3 + 2, also 5, zu.
Strings sind nichts anderes als Arrays vom Typ char - mit einer Besonderheit:
Ihr letztes Element ist das Null-Byte, in C auch '\0' geschrieben. Man nennt
diese Strings deshalb auch nullterminiert. Die Nullterminierung ist notwendig,
damit die Stringbearbeitungsfunktionen das Ende des Strings erkennen. Denn
tatsächlich kennt keine Funktion die Anzahl der Elemente eines Arrays, der ihr
als Parameter übergeben wird - außer, man gibt diese als einen weiteren
Parameter extra an.
Um einen String mit dem Namen zeichenkette und einer Länge von 80 Zeichen zu
definieren, schreibt man also:
char zeichenkette[81];
+++ Einige Funktionen zur Stringbearbeitung +++
+++ strcpy +++
Deklariert in string.h. Als Parameter muß zuerst der Name des Ziel-Strings
(also der Name, der bei der Definition des char-Arrays angegeben wurde) und
dann der Quell-String angegeben werden. Beispiel:
char begruessung[12];
strcpy(begruessung,"HALLO DU!!!");
+++ gets +++
Analog zu getchar dient gets der Eingabe von Strings. Der Name des Arrays, in
dem die Zeichenkette abgespeichert werden soll, muß dabei als Parameter
angegeben werden. Nach der Eingabe wird ein Zeilenumbruch ausgegeben.
Beispiel:
char zeichenkette[101];
.
.
.
gets(zeichenkette);
Die Deklaration befindet sich in stdio.h.
+++ puts +++
Diese Funktion gibt den String wieder auf den Bildschirm sowie einen
Zeilenvorschub aus. Ansonsten ist sie genauso wie putchar aufzurufen und auch
in stdio.h deklariert.
+++ Beispielprogram: gets und puts +++
// gets und puts
#include <stdio.h>
void main(void)
{
char name[81]; /* Hoffentlich gibt es keinen Namen, der
länger ist als 80 Zeichen! :-) */
printf("Wie heißt du? ");
gets(name);
printf("Aha, du heißt also ");
puts(name);
printf("Sei gegrüßt!\n");
}
+++ strcmp +++
Die Vergleichsoperatoren, die wir in Teil 3 kennenlernen werden, gelten nicht
für Strings. Wir benötigen stattdessen die Funktion strcmp aus string.h. Als
Parameter müssen dabei die Variablennamen der beiden zu vergleichenden Strings
angegeben werden. Der Rückgabewert von strcmp kann danach von der if-Anweisung
ausgewertet werden. Näheres erfahrt ihr in Teil 3.
+++ strlen +++
Diese Funktion aus string.h liefert die Anzahl der Zeichen des als Parameter
angegebenen Strings zurück. Die Stringendekennung wird NICHT dazugezählt!
+++ strcat +++
Und damit lassen sich zwei Strings aneinanderhängen! Der erste Parameter ist
der Ursprungstring, an den der zweite Parameter angehängt wird. Beispiel:
char stringy[81]="Park"; /* Auch bei Strings kann schon während der
Definition eine Zuweisung erfolgen! Dies
ist allerdings der einzige Fall, wo man
strcpy nicht verwenden muß. */
strcat(stringy,"bank");
strcat ist ebenfalls in string.h deklariert.
Um das Gelernte noch einmal zu wiederholen, folgt abschließend noch ein
Beispielprogramm:
// String-Beispielprogramm
#include <stdio.h>
#include <string.h>
void main(void)
{
char vor[21],
nach[21],
name[42];
printf("Hallo, Typ!\nWie lautet dein Vorname? ");
gets(vor);
printf("Und dein Nachname? ");
gets(nach);
strcpy(name,vor);
strcat(name," ");
strcat(name,nach);
printf("Du heißt also ");
puts(name);
}
So, Folks, machen wir hier für heute Schluß. In der nächsten Folge kommt dann
einiges mehr über die Variablen. Wir werden uns auch ansehen, welche
Möglichkeiten es gibt, Verzweigungen in C zu machen. Viel Spaß bis zur
nächsten Folge (und dann hoffentlich noch immer)!