Programmer En in C#

download Programmer En in C#

of 38

Transcript of Programmer En in C#

Programmeren met C#

R. van der Veer, F. Sariedine Opleiding Informatica, afdeling Engineering NHL Hogeschool 1e druk najaar 2010

Inhoudsopgave1. C# VERKE 1.1 1.2 1.3 1.4 1.5 1.6 2 E ......................................................................................................................................... 3

WAT IS C#?.............................................................................................................................................. 3 HOE KAN IK C# GAAN GEBRUIKEN? ......................................................................................................... 3 C# VOOR HET EERST GEBRUIKEN.............................................................................................................. 4 DATATYPEN ............................................................................................................................................. 7 VARIABELEN ............................................................................................................................................ 7 REKENEN MET C# .................................................................................................................................... 9

LIJSTE ...................................................................................................................................................... 11 2.1 2.2 2.3 2.4 2.5 2.6 ARRAYS (ALGEMEEN) ............................................................................................................................ 11 ARRAYLIST (COLLECTION BASED TYPE) ................................................................................................ 12 STATISTIEK OP LIJSTEN .......................................................................................................................... 13 EXTRA: STATISTIEK OP LIJSTEN M.B.V. EEN GENERIC TYPE LIST .......................................................... 14 LIJSTCOMPREHENSIES MET LINQ .......................................................................................................... 15 DUBBELE LIJSTCOMPREHENSIES ............................................................................................................ 16

3.

BESLISSI GSSTRUCTURE E HERHALI GE ............................................................................ 21 3.1 3.2 3.3 3.4 3.5 ALGEMEEN ............................................................................................................................................ 21 INGEWIKKELDE BESLISSINGEN ............................................................................................................... 21 HERHALINGEN DE FOR LUS .................................................................................................................. 23 HERHALINGEN HET FOREACHIN STATEMENT ................................................................................... 23 HERHALINGEN DE WHILE LUS.............................................................................................................. 24

4.

METHODE I C#.................................................................................................................................... 27 4.1 4.2 4.3 ALGEMEEN ............................................................................................................................................ 27 COMPLEXERE METHODEN ...................................................................................................................... 29 MEERDERE VERSIES VAN METHODEN ..................................................................................................... 30

5.

CLASSES, EE I LEIDI G .................................................................................................................... 32 5.1 5.2 ALGEMEEN ............................................................................................................................................ 32 NAAMGEVING BINNEN C# ...................................................................................................................... 34

Programmeren met C#

2

1.

C# Verkennen

1.1 Wat is C#?C# is een zeer dynamische, krachtige object georinteerde programmeertaal ontwikkeld door Microsoft. C# beschikt over de kracht, evenals sommige andere talen, om onervaren mensen programmeren te leren. De taal (syntax) lijkt op het eerste gezicht complex, maar na enige gewenning wordt de taal intutief. Verder blijkt C#, maar zeker de ontwikkelomgeving (Visual Studio van Microsoft), het je mogelijk te maken om in een zeer kort tijdsbestek krachtige en goed werkende programmas te laten schrijven. Bovendien is de Express versie van Visual Studio gratis, maar vergt wel een activatie, en is te downloaden vanaf de website: http://www.microsoft.com/express/Downloads/

1.2

Hoe kan ik C# gaan gebruiken?

Let op: Onderstaande tekst is alleen van toepassing wanneer je C# op je laptop of eigen pc wilt gaan installeren. Op de werkstations die je in de studielandschappen en de practicumzalen aantreft, staat Microsoft Visual Studio 2010 Ultimate (de meest uitgebreide variant van de ontwikkelomgeving) reeds voor genstalleerd. Allereerst dien je het programma te downloaden bij de bovengenoemde link. Je kunt op deze pagina kiezen uit diverse talen, kies wel de taal C#. Mocht je genteresseerd zijn, de overige talen in haar Express varianten kunnen naast C# Express worden genstalleerd. Deze paragraaf behandeld alleen de installatie van C# Express 2010, wat ten tijde van het schrijven van dit document de meest recente versie is. Desalniettemin zal het installatieproces van de Express versies gelijk zijn aan voorgaande versies (zoals bijv. C# Express 2008). Wanneer je op de link Visual C# 2010 Express klikt (zie figuur 1.1), krijg je de keuze uit een installatietaal. Kies hiervoor de Engelse taal, of een andere indien je dit wenst (en kunt lezen). Binnen het onderwijs zal voornamelijk naar de Engelstalige versie verwezen worden. Een Nederlandse versie ontbreekt nog, maar dat mag niet uitmaken. Zodra je een taalkeuze hebt gemaakt, wordt je doorverwezen naar een website specifiek voor het downloaden van C# 2010 Express. Dit deel van de website herinnert je eraan dat je een geldig e-mailadres op dient te geven waar de eenmalige activatiecode naartoe wordt gestuurd. Nagenoeg tegelijkertijd wordt gepoogd een executable (uitvoerbaar bestand) te downloaden wat feitelijk een webinstaller is.

Figuur 1.1 Schermweergave van de website van Microsoft.

Programmeren met C#

3

Doorloop het installatieproces en installeer het pakket zoals het zelf aangeeft. Een vooraanstaande informaticus zoals jullie dient dat eenvoudig te kunnen.

1.3

C# voor het eerst gebruiken

C# kun je starten door middels het menu start de applicatie Microsoft Visual Studio 2010 Express te kiezen, en daaruit de snelkoppeling Microsoft Visual Studio 2010 Express. Als het goed is krijgen jullie dan het startscherm te zien wat is weergegeven in figuur 1.2.

Figuur 1.2

Startscherm van Microsoft Visual Studio C# 2010 Express.

