^2The Real Adok's Way from QBasic to C               ^0...written by The Real Adok
 
^1Heute: ^4Part 3 ^1- ^4Variablen, Ein/Ausgabe, Operatoren, Bl”cke, Pr„prozessor

Seid  gegrát,  meine Freunde! Mit neuem Eifer strzen wir uns in eine weitere
Schlacht, eine neue Folge unseres C-Kurses! Diesmal geht's,  wie  angekndigt,
wieder um Variablen. Dieses Thema ist einfach riesig! Wir besch„ftigen uns mit
der  Eingabe  und  Ausgabe  von  Zahlenvariablen  und lernen dabei einige neue
Varianten von printf kennen.  Und als Draufgabe werden wir den if-Befehl & Co.
kennenlernen, mit dem wir  Verzweigungen  realisieren  und  etwas  ntzlichere
Programme erstellen k”nnen! Also, worauf wartet ihr noch? Laát uns beginnen!

                              ø6+++ ^1Los geht's! ø6+++

Jau,  wie  man Zeichen und Strings ausgibt, wiát ihr ja schon. Na, wie? Genau,
mit putchar und puts! Jetzt geht's darum, auch Zahlen ausgeben zu k”nnen. Dazu
bedienen wir uns einer altbekannten Funktion  aus  stdio.h,  ^4printf^5.  Wie  wir
wissen, kann der Parameter Text nicht nur aus druckbaren Zeichen, sondern auch
aus  Steuerzeichen  bestehen!  Diese  werden  durch  einen  Backslash (also \)
gekennzeichnet.

Jedoch  sind  nicht  nur  Steuerzeichen  nicht  druckbar,   sondern  auch  die
sogenannten  ^4PLATZHALTER^5.  Wie  immer gilt's auch hier: Nomen est Omen! Platz-
halter halten den Platz fr eine Variable frei. An  dieser  Stelle  wird  dann
eine Variable auf dem Bildschirm ausgegeben. Ein jeder Platzhalter beginnt mit
einem  Prozentzeichen.  Danach  folgt  eine Formatangabe. Einige Beispiele fr
Formatangaben:

^3       Datentyp(en):
^0 %d    ^5short int und char
^0 %ld   ^5long int
^0 %u    ^5unsigned short und unsigned char
^0 %lu   ^5unsigned long
^0 %f    ^5float
^0 %lf   ^5double

^1%f^5 und ^1%lf^5 haben brigens eine Besonderheit: Man  kann  auch  die  Anzahl  der
Nachkommastellen,  die  ausgegeben werden sollen, bestimmen! Dazu muá man nach
dem Prozentzeichen einen Punkt und danach die Anzahl der Nachkommastellen hin-
schreiben. Beispielsweise muá man ^0%.2f^5 schreiben,  um  einen  float  mit  zwei
Nachkommastellen  anzuzeigen.  Auáerdem  gibt es noch einige Formatangaben fr
Zeichen und Strings. Mit ihnen lassen sich Zeichen und Strings genauso wie mit
putchar und puts ausgeben, nur wird im Gegensatz zu  puts  kein  automatischer
Zeilenvorschub ausgegeben.

^0 %c    ^5gibt eine char-Variable als Zeichen aus
^0 %s    ^5gibt einen char-Array als String aus
^0 %%    ^5gibt das Prozentzeichen aus
  
So, aber mit diesen Formatangaben allein l„át sich absolut nix anfangen!  Jau,
ihr habt recht:  Wir mssen natrlich noch angeben, welche Variable ausgegeben
werden soll!  Und das geschieht z.B. so: ^0printf("Eine Zahl: %d\n",inty);^5 oder,
mit mehreren Variablen: ^0printf("%d %s %lf",inty,chararray,doubly);^5 Im Sources-
Verzeichnis findet ihr dazu noch ein kleines Beispielproggy, n„mlich dieses:

^0// C-Kurs 3: Die erweiterten Funktionen von printf
 
^0#include <stdio.h>
 
^0void main(void)
^0{
^0  int summand[2],
^0      summe;

^0  summand[0]=-20;
^0  summand[1]=40;
^0  summe=summand[0]+summand[1];

^0  printf("Erster Summand: %d\n"
^0         "Zweiter Summand: %d\n"
^0         "Summe: %d\n",
^0          summand[0],summand[1],summe);

^0  /* Ein String l„át sich in C auch ber mehrere Zeilen verteilen, wenn man
^0     wie oben vorgeht. */
^0}

             ø6+++ ^1Die vier Grundrechnungsarten (tatatatammm...) ø6+++

