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)!