In dit startscherm staan een aantal opties gekozen. Bij aanvang beschik je nog niet over bestaande projecten (tenzij je eerder met voorgaande Express versies hebt gewerkt) en is het voor de hand liggend dat je opteert voor New Project. Aangezien we eerst de basisbeginselen van het programmeren onszelf meester willen maken, kies je voor Console Application zoals weergegeven in figuur 1.3. In een later stadium gaan we ook zeker aan de slag met Windows applicaties, bij de modulen Programmeren 2 en 3 zullen we zelfs nagenoeg alleen Windows applicaties ontwikkelen.

Figuur 1.3 Project keuze

Programmeren met C#

4

Vul bij het vak Name een betere naam in dan ConsoleApplication1. Normaliter is de naam van een project ook de naam voor je uitvoerbare bestanden of project, dus kies voor een juiste naamgeving. Druk daarna op de OK knop. Dan zal de ontwikkelomgeving een template creren waarin je kunt gaan programmeren, dus de feitelijke ontwikkelomgeving. Figuur 1.4 geeft aan wat dit voor omgeving is. Tijdens de lessen zal hier meer over worden getoond.

Figuur 4 De ontwikkelomgeving van Visual Studio C# Bij Object Georinteerde Programmeertalen draait het ontwikkelen, lees programmeren, om de creatie van objecten. Je ontwikkeld als het ware zelf de bouwstenen voor een applicatie. Daarover volgt later meer, maar vooralsnog heb je deze kennis wel even nodig om de structuur van de taal te begrijpen. Een object is vaak een class, hier heeft Visual Studio (VS) zelf al een class aangemaakt met de naam Program. Hierna volgt wat heet een definitie van een methode. Een class bestaat altijd uit 0 of meer methoden, welke de class functionaliteit geven. Bij een Console Applicatie is er altijd een methode met de naam static void Main(string[] args) wat tussen de { en } code kan bevatten wat altijd wordt uitgevoerd bij het compilen en runnen van je programma (middels F5 of de play-knop). De exacte betekenis van de methode naam, de zogeheten keywords static, void, string, [] volgt later in dit dictaat en tijdens de lessen. Ook de using statements en de namespace wordt later uitgelegd. Tijd om eens een eerste programma te testen. Wanneer je bij bovenstaande programma (zonder iets in te hebben getypt) op F5 drukt, zorgt de ontwikkelomgeving ervoor dat je code wordt omgezet en vertaald naar code wat door het .NET Framework kan worden uitgevoerd. Echter zal de uitvoering slechts een flits van een zwart console venster laten zien en daarna terugkeren naar de ontwikkelomgeving. Type eens de code zoals weergegeven in figuur 1.5.

Programmeren met C#

5

Figuur 1.5 De eerste code toevoegen... Zoals je hierboven in figuur 1.5 kunt zien, zijn twee regels code toegevoegd. Een regel code noemt men formeel statement en wordt in de meeste gevallen afgesloten met een ;. De regel Console.WriteLine(Hello World!); zorgt ervoor dat de tekst Hello World! op de console wordt afgedrukt. Om te voorkomen dat het scherm meteen afsluit, heeft de programmeur in deze applicatie ervoor gekozen om op een signaal van het toetsenbord te wachten, in dit geval een enter. Alle overige toetsen worden getoond in je console venster. Dit statement luidt: Console.ReadLine(); Nu heb jij je eerste programma gemaakt, wat iedere programmeur altijd poogt in een voor hem of haar nieuw te leren taal. Tijd om specifieke kennis op te gaan doen.

Programmeren met C#

6

1.4

Datatypen

Een (data-)type geeft aan wat een variabele (zie 1.5) moet gaan bevatten. Er zijn diverse soorten datatypen en later zullen we leren dat we ze ook zelf kunnen ontwikkelen. Hier een klein overzicht van de datatypen die we in het begin veelal zullen gebruiken, al zijn de voorbeelden nog niet specifiek gekoppeld aan een variabele:

Datatype: int

Omschrijving: Een variabele van het type int, bevat enkel en alleen gehele getallen (zowel positief als negatief). Bijvoorbeeld: 1, -1, 0, 999. float Een variabele van het type float, kan naast gehele getallen ook kommagetallen (rele getallen) bevatten (zowel negatief als positief) maar wordt altijd gevolgd door een f. Bijvoorbeeld: 1.0f, -1.1f, 0f, 10f, etc. bool Een variabele van het type bool is een variabele die alleen een waarheid kan bevatten. Iets is onwaar (false) of waar (true), derhalve is dit ook de enige opslag. string Een variabele van het type string bevat een reeks karakters voorafgegaan aan een dubbele quote () en afgesloten met een dubbele quote. Bijvoorbeeld Hello World is een string. char Een char(-acter) is een type wat enkel en alleen 1 karakter kan bewaren en wordt altijd voorafgegaan aan een enkele quote (apostrof ()) en afgesloten met een enkele quote. Bijvoorbeeld: H is een char. Figuur 1.6 De basis typen waarmee geprogrammeerd gaat worden. Datatypen worden altijd als eerste getypt voordat men een variabelennaam typt. Dat brengt ons bij de volgende paragraaf.

1.5

Variabelen

Een variabele in C# wordt altijd voorafgegaan aan een datatype. Op deze manier dwingt C# je tot het declareren van een variabele waarin maar n soort datatype kan worden opgeslagen. Derhalve valt C# onder de familie der getypeerde talen. Python bijvoorbeeld is een ongetypeerde taal, evenals bijvoorbeeld PHP. Het intypen van een datatype gevolgd door de naam van een variabele noemt men declareren. Een variabele declareren gaat als volgt (vergeet de ; niet!) en hoeft slechts 1 maal te worden gedaan binnen een methode, of wanneer dit een classvariabele is (hierover later meer): string woord; of int getal;