Back to the kindergarten! Also, liebe Kinder, da gibt es das Plus, damit k”nnt
ihr zwei Žpfel und vier Žpfel zu sechs Žpfel machen... Scherz  beiseite,  ich
hoffe, jeder weiá, wie die vier Grundrechnungsarten funktionieren. In C werden
sie durch folgende Symbole dargestellt:

 ^4+    ^0Plus
 ^4-    ^0Minus
 ^4*    ^0Ma(h)l(zeit)
 ^4/    ^0Dividiert

Besonderheiten gibt's nur bei der Division. Denn was glaubt ihr, kommt bei der
folgenden Zuweisung raus: ^0float floaty; floaty=5/2;^5  ???  "Zwei komma fnf!!!"
Falsch,  ihr  Schlaumeier,  zu  frh  gefreut!  Es kommt nur zwei heraus! Wenn
n„mlich sowohl der Dividend als auch der Divisor Ganzzahlen sind,  also  keine
Nachkommastellen enthalten, wird immer eine Integerdivision durchgefhrt.  Die
Nachkommastellen werden also abgeschnitten. Um das zu verhindern, muá man ein-
fach eine der beiden Zahlen als Flieákommazahlen schreiben.  Also schreibt man
z.B.: ^0floaty=5/2.0;^5 . Oder, man schreibt das: ^4floaty=5/(float)2^5;
  
^2WAS SOLL DENN DAS SEIN? DA STEHT JA EIN DATENTYP IN DER KLAMMER!

Richtig, das gibt es in C auch! Und zwar nennt sich diese Eigenschaft

                              ø6+++ ^1Typecasting ø6+++

Mit  Typecasting  wird  schlicht  und  einfach eine Zahl oder eine Variable in
einen anderen Datentyp umgewandelt. Aber nur tempor„r  (fr  die  Berechnung)!
Mit  Typecasting l„át sich nicht eine Integervariable dauerhaft in eine Flieá-
kommazahl verwandeln! Der Datentyp, in den verwandelt werden soll,  muá  dabei
in zwei runde Klammern eingeschlossen werden.

Und dann gibt es noch einige Besonderheiten. Zum einen darf man ^4nie durch Null
^4dividieren^5,  wenn  man nicht absichtlich den Interrupt 0 ausl”sen will (der im
Normalfall das Programm abbricht, wenn er nicht auf eine eigene  Routine  ver-
bogen  ist).  Die  andere "Spezialit„t", die Basicler nicht kennen, obwohl sie
in allen anderen Prospen Gang und Gebe ist, nennt sich ^4šberlauf^5.  Addiert  man
zu  einem  unsigned  char,  der  gleich 255 (der Maximalwert) ist, 1, so isser
nachher 0.  Wenn ihr euch das Bitmuster der Zahl anseht, wird euch alles klar:
255d = 11111111b. Addieren wir dazu 1, so máte 100000000b entstehen.  Da  ein
Byte  jedoch  nur  8 Bit hat, wird Bit 8 abgeschnitten, und brig bleibt Null.
Daher muá man eine int-Variable als Schleifenz„hler verwenden, wenn  man  eine
Schleife  von  0  bis  255  machen  will.  Bei  einer char-Variablen wrde die
Schleife endlos laufen!  Genauso gibt's natrlich auch Unterl„ufe (Zahl ist 0,
und wir ziehen immer noch was ab.).
 
Solche šberlaufph„noneme treten natrlich auch bei den anderen Datentypen auf,
aber  dort  erst  ab  65535 (unsigned short), 2 hoch irgendwas (unsigned long)
usw. Aber nun zu was anderem!

                                 ø6+++ ^1scanf ø6+++

Der Name sagt's:  scanf aus stdio.h ist der ^4Eingabebefehl^5 fr Zahlenvariablen.
ABER:  Er  ist  sehr fehleranf„llig! Deshalb wrde ich an eurer Stelle nur mit
groáer Sorgf„ltigkeit mit ihm umgehen.  Also, das Synt„xchen von scanf lautet:
^0scanf(formatstring,adressedervariablen);
  
