^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 strzen wir uns in eine weitere Schlacht, eine neue Folge unseres C-Kurses! Diesmal geht's, wie angekndigt, 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 ntzlichere 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 fr 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 fr 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 fr 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 mssen natrlich 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 fnf!!!" Falsch, ihr Schlaumeier, zu frh 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 durchgefhrt. 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 (fr 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 wrde die Schleife endlos laufen! Genauso gibt's natrlich auch Unterl„ufe (Zahl ist 0, und wir ziehen immer noch was ab.). Solche šberlaufph„noneme treten natrlich 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 fr Zahlenvariablen. ABER: Er ist sehr fehleranf„llig! Deshalb wrde 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 ausfhrlich darber 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 krzere 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 zurcksetzen ^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 fnf, 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 ausgefhrt, 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 (fr 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 Verknpfungen 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 fr TRUE hierbei ^4-1^5 zurck. 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 ausgefhrt. Falls vorhanden, wird zum else-Zweig gesprungen. Ist vary dagegen ungleich 0, so ist die Bedingung erfllt. 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 erfllen 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 zurckliefert, 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 fr einen Puffer? Den Tastaturpuffer, den der Tastaturinterrupt verwendet, jedenfalls sicher nicht. :)) Trotzdem funzt es bei den in C eingebauten Befehlen. Fr 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 ausgefhrt. 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 hierfr 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 ntzlich 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 ausgefhrt. 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 durchgefhrt, 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 Rckgabewert 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 fr 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! Natrlich 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 fr 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 fr nichtig erkl„rt. ø6+++ ^1Tern„rer Operator ø6+++ Naja, darf's noch ein Operator mehr sein? if l„át sich n„mlich abkrzen, wenn es darum geht, je nach Erfllung einer Bedingung einer Variablen einen bestimmten Wert zuzuweisen. In C gibt es einen eigenen Operator dafr! 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 krzer: ^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 geprft, 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 "Textbersetzer". 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 natrlich 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, abkrzen. 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 rckg„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 fr den Compiler lesbare Form umgewandelt worden ist, wird der Compiler aufgerufen und weiter geht's. ^4Weitere ntzliche 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 fr 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 fr sein System! Soviel zu der Portabilit„t von C-Programmen, wenn man sie richtig anwendet. Statt ^0#if defined(...)^5 geht es auch krzer, 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 zurcklehnen oder gr”hlen oder - was der eigentliche Sinn und Zweck von dem Ganzen ist - uns hocherfreut auf das Programmieren strzen 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 fr die n„chsten drei Folgen geplant war. ^3Verst„ndlich genug isses doch, oder? Schlieálich seid ihr keine absoluten ^3Anf„nger mehr.)