Programmeren met C#

7

Een variabele declareren en meteen een waarde geven (initialiseren) kan ook: string woord = Hallo; of int getal = 10; Je kunt variabelen ook aan elkaar toekennen: string woord = Hallo; string woord2 = woord; //Dit is commentaar: woord2 bevat nu Hallo; Talen ondersteunen ook het leveren van commentaar. Commentaar wordt niet meegecompileerd, maar dient als ondersteuning voor een programmeur. Commentaar kan men herkennen aan // gevolgd door tekst. Variabelen en datatypen vormen een zeer belangrijke basis voor het programmeren. Zonder hen kun je feitelijk geen programma maken in C#.

Figuur 1.7 Voorbeeld 1: Toepassing van een datatype, variabele en het gebruik daarvan op basis van het Hallo wereld voorbeeld. Figuur 1.7 toont het gebruik, als voorbeeld, van een datatype, variabelenaam en toekenning in 1 statement. Vervolgens wordt de toegekende waarde van de variabele op het scherm getoont middels Console.WriteLine. Dit is mogelijk aangezien Console.WriteLine als argument (dat wat tussen haakjes staat) een variabele van het type string verwacht. TIP: Samengevat dient men het statement string woorden = Hallo wereld; te lezen als: De variabele met de naam woorden, is van het type string en bevat nu de waarde Hallo wereld.

Programmeren met C#

8

1.6

Rekenen met C#

Een programmeertaal zoals C# is ook geschikt om (al dan niet complexe) berekeningen uit te voeren. Hier heb minimaal 1 variabele voor nodig, of constanten en sowieso een rekenkundige operator (bijvoorbeeld *). const int getal = 20; (Lees: Er is een constante variabele met de naam getal welke alleen gehele getallen kan bevatten en waarbij de waarde is vastgesteld op 20.) Een constante, herkenbaar aan het keywoord const, zorgt ervoor dat een variabele nooit een andere waarde kan aannemen. Ook niet als de programmeur dat zou willen. Vandaar de naam constant (onveranderlijk).

Figuur 1.8 Rekenvoorbeeldje geprogrammeerd met 2 variabelen. Rekenen werkt zoals gezegd met waarden en operatoren. In Figuur 1.8 is een voorbeeld gegeven waarin twee variabelen staat (getal1 en getal2) welke geinitialiseerd zijn met een waarde. Dankzij de dynamiek van C# (wordt uitgelegd bij de module Programmeren 2) is het mogelijk dat de methode WriteLine van de class Console behalve strings ook gehele getallen op het scherm kan tonen. Console.WriteLine(getal1 * getal2); zal dan ook 200 op het scherm tonen. De operatoren om mee te rekenen zijn onder andere: + += -= * *= / /= % %= Math.Sqrt() Math.Pow( , )

Programmeren met C#

9

Voorbeelden (eenmalige declaratie van de variabele getal3 volstaat hier): int getal3 = getal1 + getal2; getal3 = getal1 getal2; getal3 = getal1 * getal2; getal3 = getal2 / getal1; getal3 = getal2 % getal1; // // // // // 10 10 10 20 20 + * / % 20 20 20 10 10 = = = = = 30, dus getal3 = 30 -10, dus getal3 = -10 200, dus getal3 = 200 2, dus getal3 = 2 0, dus getal3 = 0

NB: % betekent modulo en levert de restwaarde na een gehele deling. += (plus wordt) is een verkorte schrijfwijze om te zeggen dat je een waarde bij zichzelf optelt ( getal3 += 1 is dus feitelijk te lezen als getal3 = getal3 + 1). Geavanceerde (bitwise) operatoren: >> lijst[x + 1] select lijst[x]; De verwachte uitkomst is correct, alleen de waarde 20 wordt op het scherm getoond. Anders geschreven (met zogeheten lambda-expressies): var newlist2 = Enumerable.Range(0, lijst.Length 1) .Where( x => lijst[x] > lijst[x+1]) .Select( x => lijst[x]); Wellicht is de eerste optie mooier en iets begrijpelijker te lezen, ze doen beiden hetzelfde (let wel op de syntactische verschillen zoals punten, hoofdletters en de lambda-expressie (=>)).

2.6

Dubbele lijstcomprehensies

Sommige talen kunnen heel erg functioneel omspringen met data. Vooral Python (en amanda voor Discrete Wiskunde) gaat heel soepel en krachtig om met ook dubbele lijstcomprehensies. De volgende code kunnen jullie toevoegen aan een bestaand project (liefst onder de namespace, maar boven de class Program). /// /// Helper class which contains the data for our grade system. /// class Cijfers { /// /// Auto-implemented properties (more info will follow) /// public string student { get; set;} public string vak {get; set;} public int cijfer {get; set;} } Bovenstaande code is een nieuw object (class) met daarin drie eigenschappen (properties) die we als variabelen kunnen gebruiken. Het doel van dit zelf ontworpen object, is voornamelijk het bewaren van een naam, de naam van een vak en het bijbehorende behaalde cijfer. In Python kan dit met een zogeheten triple, om onnodig moeilijk programmeerwerk te voorkomen, is gekozen voor deze tijdelijke oplossing. Het doel van de opdracht die we hieronder gaan beschrijven, is het bijhouden van een overzicht van door een student op een bepaald vak behaald resultaat. Op deze lijst kunnen we statistiek toepassen aan de hand van zogeheten dubbele lijstcomprehensies. Echter is daar wat voorwerk voor nodig, wat hier voor jullie is voorgedaan.

Programmeren met C#

16