Im Grunde genommen geht's also wie printf! Auch  die  Platzhalter  im  Format-
string  sind  die gleichen (bis auf die Anzahl der Nachkommastellen bei floats
und doubles, die gibt's hier nicht). Nur beim  Variablennamen  mát  ihr  auf-
passen:  Vor  dem  Namen  muá IMMER ein &-Zeichen stehen. Der ^4&-Operator^5 dient
dazu, die Speicheradresse der Variablen herauszufinden (wie OFFSET  in  ASM  -
ihr  seht,  zwischen den beiden Sprachen gibt es relativ viele Parallelen). In
Wirklichkeit arbeitet scanf n„mlich mit Zeigern, einem wichtigen Baustein, den
wieder einmal alle Sprachen auáer diesem  d„mlichen  Basic  integriert  haben.
Sp„ter wird noch ausfhrlich darber diskutiert.  Hier noch ein Beispiel-Prog,
an dem ihr auch sch”n erkennen k”nnt,  wie man beim Print-Žffen von floats und
doubles die Anzahl der auszugebenden Nachkommastellen bestimmt:

^0// C-Kurs 3: scanf

^0#include <stdio.h>

^0void main(void)
^0{
^0  float zahl[2];

^0  printf("Zahl 1 eingeben: ");
^0  scanf("%f",&zahl[0]);
^0  printf("Zahl 2 eingeben: ");
^0  scanf("%f",&zahl[1]);

^0  printf("\n%.2f + %.2f = %.2f\n",zahl[0],zahl[1],zahl[0]+zahl[1]);
^0  printf("%.2f - %.2f = %.2f\n",zahl[0],zahl[1],zahl[0]-zahl[1]);
^0  printf("%.2f * %.2f = %.2f\n",zahl[0],zahl[1],zahl[0]*zahl[1]);
^0  printf("%.2f / %.2f = %.2f\n",zahl[0],zahl[1],zahl[0]/zahl[1]);
^0}
                     
                          ø6+++ ^1Weitere Operatoren ø6+++

Richtig,  das  waren noch nicht alle Operatoren, die es in C gibt! Zun„chst zu
den kombinierten Operatoren: Sie sind eine besondere  Art  der  Zuweisung.  Es
kommt  h„ufig  vor, daá man in Proggys solche Sachen wie ^0a=a+3;^5 ben”tigt. In C
geht das noch einfacher,  denn  da  benutzt  man  einfach  einen  kombinierten
Operator  und  schreibt ^0a+=3;^5 Genauso geht's mit allen anderen Operatoren. Man
schreibt einfach die Variable, mit der etwas addiert, subtrahiert usw.  werden
soll,  dann  den  Operator,  ein  Gleichheitszeichen  und  die  Zahl  oder die
Variable, die addiert, subtrahiert et cetera werden soll. Logisch!
 
Und dann gibt es NOCH eine Vereinfachung!  Als ob es nicht schon einfach genug 
ist... Statt ^0a+=1;^5 gibt's n„mlich die NOCH krzere und effektivere Form ^0a++;^5 ,
auch  Inkrementieroperator  genannt.  Der  Dekrementieroperator lautet selbst-
verst„ndlich ^0--^5. Die zwei Plusse bzw. Minusse (oder heiát das etwa MinEN? :-))
kann man auch vor der Variablen schreiben.  Das ist dann genauso, nur nicht in
Zuweisungen! Guckt euch dazu dieses Programm an:

^0// C-Kurs 3: Der Unterschied zwischen a++ und ++a

^0#include <stdio.h>

^0void main(void)
^0{
^0  char a=5,
^0       b=0;

^0  // Erste M”glichkeit
^0  b=a--;
^0  printf("b=a-- ergibt:\na=%d\nb=%d\n\n",a,b);

^0  // Variablen zurcksetzen
^0  a=5;
^0  b=0;

^0  // Zweite M”glichkeit
^0  b=--a;
^0  printf("b=--a ergibt:\na=%d\nb=%d\n",a,b);
^0}

