Reader en Writer Object leest en schrijft bytes decorator store Stream leest string en char schrijft string en char TextReader TextWriter FileStream StreamReader StreamWriter MemoryStream StringReader StringWriter NetworkStream BufferedStream GZipStream CryptoStream BinaryReader XmlReader leest XML-teksten BinaryWriter XmlWriter leest int en double Methoden van Stream abstract class FileStream Stream int Read (byte[] doel, int max) { { for (int t=0; t<max; t++) { int b = this.ReadByte(); Stream if (b==–1) return t; FileStream doel[t] = (byte) b ; } MemoryStream return max; } NetworkStream abstract virtual int ReadByte ( ) ; } class FileStream : Stream { override int ReadByte ( ) { return ............... } } Abstracte methode/klasse Abstracte methode: methode zonder body Stream FileStream MemoryStream NetworkStream Brush SolidBrush HatchBrush Abstracte klasse: bevat abstracte methode ● kun je geen new object van maken ● alleen bedoeld als superklasse Implementaties van Collections IEnumerable ICollection LinkedList Queue genummerd zonder dubbele Stack IList List ISet HashSet SortedSet IEnumerator IComparator IDictionary SortedList Sorted Dictionary Hoe doorloop je een IEnumerable ? List for (int t=0; t<alles.Count; t++) doeIetsMet( alles[t] ); Collection foreach (String s in alles) doeIetsMet( s ); opdracht for ( foreach expr ; ( expr type naam ; in expr ) opdracht expr ) opdracht Commandline programma $> date parameters Wed Nov 2, 15:45 voor het programma $> ls aap.txt hallo.doc prog.cs $> grep void prog.cs prog.cs, line 6: void Main() prog.cs, line 10: void teken() $> ls $> > files.txt output redirection Grep: main class Grep { static void Main ( string [ ] params ) { if (params.Length==0) System.out.println(“Usage: Grep pat file ...”); else for (int t=1; t<params.Length; t++) Grep.bewerk( params[0], params[t] ); } Grep: bewerk static void bewerk (String pat, String naam) { TextReader reader; String regel; try { if (naam=="") reader = Console.In; else reader = new StreamReader (naam); while for (int( n=1; (regel=reader.ReadLine() ) != null ; n++ ) if ( regel . IndexOf(pat) >= 0 ) Console.WriteLine( naam + n + regel ); } catch (Exception e) { Console.WriteLine(naam + e); } Hoofdstuk 11.3 Algoritmen: Zoeken in een netwerk Routeplanner Spoorwegkaart: Klik startpunt Klik eindpunt eind start Programma bepaalt route Klik nieuw startpunt... start Modellering elk traject heeft “kosten”; route met laagste totaalprijs is de beste Zoek de “beste” route Opbouw van het netwerk staat in een file, met: voor elke stad: naam en coördinaten voor elke weg: 2 steden, en de kosten stad Amersfoort 330 350 stad Amsterdam 250 310 stad Apeldoorn 420 330 weg Amersfoort Apeldoorn weg Amsterdam Hilversum weg Hilversum Amersfoort 43 29 16 Specificatie Bij eerste muisklik: en 3e, 5e, 7e... aangewezen stad is het beginpunt toon die in blauw Bij tweede muisklik: en 4e, 6e, 8e... aangewezen stad is eindpunt bereken de route, en toon die in rood Bij klik buiten een stad: telt niet mee Opdeling in klassen Interactieve interface met EventHandler voor: class RouteZoeker : Form teken klik Belangrijke object-typen class class class class Stad Weg Pad Netwerk met in elke klasse: een constructor-methode een methode Teken om zichzelf te tekenen ... Klasse-ontwerp wat is ... membervariabelen wat kan ... een object methodeheaders en hoe ? methodebodies De klasse RouteZoeker class RouterZoeker : Form { Netwerk netwerk; de “blauwe” stad Stad stad1; of null Pad pad; Button b; TextBox t; Label lab; “het” netwerk het “rode” pad of null we tekenen alles zelf! Event-handlers void klik(..., MouseEventArgs mea) { ...... } void teken(..., PaintEventArgs pea) { ...... } De klasse Netwerk class Netwerk { Stad [ ] Steden; alle steden op de kaart ICollection<Stad> Steden; ICollection<Weg> Wegen; we gaan per stad alle uitgaande wegen bewaren De klasse Stad class Stad { string Naam; Point Plek; ICollection<Weg> Wegen; Utrecht De klasse Weg class Weg { Stad Doel; int Kosten; De klasse Pad class Pad { IList<Stad> Steden; Stad Hier; Pad Rest; int Kosten; ongeveer een LinkedList, maar dan zelfgemaakt null Methoden van Stad class Stad { String Naam; Point Plek; ICollection<Weg> wegen; static Font font = new ... Stad ( String s, Point p ) { Naam = s; Plek = p; Wegen = new LinkedList<Weg> ( ); } void Teken (Graphics gr, Brush br) { gr . FillRectangle(br Utrecht , Plek.X-5, Plek.Y-5, 10, 10 ); gr . DrawString (Naam, font, br , Plek + new Size(6,-15) ); } Methoden van Weg class Weg { Stad Doel; int Kosten; Weg ( Stad s, int k ) { Doel =s; Kosten = k; } wordt niet getekend void Teken (Graphics gr, Pen pen ) , Stad bron ) { gr . DrawLine ( pen, bron.Plek, Doel.Plek ); } Methoden van Pad class Pad { Stad Hier; Pad Rest; int Kosten; totale kosten van het pad Pad ( Stad s, Pad r, int k ) { Hier = s; Rest = r; Kosten = k; if (Rest != null) Kosten += Rest.Kosten; } void Teken (Graphics gr, Brush br, Pen pen) Hier . Teken (gr, br); { if (Rest != null) { gr.DrawLine( pen, Hier.Plek, Rest.Hier.Plek ); Rest . Teken (gr, br, pen); } } Methoden van Netwerk class Netwerk { ICollection<Stad> Steden; Netwerk ( ) { Steden = new LinkedList<Stad> ( ); } void Teken (Graphics gr) { foreach ( Stad stad in Steden ) { stad . Teken (gr, Brushes.Black); foreach ( Weg w in stad.wegen ) w.Teken (gr, Pens.Black, stad) } } bron Methoden van RouteZoeker class RouteZoeker { Netwerk netwerk; Stad stad1; Pad pad; RouteZoeker ( ) { netwerk = new Netwerk(); stad1=null; pad=null; } void teken (object o, PaintEventArgs pea) { Graphics gr = pea.Graphics; netwerk . Teken (gr); if (pad != null) pad . Teken(gr, Brushes.Red, Pens.Red); if (stad1 != null) stad1 . Teken(gr, Brushes.Blue); } Opbouw van het Netwerk Lees een file met regels zoals: commando stad Almelo 520 280 stad Amersfoort 330 350 stad Amsterdam 250 310 stad Apeldoorn 420 330 stad Arnhem 410 380 weg Arnhem Zutphen weg Zutphen Deventer weg Deventer Zwolle weg Amsterdam Weesp weg Weesp Hilversum weg Hilversum Amersfoort locatie 29 16 31 14 15 16 kosten Opbouw van het Netwerk void Lees (string filenaam ) StreamReader sr = new StreamReader(filenaam); { while ( (regel=sr.ReadLine()) != null ) { string [] r = regel.Split(" ", StringSplitOptions.RemoveEmpty ); if (r.Length==4) if (r[0] == "stad") { this . bouwStad (r[1] new Point( int.Parse(r[2]) , int.Parse(r[3]) ) ); } else { this.bouwWeg( r[1], r[2], int.Parse(r[3]) ); } } } Opbouw van het Netwerk void bouwStad (string naam, Point p) { Stad st = new Stad(naam, p); Steden . Add (st); Netwerk’s } void bouwWeg (string van, string naar, int kosten) { Stad st1 = this . vindStad (van); Stad st2 = this . vindStad (naar); } st1 . BouwWeg (st2, kosten); class Stad { st2 . BouwWeg (st1, kosten); void BouwWeg(Stad doel, int k) { Wegen . Add ( Stad’s } new Weg(doel, k) ); Opbouw van het Netwerk Stad vindStad (String naam) { } foreach ( Stad st in Steden ) { if ( st.naam == naam ) return st ; } return null ; Stad VindStad (Point p) { foreach ( Stad st in steden ) { Math.Abs( p.X-st.Plek.X )< 5 if ( && Math.Abs( p.Y-st.Plek.Y ) <5 ) return st ; } return null ; Interactie in RouteZoeker class RouteZoeker : Form { Netwerk netwerk; Stad stad1; Pad pad; void klik (..., MouseEventArgs mea) { Stad s = netwerk . VindStad( mea.Location ); if ( s != null ) eerste klik { if (stad1==null) stad1 = s; of else { pad = netwerk . ZoekPad (stad1, s ); tweede klik? stad1 = null; } this . Invalidate (); } } Het zoek-algoritme maak een stapel van nog-niet-complete, maar veelbelovende paden Pad ZoekPad (Stad begin, Stad eind) { Stack<Pad> paden = new Stack<Pad>(); Het zoeken begint... Pad pad; pad = new Pad(begin, null, 0); null paden . push (pad); hij is niet groot... null 0 maar wel veelbelovend! Onderzoek paden uit stapel... while ( paden.Count > 0 ) { Pad pad = paden . pop(); if (pad.Hier==eind) return pad; foreach ( Weg weg in pad . Hier . Wegen ) { beter = new Pad( weg.Doel, pad, weg.Kosten); paden . Push(beter); } } return null; Pas op: niet in een kringetje zoeken! één van de wegen kom je net vandaan! foreach ( Weg weg in pad.Hier.Wegen ) { if ( ! pad . Bevat (weg.Doel) ) { beter = new Pad( weg.Doel, pad, weg.Kosten); paden . Push(beter); } } Niet de eerste oplossing, maar de beste zoeken! while ( ... ) { pad = ... if (compleet) return pad; for (...) if ( !kring ) paden.Push(...) } return null; beste = null; while ( ... ) { pad = ... if (compleet) if (beter) beste=pad; beste=pad; return pad; for (...) if ( !kring )&& !zinloos) paden.Push(...) } return return null; beste; Uitwerking Wat is “beter” ? if ( beste==null || pad.Kosten < beste.Kosten ) beste = pad; Wat is “niet zinloos” ? if ( beste==null || pad.Kosten + weg.Kosten < beste.Kosten ) paden.Push (new Pad (...) ); Verbetering van het algoritme De meest veelbelovende eerst onderzoeken ordenen qua afstand tot doel Dus in volgorde van afstand tot naar pushen moet een lComparer zijn wegen = new SortedSet<Weg>( pad.Hier.Wegen , naar ); class Stad : IComparer<Weg> { { int Compare( Weg a, Weg b) { return this.afstand(b.doel) – this.afstand(a.doel); } Routezoeker compleet!