In de class Program gaan we nu ook extra code plaatsen, wat ons helpt de cijferlijst te voorzien van gegevens. class Program { private static List cijfers = new List(); ... ... //Meer code! } Wat hierboven staat is een globale (klasse) variabele van het type List. Deze List is geoptimaliseerd voor het gebruik van onze eerder gemaakte Cijfer class. De naam van de variabele is cijfers. Het initialiseren volgt achter het = teken. Deze variabele is toegankelijk binnen de gehele class Program, wat ons doel uiteindelijk ook zal zijn. De variabele cijfers bevat straks alle resultaten, modulen en namen van studenten. Voeg ook deze methode toe, de belangrijkste want hier wordt alles vanuit aangeroepen: static void Main(string[] args) { PopulateListComprehension(); }

//Hulpmethode

Het statement PopulateListComprehension(); is de aanroep naar de methode die er zo uit ziet: private static void PopulateListComprehension() { //Data alvast invullen AddDataToGradeList(ref cijfers, "jan", "wiskunde", 3); AddDataToGradeList(ref cijfers, "piet", "wiskunde", 8); AddDataToGradeList(ref cijfers, "jan", "natuurkunde", 7); AddDataToGradeList(ref cijfers, "klaas", "wiskunde", 9); AddDataToGradeList(ref cijfers, "jan", "wiskunde", 5); AddDataToGradeList(ref cijfers, "katrijn", "wiskunde", 6); AddDataToGradeList(ref cijfers, "jan", "wiskunde", 6); AddDataToGradeList(ref cijfers, "piet", "programmeren 1", 8); AddDataToGradeList(ref cijfers, "piet", "natuurkunde", 5); //Display the filled list on the console window foreach (Cijfers cijfer in cijfers) Console.WriteLine("{0} heeft voor {1} een {2} behaald.", cijfer.student, cijfer.vak, cijfer.cijfer); Console.ReadLine(); }

De aanroep voor het toevoegen van gegevens gaat zo: AddDataToGradeList(ref cijfers, "jan", "wiskunde", 3); . Hierbij is AddDataToGradeList een hulp methode voor het toevoegen van gegevens. Dit helpt ons in het beperken van de hoeveelheid code.

Programmeren met C#

17

Deze methode ziet er zo uit: private static void AddDataToGradeList(ref List cijferLijst, string naam, string vak, int cijfer) { Cijfers info = new Cijfers(); info.student = naam; info.vak = vak; info.cijfer = cijfer; cijferLijst.Add(info); } Cijfers info = new Cijfers(); declareert en initialiseert ons eigen gemaakte class (object). Dit zorgt ervoor dat we bij de properties (eigenschappen) van dit object kunnen. Het toekennen van een waarde aan zon property gaat nu eenvoudig zoals bijv. info.student = naam; Wanneer alle eigenschappen zijn voorzien van een waarde, kunnen we het behaalde resultaat (nu is alles opgeslagen in de variabele info) toevoegen aan de cijferlijst (zie parameters van de methode (ref List cijferlijst, ). Al deze methoden initialiseren en vullen de cijferlijst. Nu kunnen we ook kijken wat de resultaten van Jan voor het vak Wiskunde zijn geweest via een (enkele) lijstcomprehensie: private static void CijfersJanWiskunde() { var resultatenWiskunde = from cijfer in cijfers where cijfer.student == "jan" && cijfer.vak == "wiskunde" select cijfer.cijfer; foreach (int cijfer in resultatenWiskunde) Console.Write(cijfer + ","); Console.WriteLine(); } Of het hoogste cijfer van Jan voor Wiskunde: private static void HoogsteCijferJanWiskunde() { var resultatenWiskunde = from cijfer in cijfers where cijfer.student == "jan" && cijfer.vak == "wiskunde" select cijfer.cijfer; var hoogsteCijfer = resultatenWiskunde.Max(); Console.Write("Hoogste cijfer Jan voor wiskunde: " + hoogsteCijfer); Console.WriteLine(); } Stel we willen nu van alle studenten het hoogste cijfer voor wiskunde weten:

Programmeren met C#

18

Dat kan aan de hand van de volgende methode met daarin een dubbele lijstcomprehensie: private static void AlleStudentenHoogsteCijferWiskunde() { var resultatenWiskunde = from grade in cijfers where grade.vak == "wiskunde" group grade by grade.student into c select new { Student = c.Key, Wiskunde = c.Max(g => g.cijfer) }; foreach (var resultaat in resultatenWiskunde) Console.WriteLine("{0} heeft voor wiskunde als hoogste resultaat een {1}", resultaat.Student, resultaat. Wiskunde); Console.WriteLine(); } De magie zit hier in het stukje code wat alle resultaten in de variabele resultatenWiskunde stopt. Even stap voor stap de uitleg: from grade in cijfers Zorgt ervoor dat alle cijfers (inclusief studentnaam, vak en cijfer) uit de lijst cijfers worden gehaald en in grade gestopt; where Grade.vak == wiskunde beperkt de volgende statements, opdat alleen die resultaten worden vergeleken waar het het vak wiskunde betreft. group grade by grade.student into c groepeert de resultaten op student. Ieder resultaat van elke student wordt zo gegroepeerd bij de naam van de student. Deze verzameling (naam, vak en cijfer) wordt bewaard in een nieuwe variabele genaamd c (voor cijfer). select new { Student = c.Key, Wiskunde = c.Max( g => g.cijfer) }; creert de output welke daadwerkelijk in de variabele resultatenWiskunde gestopt wordt. Doordat de groepering op studentnaam, vak en cijfer heeft plaatsgevonden en in c gestopt is (met een ordening op de naam van de student), kun je de eigenschap Key nemen als waarde. Deze bevat toevalligerwijs ook de feitelijke studentnaam. Uit alle cijfers voor het vak wiskunde voor deze student wordt via de methode Max, het hoogste resultaat voor wiskunde opgeslagen. Doordat we nu een nieuwe lijst hebben aangemaakt met twee verschillende datatypen, bestaat de var resultatenWiskunde zogeheten anonymous types. Voor het tonen van de gegevens (in de foreach loop) wordt dan ook wederom een var gebruikt i.p.v. een datatype zoals bijv. string of int. Meer informatie over LINQ kun je vinden op: http://msdn.microsoft.com/en-us/vcsharp/aa336746.aspx

Programmeren met C#

19

Opgave 1 (aftekenen in practicum):Bij metingen is het gebruikelijk om extreme waarden weg te laten. Haal bij de onderstaande lijst meetwaarden de extremen weg en bereken dan nogmaals het gemiddelde en de standaarddeviatie, zoals eerder is voorgedaan in dit dictaat. float[] meetwaarden = { 0.4f, 0.5f, 0.3f, 0.7f, 0.6f, 0.6f, 0.4f };

Opgave 2 (aftekenen in practicum):Formuleer de volgende vragen in C#: 1. Geef een lijst van alle kwadraten van 1 t/m 100 (d.w.z. [1,4,9, 16, 25, ]). 2. Geef een lijst van alle oneven kwadraten van 1 t/m 100 (d.w.z. [1, 9, 25, ]). 3. Geef een lijst met alle delers van het getal 100 ( d.w.z. [1, 2, 4, 5, 10, ]) Hint: Een getal x is deelbaar door y als x % y == 0 (% geeft de rest van een deling) 4. Geef alle priemgetallen tussen 2 en 100 (d.w.z. [2,3,5,7,11, ]). Hint: Een getal is een priemgetal als de lijst van zijn delers de lengte 2 heeft.

Opgave 3 (aftekenen in practicum):De volgende vragen zijn gebaseerd op hoofdstuk 2.6 Dubbele Lijstcomprehensies. Test eerst of je de voorbeelden kunt overnemen en laten werken. Kom je er niet uit, vraag dan de practicumdocent om hulp. Formuleer de volgende vragen in C#, gebaseerd op de lijstcomprehensies en dubbele lijstcomprehensies en de code van hoofdstuk 2.6: 1. welke cijfers heeft Piet gehaald? (enkele lijstcomprehensie!) 2. wat is het hoogste cijfer dat Piet heeft gehaald? (enkele lijstcomprehensie!) 3. welke studenten hebben alleen maar voldoendes gehaald? (dubbele lijstcomprehensie!) HINT: Een cijfer is een voldoende als het niet voorkomt in een lijst met cijfers < 6. 4. Geef per vak het aantal afgelegde tentamens aan. (dubbele lijstcomprehensie!) HINT: Een tentamen is afgelegd als daarvoor een cijfer bekend is. De output kan er zo uit zien: Wiskunde is 5 keer afgenomen. Natuurkunde is 2 keer afgenomen. Programmeren 1 is 1 keer afgenomen.

Programmeren met C#

20

3.3.1

Beslissingsstructuren en herhalingenAlgemeen

In hoofdstuk 2 over Lijsten en Lijstcomprehensies werden al een aantal voorbeelden gegeven van (en over) beslissingsstructuren. Een beslissing geeft aan of een statement moet worden uitgevoerd of niet. Beslissingen worden genomen aan de hand van vergelijkingen. Een vergelijking in C# gaat zo: static void Main(string[] args) { int waarde = 10; //10 toekennen aan variabele if (waarde == 10) //Variabele vergelijken Console.WriteLine("De waarde is goed."); else Console.WriteLine("De waarde is niet goed."); } Soms hoeft er ook niets te worden gedaan: static void Main(string[] args) { int waarde = 9; if (waarde < 10) { //Niets hier } else Console.WriteLine("De waarde is groter dan 10."); }

3.2

Ingewikkelde beslissingen

Het kan zijn dat je meerdere vergelijkingen nodig hebt zoals: static void Main(string[] args) { int waarde = 10; if (waarde > 9 && waarde < 11) { Console.WriteLine("De waarde is goed namelijk {0}", Convert.ToString(waarde)); } else Console.WriteLine("De waarde is niet goed."); } TIP: Convert.ToString(waarde) zet een geheel getal om naar een string. Je kunt vergelijkingen dus logisch verbinden d.m.v. booleaanse logica. De operatoren hiervoor zijn: && (logic and) || (logic or) ! (not)

Af en toe is n else te weinig omdat je meerdere controles wilt uitvoeren. Stel we willen wanneer we een 1 tegenkomen deze vermenigvuldigen met 1 en wanneer we een 2 tegenkomen deze vermenigvuldigen met 12, etc:

Programmeren met C#

21

static void Main(string[] args) { float waarde = 2.0f; if (waarde == 1.0f) { waarde *= 1.5f; } else if (waarde == 2.0f) { waarde *= 12.0f; } else { waarde = 0.0f; } } Of korter geschreven met hetzelfde effect: static void Main(string[] args) { float waarde = 2.0f; if (waarde == 1.0f) waarde *= 1.5f; else { //Genest if statement if (waarde == 2.0f) waarde *= 12.0f; else waarde = 0.0f; } } Samengevat is de structuur van een beslissing binnen je programma als volgt te omschrijven: if (Conditie_1) { // Statement_1; } else if (Conditie_2) { // Statement_2; } else if (Conditie_3) { // Statement_3; } else { // Statement_n; } Later, zullen we ook leren dat we ook andere gereedschappen kunnen gebruiken voor het maken van beslissingen.

Programmeren met C#

22

3.3

Herhalingen de for lus

Herhalingen kunnen nuttig zijn bij bepaalde berekingen of simpele herhalingen zoals: static void Main(string[] args) { for (int i = 0; i < 3; i++) Console.WriteLine(i); } Bovenstaande code toont: 0 1 2 Ook het berekenen van de tafel van 20:static void Main(string[] args) { for (int i = 1; i < 11; i++) Console.WriteLine( "{0} x 20 = {1}", i, i*20 ); Console.ReadLine(); }

En for lus werkt het handigst met een integer variabele (vaak afgekort tot i van indexer) waaraan een onder- en bovengrens wordt gekoppeld. In bovenstaand voorbeeld is de ondergrens zo dat i gelijk wordt gesteld aan 1. De bovengrens is < 11, dus 10 doet nog mee. Toch mag je er ook voor kiezen de indexer en de ondergrens en bovengrens weg te laten: for ( ; ; ) { } Bovenstaand voorbeeldje is een zogeheten infinite loop. Bijzonder nuttig nietwaar?

3.4

Herhalingen het foreach in statement

Een ander soort lus, maar zeer nauw verwant aan de for lus, is het foreachin statement. Het foreach statement is ontwikkeld voor het itereren (= doorlopen) van collections. Voorbeelden hiervan heb je reeds in hoofdstuk 2 gezien (Lijsten en Lijstcomprehensies). static void Main(string[] args) { int[] fibarray = new int[] { 1, 1, 2, 3, 5, 8, 13 }; foreach (int i in fibarray) { System.Console.WriteLine(i); } } Bovenstaand voorbeeld drukt alle voorkomende getallen in de array fibarray af.

Programmeren met C#

23

In tegenstelling tot een for lus (en een while lus ook) kan een foreach statement geen data aanpassen zoals bijvoorbeeld de array groter of kleiner maken. Dit heeft te maken met de technische werking van een foreach statement. Wanneer je wel elementen wilt toevoegen of verwijderen bij een collectie, maak dan gebruik van een for lus. Voor de andere voorbeelden, zie hoofdstuk 2.

3.5

Herhalingen de while lus

Nog een andere manier om herhalingen uit te voeren, is het gebruik van een while lus. Deze lussen worden voornamelijk gebruikt wanneer er vooraf getest moet worden of een bepaalde conditie geldt. Deze conditie mag variabel zijn en in tegenstelling tot een for lus, hoeft bij een while lus niet van te voren duidelijk te zijn hoe vaak de lus doorlopen wordt. De test is een test waarbij de uitkomst True of False is. Dit noemt men een booleaanse expressie. De algemene structuur van een while lus is zo:

Bovenstaande tekening noemt men een flowchart. Je leest ze van boven naar beneden en hiermee beschrijf je de flow van een programma. De booleaanse expressie (condition?) stelt de keuze voor. Hier krijgt de flow de keuze om rechtdoor te gaan (en zo de code uitvoert binnen de while lus) of om te stoppen. Dit wordt allemaal besloten aan de hand van de uitkomst van de expressie, is de uitkomst van deze expressie (vergelijking dus) waar (=true) dan volgt de uitvoering van de loop body. In alle andere gevallen wordt gestopt.

Programmeren met C#

24

De structuur van een while lus zie je hieronder: static void Main() { int n = 1; while (n < 6) { Console.WriteLine("Huidige waarde van n is {0}", n); n++; } } Net als bij de for lus, kan je hier op eenvoudige wijze een oneindige lus creren, wat vaak resulteert tot de welbekende StackOverFlow Exception. Een voorbeeld van een oneindige lus m.b.v. een while statement: static void Main(string[] args) { while (1 < 10) Console.WriteLine("Hallo"); } Probeer dit maar eens in C#. 1 < 10 is altijd waar, verander de code maar eens naar while ( 1 > 10 ). Voorbeeld 1: int counter = 5; int n = 1; while ( counter > 0) { n *= counter; counter--; } //Wat is de waarde van de variabele n na afloop van dit //statement? Voorbeeld 2: int counter = 0; int a = 1, b = 2; while ( counter < 10) { a += b; b += 3; counter++; } //Wat is de waarde van de variabelen a en b? Voorbeeld 3: int wortel = 0; while ((wortel + 1) * (wortel + 1) < 10) wortel++; //Wat is de waarde van 'wortel'?

Programmeren met C#

25

Opgave 1 (aftekenen in practicum):1. Schrijf een programma met een for lus welke de tafel van 100 toont. De output wordt dan zoiets als 1 x 100 = 100, 2 x 100 = 200, etc 2. Idem als 1, maar nu met een lijst(-comprehensie) en een foreach statement. 3. Een palindroom is een woord dat gelijk is aan zijn inverse. Bijvoorbeeld: lepel of parterretrap. Schrijf een programma fragment dat test of een woord een palindroom is en dit in de output ook aangeeft. Je programmafragmenten moeten wel werken. 4. Gegeven een array met waarden: int lijst = { 1,2,3,4,5}; Schrijf een programmafragment dat de som berekent uit deze lijst (zonder lijstcomprehensies!). 5. Nogmaals een (gesorteerde) lijst: int lijst = { 1,1,2,3,4,4,5,7,7,7,10}; Schrijf een programma fragment dat berekent hoeveel dubbele elementen voorkomen. Een element is dubbel als het gelijk is aan zijn voorganger. NB: Hoe vaak komt zeven dubbel voor?

Opgave 2 (aftekenen in practicum):1. Hoe vaak wordt in de volgende lus Hello World geprint? Doe dit eerst eens uit je hoofd en vergelijk dit met je programma. int n = 10; while ( n-- > 0 ) Console.WriteLine(Hello World); 2. Wat is de waarde van de variabele n na dit fragment. Wederom eerst uit je hoofd, vergelijk het daarna door het te programmeren en de uitkomst te tonen. int a = 1, n = 1; while ( a < 100 ) { a *= n; n++; } 3. Maak met behulp van een while lus, een figuur met *. Bijvoorbeeld een driehoekpatroon: * ** *** **** *** ** * HINT: Onderzoek de mogelijkheid om binnen een console tekst uit te lijnen. Bijvoorbeeld: Console.WriteLine("\t{0,8:s}", sterretjes);

Opgave 3 (aftekenen in practicum):1. Bereken de grootte van een kippenpopulatie na n jaar. Je mag van de volgende gegevens uitgaan: In het begin zijn er twee kippen (haan en hen); Kippen sterven niet; Ieder volwassen kippenpaar krijgt na 1 maand n nieuw paar jonge kippen; De jonge kippen zijn 1 maand na de geboorte volwassen, een maand later kunnen ze jongen krijgen.

Programmeren met C#

26

4.4.1

Methoden in C#Algemeen

Programmeertalen kennen vaak functies en procedures (of ook wel subroutines genaamd). C# maakt daarin geen direct onderscheid. Wel in de technische werking, maar niet qua typering. In C# spreekt men altijd van methoden. Een methode in C# is een groepje opdrachten waar je een naam aan geeft. In Console applicaties (vooral in de class Program.cs) zijn deze methoden vaak static. Later is dit niet meer nodig. Voorbeeld: de lijst met priemgetallen binnen het bereik 2 tot 100. var myPrimes = from x in Enumerable.Range(2, 100) where (from y in Enumerable.Range(1,x) where x % y == 0 select y).Count() == 2 && x < 100 select x; Deze statements (= regels code) kun je ook in een methode plaatsen. Er dient een naam te worden gegeven (Primes()) en tussen de { en } plaats je dan de code: public static void Primes() { var myPrimes = from x in Enumerable.Range(2, 100) where (from y in Enumerable.Range(1,x) where x % y == 0 select y).Count() == 2 && x < 100 select x; foreach (var prime in myPrimes ) Console.Write(prime + , ); } De bovenstaande methode heeft geen resultaattype. Dit kun je herkennen aan het woordje void. Ook heeft deze methode geen argumenten (=parameter), wat je weer kunt herkennen aan het feit dat er niets tussen de ( en ) staat. Wanneer een methode geen resultaattype heeft, worden de statements uitgevoerd en gebeurd verder weinig. Een kleine aanpassing levert een nieuwe methode: public static int[] Primes (int upperBound) { var myPrimes = from x in Enumerable.Range(2, upperBound) where (from y in Enumerable.Range(1,x) where x % y == 0 select y).Count() == 2 && x < upperBound select x; return myPrimes.ToArray(); } Nu hebben we een resultaattype, wat te herkennen is aan de nieuwe naam tussen het keyword static en de methode naam Primes, namelijk int[]. Ook hebben we onze methode iets dynamischer proberen te maken door een bovengrens aan te kunnen geven via een argument ofwel parameter. Een parameter heeft altijd een datatype (hier int) en een naam (hier upperBound).

Programmeren met C#

27

Toepassing voor de eerste methode: public static void Main(string[] args) { Primes(); //Drukt de priemgetallen af binnen het bereik 2 tot 100. Console.ReadLine(); } Output op scherm: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97,

Toepassing voor de tweede methode: public static void Main(string[] args) { var primes = Primes(10); //Drukt de priemgetallen af binnen het bereik 2 //tot 10 foreach (var prime in primes) Console.Write(prime + , ); Console.ReadLine(); } Output op scherm: 2, 3, 5, 7, Methoden ondersteunen het programmeren doordat je specifieke problemen kunt opsplitsen in deelproblemen. Voor ieder deelprobleem kan men vaak kleinere deelproblemen onderscheiden. Uiteraard is het doel van een methode voornamelijk ook het bevorderen van het hergebruik van code. Beschouw het volgende voorbeeld (inclusief halfautomatisch gegenereerd commentaar): /// /// Method which calculates the longest side of a right-angled triangle. /// (Also known as the Pythagorean theorem) /// /// Side a /// Side b /// The length of side c public static double Pythagoras(double a, double b) { return Math.Sqrt(Math.Pow(a, 2.0) + Math.Pow(b, 2.0)); } Door middel van het keyword return, geven we aan dat het resultaat van een berekening teruggegeven wordt door de methode. De methode Pythagoras kan keer op keer worden aangeroepen met verschillende waarden voor de parameters.

Programmeren met C#

28

Toepassing: public static void Main(string[] args) { double c = Pythagoras(3,4); Console.WriteLine(c); //Toont 5 op het scherm. Console.ReadLine(); }

4.2

Complexere methoden

Methoden kunnen slechts n resultaattype teruggeven. Dit kan in sommige gevallen een beperking zijn. Bijvoorbeeld een methode wat een vermenigvuldiging doet waarbij het resultaat nog in een 32-bits integer past en tevens aangeeft of de operatie gelukt is: public static int Vermenigvuldig(int x, int y, ref bool succes) { if ( (x*y) < Int32.MaxValue) { success = true; return x * y; } else { return 0; } } De aanroep c.q. toepassing gaat zo: public static void Main(string[] args) { bool gelukt = false; //Nog niet gelukt. int resultaat = Vermenigvuldig(12, 3, ref gelukt); //Gelukt is nu true en resultaat = 36. } Hier staat het ref keyword genoemd wat voor ons de truuc doet om meerdere resultaten uit een functie te kunnen halen. Ref staat voor referentie (pass by reference) en betekent dat men een verwijzing (naar de oorspronkelijke variabele) doorgeeft als parameter en geen kopie (zoals bij een pass by value). Let op: wanneer je ref gebruikt, moet je de variabele die je in de aanroep meegeeft vooraf initialiseren (wat hier gedaan is door het statement bool gelukt = false;).

Programmeren met C#

29

Hier is nog een verschil mogelijk, wanneer men bijvoorbeeld nog geen initialisatie kan toepassen. Dit werkt met een zogeheten output parameter (te herkennen aan out): public static int Vermenigvuldig(int x, int y, out bool succes) { if ( (x*y) < Int32.MaxValue) { success = true; return x * y; } else { succes = false; //Noodzakelijk, aangezien een output parameter //niet geinitialiseerd is! return 0; } } De aanroep c.q. toepassing gaat nu zo: public static void Main(string[] args) { bool gelukt; //Nog niet genitialiseerd int resultaat = Vermenigvuldig(12, 3, out gelukt); //Gelukt is nu true en resultaat = 36. }

4.3

Meerdere versies van methoden

Soms herken je wel eens een methode met dezelfde naam welke een verschillend aantal parameters hebben. Dit is in C# mogelijk doordat de compiler bepaald welke methode dient te worden aangeroepen. Formeel heet dit method overloading (bij Programmeren 2 en 3 komen we hier nog op terug) en kan alleen als een methode een verschillend aantal parameters heeft: public static int Vermenigvuldig(int a, int b) { return a * b; } public static int Vermenigvuldig(int a, int b, int c) { Return a * b * c; } Voorbeeldaanroep of toepassing: public static void Main(string[] args) { int x = Vermenigvuldig(4, 5); int y = Vermenigvuldig(4, 5, 6); }

//Levert 20 //Levert 120

Programmeren met C#

30

Opgave 1 (aftekenen in practicum)1. Maak een methode die de middelste letter van een string (meegegeven als parameter) afdrukt. Gebruik de eigenschap Length van een string om de lengte te bepalen. 2. Idem, maar dan de middelste 2 letters als de lengte van de opgegeven string even is. 3. Schrijf een methode die alle getallen tot en met 100 optelt [som = n (n+1)] 4. Idem, maar dan voor een willekeurig getal (i.p.v. 100). 5. Idem, maar dan de som vanaf een bepaald getal tot en met een bepaald getal, dus bijvoorbeeld 9+10+11+12+13+14+15. 6. Maak een methode die de inhoud van de lijst met priemgetallen (zie hoofdstuk 4) zo afdrukt, dat er een element per regel wordt afgedrukt. 7. Maak een methode welke het aantal woorden in een tekst (= string) telt. Aangenomen dat de woorden door een spatie gescheiden worden. 8. Maak een methode die een (primitieve) sinus tekent met *. Onderzoek hoe je de uitlijning kunt gebruiken (zie hoofdstuk 3).

Opgave 2 (aftekenen in practicum)1. Maak een functie die de 1e 10 getallen van Fibonacci afdrukt, d.w.z. de rij getallen waarbij een getal de som van de 2 voorafgaande is: 1,1,2,3,5,8, 2. Voeg een parameter (met naam n) toe aan deze methode, waarop de 1e n getallen worden afgedrukt. 3. Pas de methode aan, om de Fibonnaci reeks in een lijst op te slaan en deze teruggeeft. 4. BONUS, voor de wiskunde liefhebbers: De gulden snede is volgens kenners de mooiste lengte verhouding (en komt veel voor in de natuur) en wordt ook vaak toegepast binnen de architectuur. Zij wordt gedefinieerd als a/b waarbij (a+b)/a = a/b. Na enig rekenen kun je vinden dat a/b = + * 51/2. Ook in Fibonacci zit deze verhouding verborgen: als je twee opeenvolgende termen van de fibonacci-rij op elkaar deelt kom je steeds dichter bij dit getal. Maak een methode met de naam guldenSnede(int aantal, int[] fibRij) die dit getal (in een float!) teruggeeft. TIP: quotient = 1.0f * fibRij[i]/fibRij[i-1]

Opgave 3 (aftekenen in practicum)1. Maak een methode die de 3e letter van een opgegeven string afdrukt, met als heading: public static void DerdeLetter(string tekst). 2. Wordt inderdaad de 3e letter afgedrukt? 3. Veralgemeen de methode zo, dat letter n wordt afgedrukt. Noem hem LetterN. 4. Wat gebeurd er als je de waarde 0, of kleiner dan 0 meegeeft? 5. Wat gebeurd er als je een waarde opgeeft die groter is dan de lengte van de tekst? 6. Pas de methode aan, waarbij geen invoerfouten meer kunnen optreden.

Programmeren met C#

31

5.5.1

Classes, een inleidingAlgemeen

Classes in C# (en andere object georinteerde talen) zijn objecten. Je kunt ze beschouwen als de bouwstenen voor een programma. Classes bestaan uit (class-)variabelen, properties en methoden, dit alles samen geeft een class een bepaalde functionaliteit. En die functionaliteit is bij juist gebruik van classes altijd weer te gebruiken. De syntax (en structuur) voor een class is als volgt: class ClassName { //Class variabelen, met private access modifier private int _variableEen; private string _variabelTwee; //Property, voor het verkrijgen en initialiseren van een class variabele public int VariabeleEen { get { return _variabeleEen; } set { _variabeleEen = value; } } //Auto-implemented property (geen class variabelen meer nodig) public float VariabeleDrie { get; set;} public ClassName() { } public void Method1() { } private void Method2() { } } Een class heeft altijd een naam, bijvoorbeeld de naam Persoon zoals in het voorbeeld op de volgende pagina. Daarnaast kan men ook access modifiers toekennen aan een class (in C# kent men de volgende: private, public, protected, internal en protected internal) maar dit zal bij Programmeren 2 worden behandeld. Wat wellicht opvalt aan de structuur van de class is dat er een speciale methode aanwezig is met dezelfde naam als de class. Deze methode heeft geen resultaattype (of returntype) en ook niet een void als returntype. Zon methode noemt men een constructor. //