Wie ihr seht, treten hier zwei verschiedene Ergebnisse auf!  Und das nur, weil
einmal das Dekrement hinter a und einmal vor a steht!  Nun, betrachten wir die
Ergebnisse  n„her.  Bei  beiden M”glichkeiten hatte am Schluá a den Wert vier.
Das ist logisch, schlieálich wurde beide Male a um eins erniedrigt! Aber b hat
immer andere Werte. Beim ersten Mal ist b fnf, beim  zweiten  Mal  vier.  Das
liegt  an  der Reihenfolge, wie C die Dekrements auswertet. Wenn das Dekrement
hinter der Variablen steht, wird zuerst die Zuweisung  ausgefhrt,  erst  dann
dekrementiert. Also bedeutet die Zeile ^0b=a--;^5 soviel wie ^0b=a; a--;

Genau  umgekehrt  ist's,  wenn  das  Dekrement  vor  der Variablen steht! Dann
erfolgt zuerst das Dekrement und erst danach die  Zuweisung!  ^0b=--a;^5  bedeutet
also ^0a--; b=a;^5  Habt  ihr's  kapiert?  Beim Inkrement verh„lt es sich genauso!

                           ø6+++ ^1Bin„re Operatoren ø6+++

Nimmt  das  denn  kein  Ende???  Sorry,  aber in C gibt es wirklich SEHR viele
Operatoren! Ich will mich aber gn„dig erweisen und stelle euch (fr heute :) )
nur mehr die bin„ren Operatoren vor. Also, hier eine kleine Tabelle:

 ^4~      ^0bitweises NOT                       ^5      NOT 0101b = 1010b
 ^4&      ^0bitweises AND                       ^50101b AND 0011b = 0001b
 ^4^01^  ^00    ^0bitweises XOR                       ^50101b XOR 0011b = 0110b
 ^4|      ^0bitweises OR                        ^50101b  OR 0011b = 0111b

Und, wenn wir schon dabei sind, die Bitschiebeoperatoren, die in der Demoszene 
sehr  oft  angewendet  werden, weil sie schneller als normale Multiplikationen 
und Divisionen sind.

 ^4a<<x   ^5entspricht: ^0  a mal (2 hoch x)
 ^4a>>x   ^5entspricht: ^0a durch (2 hoch x)

Das gleiche steht brigens auch im Assemblerkurs #5, nur eben ASM-spezifisch.

                             ø6+++ ^1Verzweigungen ø6+++

Der IF-Block von Basic funktioniert in C mit ^0if(ausdruck) tuedas else tuedies^5.
Sollen tuedas und/oder tuedies mehr als einen Befehl beinhalten,  schreibt man
einfach Klammern um sie herum:

^0 if(ausdruck) {
^0   ...
^0 }
^0 else {
^0   ...
^0 }

Der  Rest  entspricht  Sucking-Basic.   else-Zweig  kann  weggelassen  werden,
Verschachtelungen sind auch m”glich,   und statt EXIT IF schreibt man ^0break;^5 .
Die Vergleichsoperatoren im Ausdruck sind:

 ^4==   ^5Test auf ^0Gleichheit
 ^4!=   ^5Test auf ^0Ungleichheit
 ^4<    ^5Test auf Kleinigkeit... „h, sagen wir lieber nur "^0kleiner^5" ;-)
 ^4>    ^0grӇer
 ^4<=   ^0kleiner oder gleich
 ^4>=   ^0grӇer oder gleich

Die  logischen  Verknpfungen  sind ^4&&^5 (und), ^4||^5 (oder) sowie ^4!^5 (not). Ist der
Inhalt des Ausdrucks falsch, so ergibt er den Wert  ^40^5  (FALSE).  Jeder  andere
Wert ist TRUE.  Die Vergleichsoperatoren geben fr TRUE hierbei ^4-1^5 zurck. Aus
diesem  Grund  muá  der  Ausdruck  nicht  immer  aus einem Vergleich bestehen.
Schreiben wir z.B. ^0if(vary)^5, und die Variable ist gleich 0, so ergibt der Test
automatisch FALSE. Die Anweisungen innerhalb if werden nicht ausgefhrt. Falls
vorhanden, wird zum else-Zweig gesprungen. Ist vary dagegen ungleich 0, so ist
die Bedingung erfllt.

Ein kleines Beispielprogr„mmelchen, das einige von euch  vielleicht  noch  aus
The Real Adok's Way to QBASIC kennen (dort gab's das gleiche in Basic):

