Eerste stappen in C. Een typisch programma in C en C++ bestaat uit een aantal onderdelen: /*
Alles wat op meerdere lijnen staat zoals hier is commentaar. */ // Dit is commentaar op 1 lijn. Geldig tot einde van de lijn.
// Eerste deel: include van een aantal header bestanden: #include <stdio.h> /* getchar, putchar, printf, … */ #include <stdlib.h> /* om exit te kennen */ #include <math.h> /* abs,labs,pow,sqrt, sin, cos, tan */ #include
/* om maxint te kennen */ #include /* om kbhit te kennen */ #include <string.h> /* strcpy, strcmp, strcat, strlen */ #include /* voor isupper, isdigit, toupper */ /* idem : islower, tolower */ #include /* C++ functies cin en cout */ // Tweede #define #define #define
deel: definitie van “constanten”: PI 3.14159265358979 max(i,j) i>j?i:j min(i,j) i<j?i:j
// Derde deel: Opsomming van eigen geschreven functies: // Vierde deel: hoofdprogramma (moet main noemen!!): int main() { // Hier staat het programma while (!kbhit()); exit((int)0); } // Vijfde deel: De code van de eigen geschreven functies: We zullen zeer dikwijls de I/O functies cin en cout gebruiken. Deze zijn C++ functies. Ze zijn echter de enige C++ functies die we zullen gebruiken. Omdat we het dit jaar echter toch niet over objecten zullen hebben, blijf ik spreken over C, goed wetende dat het eigenlijk C++ code is die we schrijven.
Een eerste C programma: #include
// De preprocessor zal dit bestand invoegen.
void main() { int a, b, c;
// declaratie van 3 gehele getallen < 32000
cout << “Geef twee getallen:”; // output cin >> a >> b; // input. Let op: eol nog in inputbuffer cin.get(); // lees eol: entertoets cout << endl; // begin nieuwe lijn c=a+b; cout << “De som van “ << a << “ en “ << b << “ is “ << c << endl; cout << “Het produkt van “ << a << “ en “ << b << “ is “ << a*b; // gebruik var’s en uitdrukking in uitvoer. cin.get(); // wacht op entertoets } Let op de ; na elk bevel. Een tekst staat steeds tussen “ “. Bijvoorbeeld: “PC” is een tekst (string) bestaande uit drie tekens: namelijk de P en de C en een speciaal teken ‘\0’ om het einde van de tekst te kenmerken. Eén teken staat tussen ‘ ‘. Bijvoorbeeld ‘P’ is één teken. cin.get() dient om de uitvoering van het programma te onderbreken, zodat we de uitvoer kunnen bestuderen. Het programma wacht dan op een aanslag van de <enter> toets. Preprocessor directieven beginnen met een # . Het gevolg van het #include bevel is dat dit bestand (iostream.h) zal gekopieerd worden samen met de rest van de code in een intermediair bestand, dat nadien door de compiler zal gecompileerd worden. Na de preprocessor, werkt de compiler en dan de linker. Deze laatste kan afzonderlijk gecompileerde programmaonderdelen samenvoegen. Een header bestand (zoals iostream.h) wordt gebruikt om er voor te zorgen dat de compiler kan nagaan of de opgeroepen functies juist gebruikt worden: het juiste aantal parameters van het juiste type. Indien men daartegen een doodzonde doet, zal de compiler stoppen met compileren en foutboodschappen genereren. Header bestanden hebben als extensie steeds: .h Het hoofdprogramma heeft een type. Default is dit het type int. Dit geeft het de mogelijkheid een geheel getal naar het operating systeem te sturen. Men kan evenwel ook het type void gebruiken. Men doet dit wanneer men helemaal niets naar het operating systeem wenst te sturen.
Een tweede C programma: #include void main() { char naam_1[20], naam_2[20]; // Declaratie van twee rijen, 20 tekens lang. // In C moet de maximale lengte van een string bij compilatie gekend zijn!! // We kunnen spreken over naam_1[0] tot naam_1[19]. int leeftijd_1, leeftijd_2; cout << "Wat is de naam van de eerste persoon" << endl; cin.getline(naam_1,20); // Lees max. 20 tekens in naam_1 // eol is gelezen! cout << "Wat is zijn/haar leeftijd; " << '\n'; // endl en ‘\n’ zijn equivalent. endl is C++ cin >> leeftijd_1; // eol nog in inputbuffer cin.get(); // lees eol cout << "Wat is de naam van de tweede persoon" << endl; cin.getline(naam_2,20); // eol gelezen cout << "Wat is zijn/haar leeftijd; " << '\n'; cin >> leeftijd_2; // eol nog in inputbuffer cin.get(); // lees eol cout << "De personen " << naam_1 << " en " << naam_2 << " zijn samen " << (leeftijd_1 + leeftijd_2) << " jaren oud." << '\n'; cin.get();
// lees eol
} Merk op dat: Maar:
cout << “1 + 9” als uitvoer heeft: 1 + 9. (=string!) cout << (1 + 9) als uitvoer de waarde 10 heeft.
cin haalt tekens uit de invoerbuffer en stuurt deze door naar de gewenste variabelen. Wanneer één getal ingelezen wordt, staat daarna in de invoerbuffer waarschijnlijk de endl. Deze wordt door de cin niet gelezen. Als men daarna een string zou wensen in te lezen, zou deze onmiddellijk nog dat endl teken in de invoerbuffer zien staan en dus een lege string veronderstellen. Dat was waarschijnlijk niet de bedoeling. cin.get() kan dan het <enter> teken wel uit de buffer halen.
cin.get() haalt echter slechts één teken uit de invoerbuffer. Om er zeker van te zijn dat hij helemaal leeg is, moet hij de invoerbuffer via het programma leeg gemaakt worden door te lezen totdat men aan het teken van de <enter> toets komt. Dit kan bijvoorbeeld aan de hand van een functie clearbuf(). Men kan deze implementeren in het startprogramma als volgt: // Eerste deel: include van een aantal header bestanden: #include /* C++ functies cin en cout */ // Tweede #define #define #define
deel: definitie van “constanten”: PI 3.14159265358979 max(i,j) i>j?i:j min(i,j) i<j?i:j
// Derde deel: Opsomming van eigen geschreven functies: void clearbuf(void); // Vierde deel: hoofdprogramma (moet main noemen!!): int main() { // Hier staat het programma while (!kbhit()); exit((int)0); } // Vijfde deel: De code van de eigen geschreven functies: void clearbuf(void) { char ch; // ch MOET van het type char zijn do cin.get(ch); // als ook de <enter> toets moet while (ch!='\n'); // ingelezen worden!! (overloading) } De vorige twee programma’s werken nóg beter wanneer alle cin.get(); bevelen worden vervangen door clearbuf(); bevelen. Men moet dan wel voor het hoofdprogramma de functie clearbuf kenbaar maken en achter het hoofdprogramma deze functie echt noteren. Allicht is dit beter voor alle voorbeelden van het boek! Wanneer men in het tweede voorbeeldprogramma als leeftijd van de eerste persoon een getal geeft, gevolgd door een aantal blanco’s, zal de versie zoals hierboven genoteerd falen. De naam van de tweede persoon wordt niet gevraagd! Wanneer men de functie clearbuf() gebruikt, werkt het programma wel exact!
Variabelen en hun types. De gekende types zijn: • char : Eén teken. Wordt bijgehouden in één byte. • int : Geheel getal van 2 of 4 bytes (niet gespecificeerd.) • short int : geheel getal van 2 bytes • short : idem short int • long int : geheel getal van 4 bytes • long : idem long int • float : reëlgetal van 4 bytes • double : reël getal in dubbele nauwkeurigheid (8 bytes?) • long double : reël getal in viervoudige nauwkeurigheid Een functie van het type void is een functie die geen resultaat naar het oproepende programma stuurt. De functie clearbuf() is daarvan een voorbeeld. Unsigned types: unsigned int zijn gehele getallen die niet negatief worden. Voor een int is het bereik van de waarde van -32.768 tot +32.767. Voor een unsigned int van 0 tot 65.535. Je kan hetzelfde doen voor een char: een unsigned char loopt van 0 tot 255.
Tijdens de bewerkingen gebeuren er automatische typeconversies: C kiest als type steeds het meest beduidende type. Bij een double plus een int wordt de int een double. Als opsomming van meest naar minst beduidend geldt: • long double • double • float • long • int • char Men kan de typeconversie forceren met een cast: als a een double is, is (int)a een integer. Namen van variabelen moeten aan de normale eisen voldoen: • niet beginnen met een getal • geen blanko’s bevatten • case sensitive: A en a zijn twee verschillende variabelen • Twee verschillende variabelen moeten een verschil in de naamgeving hebben in de eerste 32 tekens. • Mag _ bevatten.
Een variabele kan men initialiseren tijdens de declaratie als volgt: int a=10; Natuurlijk doet: int a; a=10; bijna hetzelfde, naar in het tweede geval wordt a gelijk aan 10 tijdens de uitvoering van het programma. In het eerste geval is het reeds tijdens de compilatie.
Operatoren. • + • • * • / • % (= rest van een deling) Let op: 2/3*100=0 : eerst wordt 2/3 berekend en er wordt afgekapt!! Speciale operatoren: • c++ • ++c • c-• --c • c*=b
is hetzelfde als c=c+1 (maar postincrement) is hetzelfde als c=c+1 (maar preincrement) is hetzelfde als c=c-1 (maar postdecrement) is hetzelfde als c=c-1 (maar predecrement) is hetzelfde als c=c*b (* mag zijn: + - * / )
Maar: main() { int i, j, k, l, c; c=0; // c i=c++; // i j=++c; // j k=c--; // k l=--c; // l }
= = = = =
0 0 2 2 0
en en en en
c c c c
= = = =
1 2 1 0
Constanten. Men kan aan een variabele vanzelfsprekend een constante waarde geven. Voorbeelden kan men hierboven vinden. Het kan echter gewenst zijn een speciaal “type” aan een constante te geven. Stel dat men bijvoorbeeld de waarde 7 aan een long int wenst toe te kennen. Dan is de 7 best ook een “long int”. Men heeft volgende mogelijkheden: • • • • • • •
7 7L 7U 7UL 7. e1 7.f 0x10
naar een int naar een long int unsigned int unsigned long int wetenschappelijke notatie (waarde is 70) voor een float of double of long double. (waarde is 7.) hexadecimale schrijfwijze (waarde is 16)
Men kan ook de preprocessor gebruiken om constanten goed toegankelijk te houden. Een voorbeeld: #define
PI
3.14159265358979
Als in een uitdrukking staat : omtrek = PI*2.*straal; zal de preprocessor er van maken: omtrek=3.14159265358797*2.*straal. Dit is handig om de lengte van rijen goed aanpasbaar te houden. Men kan bovenaan het programma een (aantal) constante(n) noteren met hun waarden. Deze is bijvoorbeeld de lengte van een rij getallen. Verder in het programma gebruikt men deze constante. Indien de lengte te klein blijkt, moet alleen op de plaats van het preprocessordirectief de waarde aangepast te worden. Voor dit soort “constanten” zal men als regel (die niet moet gevolgd worden, maar het is wel wenselijk voor de leesbaarheid en iedereen doet het) hanteren dat deze namen in hoofdletters gebruikt worden. Dit om ze te onderscheiden van de gewone variabelen.
Men kan ook van een variabele zeggen dat hij niet van waarde mag veranderen als volgt: const int a; Dit is natuurlijk geldig voor om het even welk type van variabele.