Løsningsforslag eksamen in105, våren 2000 Løsningsforslaget er basert på et løsningsforslag av Anders Brunland og er siden modifisert av Ole Christian Lingjærde. Dato: 13.06.00. Oppgave 1A I klassen Hjorne: String navn; Hjorne(String n) { navn = n; String fånavn() { return navn; Hashtable allehjørner = new Hashtable(); // key = navn, elem = Hjorne void leshjørnerfrafil() throws IOException { String linje; Hjorne hjørne; BufferedReader fin = Text.open("Hjorner.dat"); StringTokenizer st; while ((linje = fin.readline())!= null) { st = new StringTokenizer(linje); hjørne = new Hjorne(st.nextToken()); hjørne.settlengdegrad(double.valueof(st.nexttoken()).doublevalue()); hjørne.settbreddegrad(double.valueof(st.nexttoken()).doublevalue()); allehjørner.put(hjørne.fånavn(), hjørne); Oppgave 1B Et spørsmål som må avklares i denne oppgaven er hvor man ønsker å gjøre innlesningen. Hvis man "dytter" ansvaret for innlesing av hjørner ned til Eiendom, får man et problem med at Eiendom ikke har tilgang på hashtabellen med alle hjørner i. I så fall må man sende med en peker til tabellen som parameter. Det er etter min mening ikke en god løsning å gjøre tabellen static i Registerklassen. En annen innfallsvinkel er å gjøre mesteparten av innlesingen i Register-klassen. Det er gjort her.
class Person { String navn; String adr; String fnr; Person(String navn, String adr, String fnr) throws IOException { this.navn = navn; this.adr = adr; this.fnr = fnr; class Eiendom { Person eier; String gnr, bnr; int anthjørner; Hjorne[] hjørner; Eiendom(String gnr, String bnr, Person p, int anth) { this.gnr = gnr; this.bnr = bnr; eier = p; anthjørner = anth; hjørner = new Hjorne[antH]; void setthjørne(int nr, Hjorne hjørne) { hjørner[nr] = hjørne; String fågnr() { return gnr; String fåbnr() { return bnr; Siden kombinasjonen av gårdsnummer og bruksnummer er unik velger vi å bruke dette som identifikator på eiendommene. Det er noe uklart i oppgaveteksten hvorvidt dette skal oppfattes som tall eller tekst. Siden det benyttes i en hashtabell har vi i dette forslaget valgt å tolke det som tekst.
Hashtable alleeiendommer = new Hashtable(); // key = gnr, elem = Hashtable // Et par hjelpemetoder void settinneiendom(eiendom e) { Hashtable ht = (Hashtable) alleeiendommer.get(e.fågnr()); if (ht==null) { ht = new Hashtable(); alleeiendommer.put(e.fågnr()); ht.put(e.fåbnr(), e); Eiendom finneiendom(string gnr, String bnr) { Hashtable ht = (Hashtable) alleeiendommer.get(gnr); if (ht!=null && ht.containskey(bnr)) return (Eiendom) ht.get(bnr); else return null; void leseiendommerfrafil() throws IOException { String navn, adr, fnr, gnr, bnr; Eiendom eiendom; Person p; int ant; BufferedReader fin = Text.open("Eiendommer.dat"); StringTokenizer st; navn = fin.readline(); while (!navn.equals("zzz")) { adr = fin.readline(); fnr = fin.readline(); p = new Person(navn, adr, fnr); st = new StringTokenizer(fin.readLine()); gnr = st.nexttoken(); bnr = st.nexttoken(); ant = Integer.parseInt(fin.readLine()); eiendom = new Eiendom(gnr, bnr, p, ant); settinneiendom(eiendom); for (int i = 0; i < ant; i++) { st = new StringTokenizer(fin.readLine()); st.nexttoken(); /* Kaster første token... det forutsetter at * indexen alltid starter på 1 og øker med 1. */ eiendom.setthjørne(i, (Hjorne) allehjørner.get(st.nexttoken())); navn = fin.readline();
Oppgave 1C Metodene laget i oppgave 1A og B kan kalles i konstruktøren til Eiendomsregister eller til Register. Hvis de skal kalles i Register må evt. konstruktøren i Eiendomsregister inneholde: reg = new Register(); Oppgave 2 EiendomsregisterMain main Hjorne Eiendom Eiendomsregister reg navn breddegrad hjørner anthjørner lengdegrad gnr bnr eier Register allehjørner alleeiendommer navn fnr adr Kolonner uten noen utgående piler i hashtabeller, og andre referanser uten utgående piler, angir referanser til objekter av klassen String. Hashtable Person
Oppgave 3A I klassen Person: void skrivtilskjerm() { System.out.println(navn); System.out.println(adr); System.out.println(fnr); I klassen Hjorne: void skrivtilskjerm() { System.out.println(navn + "\t" + lengdegrad + "\t" + breddegrad); void skrivtilskjerm() { eier.skrivtilskjerm(); System.out.println(gnr + " " + bnr); System.out.println(antHjørner); // Skriver hjørner. System.out.print((i + 1) + " "); hjørner[i].skrivtilskjerm(); void skriveiendom(string gnr, String bnr) { Eiendom e = finneiendom(gnr, bnr); if (e!= null) e.skrivtilskjerm(); else System.out.println("Eiendommen med gnr " + gnr + " og bnr " + bnr + "\ner ikke registrert.");
Oppgave 3B void skrivtilskjerm() { int omkrets = 0; eier.skrivtilskjerm(); System.out.println(gnr + " " + bnr); System.out.println(antHjørner); // Skriver hjørner. System.out.print((i + 1) + " "); hjørner[i].skrivtilskjerm(); /* * Utvidelsen fra 3A: * For å "komme rundt" eiendommen benytter jeg modularegning. */ omkrets += Register.finnLengde(hjørner[i], hjørner[(i - 1 + anthjørner) % anthjørner]); System.out.println("Omkrets = " + omkrets); /* * Forutsetter her at metoden finnlengde er "static". Dette for at jeg enkelt * skal ha tilgang til den fra Eiendoms-klassen. */ static int finnlengde(hjorne h1, Hjorne h2) { // Beregner lengden mellom h1 og h2. void skriveiendom(string gnr, String bnr) { Eiendom e = finneiendom(gnr, bnr); if (e!= null) e.skrivtilskjerm(); else System.out.println("Eiendommen med gnr " + gnr + " og bnr " + bnr + "\ner ikke registrert.");
Oppgave 4 void skrivallehjørner() { Enumeration e = allehjørner.elements(); while (e.hasmoreelements()) ((Hjorne) e.nextelement()).skrivtilskjerm(); System.out.println("Totalt " + allehjørner.size() + " hjørner."); Oppgave 5 // Hjelpe-metode: boolean harhjørne(hjorne h) { for (int i = 0; i < anthjørner; i++) if (hjørner[i] == h) return true; return false; Hjorne fåhjørne(int nr) { return hjørner[nr % anthjørner]; // Aksepterer også nr >= anthjørner. // Dette benyttes i oppgave 7. boolean harfelleshjørne(eiendom e) { for (int i = 0; i < e.anthjørner; i++) if (harhjørne(e.fåhjørne(i))) return true; return false; void støterborti(string gnr1, String bnr1, String gnr2, String bnr2) { Eiendom e1 = finneiendom(gnr1, bnr1); Eiendom e2 = finneiendom(gnr2, bnr2); if (e1!= null && e2!= null && e1.harfelleshjørne(e2)) System.out.println("Eiendommene støter borti hverandre"); else System.out.println("Eiendommene støter ikke borti hverandre"); Oppgave 6 Hjorne fåhjørne(string navn) { if (hjørner[i].fånavn().equals(navn)) {
return hjørner[i]; return null; Eiendom[] deleiendom(bufferedreader stdin) throws IOException { Eiendom[] nye = new Eiendom[2]; Hjorne[] h = new Hjorne[2]; int[] hpos = new int[2]; int k = 0; // Be brukeren velge to hjørner for deling skrivtilskjerm(); System.out.print("Første hjørne for deling: "); h[0] = fåhjørne(stdin.readline()); System.out.print("Andre hjørne for deling: "); h[1] = fåhjørne(stdin.readline()); // Finn posisjonen til de to dele-hjørnene if (hjørner[i] == h[0] hjørner[i] == h[1]) hpos[k++] = i; // Klar for å lage to eiendomsobjekter: String nyttgnr; String nyttbnr; Text.prompt("Nytt gårdsnummer:"); nyttgnr = stdin.readline(); Text.prompt("Nytt bruksnummer:"); nyttbnr = stdin.readline(); nye[0] = new Eiendom(gnr, bnr, eier, 1 + anthjørner-(hpos[1]-hpos[0])); nye[1] = new Eiendom(nyttGnr, nyttbnr, eier, 1 + hpos[1]-hpos[0]); // Sett hjørnene i de to eiendommene int i0 = 0; int i1 = 0; if (i <= hpos[0] i >= hpos[1]) nye[0].setthjørne(i0++, hjørner[i]); if (i >= hpos[0] && i <= hpos[1]) nye[1].setthjørne(i1++, hjørner[i]); return nye; void deleiendom(string gnr, String bnr) throws IOException { Eiendom gml = finneiendom(gnr, bnr); Eiendom[] nye; BufferedReader stdin = Text.open(System.in);
nye = gml.deleiendom(stdin); settinneiendom(nye[0]); settinneiendom(nye[1]); Oppgave 7 boolean fellesgrensemed(eiendom e) { boolean a, b; for (int j = 0; j < e.fåanth(); j++) { a = e.fåhjørne(j)==fåhjørne(i) && e.fåhjørne(j+1)==fåhjørne(i+1); b = e.fåhjørne(j)==fåhjørne(i+1) && e.fåhjørne(j+1)==fåhjørne(i); if (a b) return true; return false; boolean fellesgrense(string gnr1, String bnr1, String gnr2, String bnr2) { Eiendom e1 = finneiendom(gnr1, bnr1); Eiendom e2 = finneiendom(gnr2, bnr2); return e1.fellesgrensemed(e2);