^0// C-Kurs 3: Verzweigungen mit if

^0#include <stdio.h>

^0void main(void)
^0{
^0  long int zahl[2];

^0  printf("Gib die erste Zahl ein!  ");
^0  scanf("%ld",&zahl[0]);
^0  printf("Gib die zweite Zahl ein! ");
^0  scanf("%ld",&zahl[1]);

^0  printf("\nDie beiden Zahlen erfllen folgende Bedingungen:\n");
^0  if(zahl[0]==zahl[1]) printf("Zahl 1 ist gleich Zahl 2.\n");
^0  if(zahl[0]<=zahl[1]) printf("Zahl 1 ist kleiner oder gleich Zahl 2.\n");
^0  if(zahl[0]>=zahl[1]) printf("Zahl 1 ist grӇer oder gleich Zahl 2.\n");
^0  if(zahl[0]<zahl[1])  printf("Zahl 1 ist kleiner als Zahl 2.\n");
^0  if(zahl[0]>zahl[1])  printf("Zahl 1 ist grӇer als Zahl 2.\n");
^0  if(zahl[0]!=zahl[1]) printf("Zahl 1 ist ungleich Zahl 2.\n");
^0}

                          ø6+++ ^1String-Vergleiche ø6+++

Wenn  wir  testen  wollen,  ob  der  String  str1  dem String str2 entspricht,
schreiben wir ^0if(!strcmp(str1,str2))^5 . Die  Verneinung  ist  deshalb  wichtig,
weil  strcmp  den  Wert  0  zurckliefert,  wenn beide Strings identisch sind.
Wieder ein Beispielprogramm (g„hn),  um  das  gelernte  Zeug  noch  einmal  in
unseren Seelen zu vertiefen (ach, wie poetisch).

^0// C-Kurs 3: strcmp und strlen

^0#include <stdio.h>
^0#include <string.h>

^0void main(void)
^0{
^0  char vor[21],
^0       nach[21],
^0       name[42];

^0  printf("Hallo, Typ!\nWie lautet dein Vorname? ");
^0  scanf("%s",vor);
^0  fflush(stdin);
^0  printf("Und dein Nachname? ");
^0  scanf("%s",nach);
^0  fflush(stdin);

^0  if(!strcmp(vor,nach))
^0  {
^0    printf("\nHe, du Schlingel! Dein Vorname ist ja genauso wie dein ");
^0    printf("Nachname!\nAber wie dem auch sei...\n");
^0  }

^0  strcpy(name,vor);
^0  strcat(name," ");
^0  strcat(name,nach);

^0  printf("\nDu heiát also %s!\n",name);
^0  printf("Wuátest du eigentlich, daá dein Name ");
^0  printf("genau %d Zeichen lang ist?",strlen(name));
^0}

Die  Funktion  ^4fflush(stdin)^5  sollte hierbei den Tastaturpuffer lernen. Jedoch
was fr einen Puffer? Den Tastaturpuffer, den der Tastaturinterrupt verwendet,
jedenfalls sicher nicht. :)) Trotzdem  funzt  es  bei  den  in  C  eingebauten
Befehlen. Fr fortgeschrittene Zwecke empfehle ich die Funktion:

^0void delkeybuf(void)
^0{
^0  asm {
^0    cli
^0    mov ax,0x40
^0    mov es,ax
^0    mov bx,0x1c
^0    mov ax,word ptr es:[bx]
^0    mov bx,0x1a
^0    mov word ptr es:[bx],ax
^0    sti
^0  }
^0}

Solange  niemand  auf  die Idee kommt, mit einem exotischen Tool seinen Puffer
auf andere Speicheradressen zu verlagern, haut es hin.

                                ø6+++ ^1switch ø6+++

Was in Basic SELECT CASE ist, heiát in C switch. Typischer Aufbau:

^0switch(ausdruck)
^0{
^0  case 1:    //Jetzt kommen die Befehle
^0             break;
^0  case 2:    //Wieder Befehle
^0             break;
^0  default:   //usw.
^0}

Was  den  Unterschied  zu  anderen  Sprachen macht, ist ^4break^5. L„át man ^0break;
n„mlich weg, werden auch die  darunterliegendenden  M”glichkeiten  ausgefhrt.
Ein  Beispiel,  zuerst  richtig,  danach  schlampig.  Links  steht die switch-
Anweisung, rechts immer das Žquivalent als if-Block.

^0switch(vary>1)                         ^4if(!(vary>1))
^0{                                      ^4  printf("Wert <= 1\n");
^0  case 0:    printf("Wert <= 1\n");    ^4else
^0             break;                    ^4  printf("Wert > 1\n");
^0  default:   printf("Wert > 1\n");
^0}

Ihr  seht,  da  TRUE  und  FALSE  Zahlenwerte sind, kann auch ein switch-Block
Entscheidungen treffen, obgleich if hierfr wesentlich  besser  geeignet  ist.
Nun das "schlampige" Beispiel:

^0switch(vary>1)                         ^4if(!(vary>1))
^0{                                      ^4{
^0  case 0:    printf("Wert <= 1\n");    ^4  printf("Wert <= 1\n");
^0  default:   printf("Wert > 1\n");     ^4  printf("Wert > 1\n");
^0}                                      ^4}
                                       ^4else
                                       ^4  printf("Wert > 1\n");

Ihr  seht  also,  was da entstehen kann. Am besten, ihr probiert das Ganze mal
live aus, um euch mit dieser  Eigenheit  vertraut  zu  machen.  In  bestimmten
F„llen kann sie auch ganz ntzlich sein, um Speicherplatz zu sparen.

                                  ø6+++ ^1for ø6+++

Die  Z„hlschleife  heiát  in  C ebenfalls for, beherbergt jedoch vielf„ltigere
M”glichkeiten. Eine Z„hlschleife aus Basic wie

^0FOR zaehler = startwert TO endwert STEP 1
^0 ...
^0NEXT

sieht in C so aus:

^0for(zaehler=startwert;zaehler<=endwert;zaehler++)
^0{
^0  ...
^0}

Die erste Anweisung innerhalb des Schleifenkopfs wird vor dem ersten Durchlauf
ausgefhrt.   Sie  dient  bei  einer  konventionellen  Z„hlschleife  also  der
^4* ^3megacoolen ^4*^5 ^1Initialisierung^5 der Variablen. (Hupsi! H„tte fast vergessen, in
dem  schwachsinnigen  Stil  von vorhin zu schreiben.) Nungut... Das zweite ist
die ^1Bedingung^5.  Das Innere der Schleife wird hierbei solange durchgefhrt, wie
diese Bedingung TRUE ergibt. So lassen sich sehr sehr sch”ne Endlosschleifchen
coden, indem man diese Bedingung auf 1 oder  einen  anderen  Wert  ungleich  0
setzt.  :))  Die  dritte Anweisung schlieálich sagt, was ^1nach jedem Schleifen-
^1durchlauf^5 geschehen soll. In diesem Fall wird die Z„hlvariable um 1 erh”ht.

Theoretisch lieáe sich der Schleifenbody also ganz  weglassen  und  in  dieser
dritten Anweisung unterbringen! :))))) Das machen auch viele wahnwitzige Coder
wie  z.B.  dieser  Fowl  aus dem Cream (hallo!). :-)) Es gibt da n„mlich einen
bisher unerw„hnten Operator in C ^4,^5  den  Beistrich.  Mit  diesem  lassen  sich
mehrere  Funktionsaufrufe  verketten,  wobei  jedoch  der  Rckgabewert dieser
Funktionen verlorengeht. Anyway, gew”hnt euch diesen Stil erst gar  nicht  mal
an. :) Hier mal ein Primitivbeispiel zur Fakult„tsberechnung.

^0// C-Kurs 3: Fakult„tsberechnung mit for

^0#include <stdio.h>

^0void main(void)
^0{
^0  unsigned char zahl,
^0                i;
^0  unsigned long ergebnis=1;

^0  printf("Bitte 'ne Zahl zwischen 2 und 30 eingeben: ");
^0  scanf("%ud",&zahl);
  
^0  switch( (zahl>=2) && (zahl<=30) )
^0  {
^0    case 0:    printf("\nZwischen 2 und 30 habe ich gesagt. ™rks.\n");
^0               break;
^0    default:   for(i=2; i<=zahl; i++) ergebnis*=(unsigned long)i;
^0               printf("\nFakult„t ist: %lu\n",ergebnis);
^0  }
^0}

Theoretisch lieáe sich eine for-Schleife auch wie die DO-WHILE-Schleife von...
ich  wag's  gar  nicht  zu  sagen...  "Basic"  (kreisch)  einsetzen, indem man
Anweisungen 1 und 3 im Schleifenkopf wegl„át: ^0for(;bedingung;)^5 Aber Kerningham
und Ritchie, die alten Herren,  denen die Erfindung von C zugeschrieben worden
ist (nein, nein, sie haben  C  tats„chlich  erfunden,  'tschuldigung!),  haben
eine humanere L”sung fr dieses Problem gefunden: die ^4while^5-Schleife. Sie wird
wie for verwendet, nur wird eben NUR Anweisung 2 geschrieben:

^0while(ausdruck)
^0{
^0  ...
^0}

Ist  sowieso  logisch!  Natrlich muá es auch eine anders orientierte Schleife
geben. Eine, die hinten hat, was vorne steht. Sie lautet:

^0do
^0{
^0  ...
^0} while(ausdruck)

Im Gegensatz zu Doofsic, ja, sogar zu Pascal (nicht Andre :) ) gibt  es  in  C
kein  UNTIL.  Aber  das  ist  sowieso nur fr Anf„nger gedacht, die schnell zu
guten Programmierergebnissen kommen  wollen,  ohne  sich  n„here  Gedanken  zu
machen.  UNTIL kann emuliert werden, indem man den Ausdruck in der Klammer mit
einem Rufzeichen versieht, ihn also verneint. Somit  w„re  wieder  ein  dummes
Argument pro Basic aus dem bl”den Prospenstreit fr nichtig erkl„rt.

                           ø6+++ ^1Tern„rer Operator ø6+++

Naja, darf's noch ein Operator mehr sein?  if l„át sich n„mlich abkrzen, wenn
es  darum  geht,  je  nach  Erfllung  einer  Bedingung  einer Variablen einen
bestimmten Wert zuzuweisen.  In  C  gibt  es  einen  eigenen  Operator  dafr!
Eigentlich  sind  es  ja  mehrere  Operatoren.  Machen  wir  wieder einmal ein
By-Spiel. Statt der Anweisung

^0if(mariussagtrichtiges)
^0  mariusistgescheit=-1;
^0else
^0  mariusistgescheit=0;

schreibt man krzer: ^0mariusistgescheit = mariussagtrichtiges ? -1 : 0

Ganz sch”n kompliziert, was? Wird man  im  normalen  Programmierleben  sowieso
wenig brauchen, weil man n„mlich genausogut schreiben kann:

^0mariusistgescheit=( mariussagtrichtiges != 0 );

Auch ein Vergleich ist ein Operator. Mit obiger Anweisung wird zuerst geprft,
ob die Variable mariussagtrichtiges ungleich FALSE ist.  Das  Ergebnis  dieses
Vergleichs  wird  der  Variablen  mariusistgescheit  zugewiesen.  Wer sich die
Zahlenwerte von TRUE und FALSE nicht merken  kann,  dem  kann  mit  Hilfe  des
Pr„prozessors Abhilfe geschaffen werden.

                           ø6+++ ^4DER PRŽPROZESSOR ø6+++

Bisher  tauchte  der  PP  nur  im  Zusammenhang mit dem Einbinden von externen
Headerdateien auf. Der PP kann jedoch noch viel mehr!  Da stellt sich zun„chst
die  Frage:  Was ist der PP berhaupt? Er ist eine Art "Textbersetzer". Bevor
ein Quellcode compiliert werden kann,  muá  es  zuerst  in  den  PP  geschickt
werden.  Dieser  sucht  nun nach "seinen" Befehlen wie ^0#include^5, ^0#define^5 etc.,
welche natrlich immer mit einem amerikanischen Numerus beginnen.  Die Befehle
veranlassen  den  PP,  den  Quellcode  des  Programms  zu „ndern. St”át er auf
^4#include^5, so wird die danach angegebene Headerdatei ge”ffnet und  komplett  in
das  Proggy  eingebunden. Ebenso veranlassen die anderen Befehle wie ^4#define^5 &
Co. den PP, etwas im Programm zu „ndern.

Da sind wir beim springenden Punkt:  ^1Was  macht  #define?^5  #define  dient  zum
Erstellen  von  Konstanten  und  Makros  (nicht "Markos" :)) ).  Die Anweisung
^0#define TRUE -1^5 veranlaát den PP, berall dort, wo im Quellcode  das  W”rtchen
TRUE steht, es durch -1 zu ersetzen.  Ebenso kann man mit der kurzen Anweisung
^0#define CLS _clearscreen(_GCLEARSCREEN)^5 den  langen  Funktionsaufruf,  welchen
wir bereits in Folge 1 kennengelernt haben, abkrzen.  Und es lassen sich auch
Makros mit Parametern definieren: ^0#define CUBE(x) x*x^5 .  Hier liegt jedoch der
Hund  begraben!  Denn  was  passiert, wenn ich im Quelltext irgendwo ^0CUBE(1+1)
schreibe? Der PP ersetzt dies durch ^01+1*1+1^5!  Wir t„ten also besser daran, das
Makro ^0CUBE(x)^5 mit ^0(x)*(x)^5 zu definieren.

Eine weitere Fehlerquelle liegt darin, daá sich eine Makrodefinition jederzeit
berschreiben oder mit dem Befehl ^4#undef^5 rckg„ngig machen l„át. Ebenso k”nnte
man Variablen mit Makros/Konstanten verwechseln. Aus diesem Grund hat man sich
angew”hnt, ^2MAKROS GROSS^5 zu schreiben, w„hrend ^2variablen klein^5 sind.

Nachdem nach dem PP-Lauf der Quellcode in eine fr den Compiler  lesbare  Form
umgewandelt worden ist, wird der Compiler aufgerufen und weiter geht's.

^4Weitere  ntzliche  PP-Befehle^5  sind  #if, #endif,  #ifdef, #ifndef, #else und
#elif. Damit l„át sich eine bedingte šbersetzung  realisieren!  Schreiben  wir
n„mlich:

^0#if defined(WIN95)
^0  printf("Windows-95-Version des Programms wird geladen...\n");
^0#elif defined(LINUX)
^0  printf("Linux-Version loading...\n");
^0#else
^0  printf("Starte DOS-Version...\n");
^0#endif

...so wird Anweisung Nummer 1 nur dann compiliert, wenn das Makro WIN95 vorher
definiert  wurde.  Ist  dagegen  LINUX  definiert,  wird  die zweite Anweisung
compiliert. Und wenn weder WIN95 noch LINUX definiert sind,  gibt's  Anweisung
Nummer 3. So lieáe sich der Quellcode von mehreren verschiedenen Versionen des
Programms  fr verschiedene Betriebssysteme in einem einzigen Quellcode unter-
bringen.   Dieser  muá  nur  minimal  ver„ndert  werden  (n„mlich  die  Makro-
definitionen), danach wird er neu compiliert, schon hat man  sein  Proggy  fr
sein System! Soviel zu der Portabilit„t von C-Programmen, wenn man sie richtig
anwendet.

Statt  ^0#if defined(...)^5  geht  es  auch krzer, indem man ^0#ifdef ...^5 schreibt.
Wenn man jedoch #if verwendet, sind auch komplexere  Varianten  m”glich,  etwa
^0#if KONSTANTE == 1^5 .

Naja, das war viel auf einmal, stimmt's?  Aber wenn wir so weiter machen, sind
wir n„chste oder bern„chste Folge mit den Grundkenntnissen der Programmierung
in C fertig. Dann k”nnen wir uns ruhig und entspannt zurcklehnen oder gr”hlen
oder - was der eigentliche Sinn und Zweck von dem Ganzen ist - uns hocherfreut
auf  das  Programmieren  strzen  und  endlich  meine  ganzen  Theoriestunden-
Artikelchen aus den vorigen, diesem und nachfolgenden Hugi(s) kapieren.

^1                                  Euer Adok.

^3(Na, wie ihr seht,  habe ich schon diesen Kursteil fast komplett berarbeitet.
^3Hope  u  enjoy it... Er ist jetzt wohl doppelt so lang geworden, wie er vorher
^3war, und beinhaltet alles, was fr  die  n„chsten  drei  Folgen  geplant  war.
^3Verst„ndlich  genug  isses  doch,  oder?  Schlieálich seid ihr keine absoluten
^3Anf„nger mehr.)