Kandidatnummer: UNIVERSITETET I OSLO BOKMÅL Det matematisk-naturvitenskapelige fakultet LØSNINGSFORSLAG Eksamen i : INF1000 Grunnkurs i objektorientert programmering Eksamensdag : Fredag 2.desember 2011 Tid for eksamen : 14.30 18.30 Oppgavesettet er på : 17 sider (13 oppgaver) Vedlegg : Ingen Tillatte hjelpemidler : Alle trykte og skrevne Les nøye gjennom hver oppgave før du løser den. For hver oppgave er angitt det maksimale antall poeng du kan få hvis du svarer helt riktig. Summen av poengene er 240, slik at 1 poeng tilsvarer 1 minutt av eksamenstiden. Pass på at du bruker tiden din riktig. Kontroller også at oppgavesettet er komplett før du begynner å besvare det. Dersom du savner opplysninger i oppgaven, kan du selv legge dine egne forutsetninger til grunn og gjøre rimelige antagelser, så lenge de ikke bryter med oppgavens "ånd". Gjør i så fall rede for forutsetningene og antagelsene du gjør. Dine svar skal skrives på disse oppgavearkene, og ikke på separate ark. Dette gjelder både spørsmål med avkrysningssvar og spørsmål hvor du bes om å skrive programkode. I de oppgavene hvor det skal skrives programkode, anbefales det at du først skriver en kladd på eget ark før du fører svaret inn i disse oppgavearkene på avsatt plass. Noen av spørsmålene er flervalgsoppgaver. På disse oppgavene får du poeng etter hvor mange korrekte svar du gir. Du får ikke poeng hvis du lar være å besvare et spørsmål, eller dersom du krysser av begge svaralternativer. Hvis du har satt et kryss i en avkrysningsboks og etterpå finner ut at du ikke ønsket å krysse av der, kan du skrive "FEIL" like til venstre for den aktuelle avkrysningsboksen. Husk å skrive såpass hardt at besvarelsen blir mulig å lese på alle gjennomslagsarkene, men ikke legg andre deler av eksamensoppgaven under når du skriver. Oppgave 1 (1 poeng) a) Hvor mange int-verdier er det plass til i arrayen hus? int[] hus = new int[19]; Svar:...19... 1
Oppgave 2 (9 poeng) Er disse programsetningene lovlige i Java? JA NEI int x = 5 / 2; double y = 3 / 2; int[]int[] a = new int[4]int[6]; int i =4, k=i*(i-3); String int = abc ; double [] i4 = new i4[2]; int [][] XX = 1.23; double x = new double(1.0); Double x = new Double(1.0); Oppgave 3 (12 poeng) a) Hvor mange ganger blir INF1000 skrevet ut av følgende løkke: for (int k=1; k <= 11; k++) { System.out.println("INF1000"); Svar:...11... ganger b) Hvor mange ganger blir INF1000 skrevet ut av følgende løkke: int i = 1; while (i++ < 5) { System.out.println("INF1000 "); Svar:...4... ganger c) Hvor mange ganger blir INF1000 skrevet ut av følgende løkker: for (int j= 2 ; j < 6 ; j = j+1 ) { for (int i = 1; i < j; i++) { System.out.println("INF1000"); Svar:...10... ganger d) Hvor mange ganger blir INF1000 skrevet ut av følgende løkke: int k = 1; while (k+5 > 2*k++ ) { System.out.println("INF1000"); Svar:...4... ganger 2
Oppgave 4 (4 poeng) Anta at følgende kodelinjer utføres: int to = 2, trettitre =33; int mange = (to++) * (--trettitre) ; int svar = to + mange++; Hva er verdien til variabelen svar rett etterpå? Svar:...67... Oppgave 5 (10 poeng) Skriv ferdig metoden under, som regner ut og returnerer arealet A av et rektangel. Formelen du skal bruke er: A = b* a hvor a og b er lengden av de to ulike sidene i rektangelet. Svar: double rektangelareal(double a, double b){ double svar = a*b ; return svar; Oppgave 6 ( 20 poeng) Skriv ferdig metoden under, som får som argument en array med høyder for elever i en videregående skole i hele cm. Du skal regne ut og returnere hvor mange elever som er høyere enn 90 % av gjennomsnittshøyden for alle elevene. (Hint: Først går du gjennom arrayen og finner gjennomsnittshøyden. Deretter går du gjennom arrayen en gang til og teller opp hvor mange som er høyere enn 90% av dette gjennomsnittet). Gjennomsnittet skal regnes ut som et flyttall (double). Svar: int antallhøyeelever (int[] elevhøyder ){ int tot = 0; int ant = elevhøyder.length; for (int i=0, i<ant; i++) // finn summen av alle høyder tot +=elevhøyder[i]; double snitt90 = 0.9*tot/ant; // 90% av gjennomsnittet int anthøye = 0; for (int i = 0; i<ant; i++) // tell antall over 90% if (elevhøyder[i] > snitt90) anthøye++; return anthøye; 3
Oppgave 7 (8 poeng) Anta at følgende kodelinjer utføres: String s = "ab" +"aabcabc"; String t = s.substring(1,6); int pos = t.indexof("ab"); Hva er verdien til variabelen pos rett etterpå, og hva er t? Svar:...pos:...2...t: baabc... Oppgave 8 (8 poeng) int svar(int n, int m){ int k = 0; while(n > 0) { n--; k+=m; return k; Hva returneres fra metodekallet svar(52,4)? Svar:...n*m, dvs 208... Oppgave 9 (20 poeng) En Pyramide har i denne oppgaven (og i Egypt) en kvadratisk bunnflate der lengde angir lengden på bunnflatens sider. I programmet nedenfor skal du lage en konstruktør til klassen Pyramide som har denne lengden og pyramidens høyde som to double-parametre. Du skal også lage en objektmetode i klassen Pyramide som regner ut volumet og returnerer denne verdien (du skal bruke formelen: volum = 0.333*høyde*lengde*lengde). Du skal også skrive programkode i main som oppretter to pyramider, en med lengde =30.1 og høyde = 22.9 og en med lengde = 60.2, og med dobbelt så stor høyde som den første pyramiden. Fra main skal du så kalle på volumberegningsmetoden i hvert av de to objektene og skrive ut en linje for hver pyramide med høyde, lengde og volum. Svar: class PyramideTest { public static void main ( String [] args) { // skriv kode her som lager to Pyramide-objekter og // skriver ut deres høyde, lengde og volum Pyramide p1 = new Pyramide (22.9, 30.1); Pyramide p2 = new Pyramide (2*22.9, 60.2); System.out.print ("Pyramide 1: Høyde=" + p1.høyde); System.out.print (" Lengde=" + p1.lengde); System.out.println (" Volum=" + p1.regnvolum()); System.out.print ("Pyramide 2: Høyde=" + p2.høyde); System.out.print (" Lengde=" + p2.lengde); System.out.println (" Volum=" + p2.regnvolum()); // end main // end class PyramideTest // 4
class Pyramide { double høyde, lengde; // skriv konstruktør her Pyramide (double høyde, double lengde) { this.høyde = høyde; this.lengde = lengde; // skriv objektmetode her som beregner og returnerer volumet double regnvolum () { double vol = 0.333*høyde*lengde*lengde; return vol; // end class Pyramide Oppgave 10 (18 poeng) Et Universitet er ofte organisert slik: Universitetet er delt opp i en rekke Fakulteter og noen Sentre. Hvert Fakultet er delt opp i et antall Institutter. Både Institutter og Sentre er delt opp i et antall Forskningsgrupper. Ansatte registreres både som ansatte ved Universitetet og på hvert Institutter/ Senter. Hvert Institutt gir en rekke Kurs, som har 1-2 Ansatte som forelesere. Tegn et UML klasse-diagram over de klassene vi kan tenkes å bruke for å representere dette problemet. Gi navn på forholdene mellom disse klassene slik det er beskrevet ovenfor og plasser antall på begge sider av hvert forhold. Svar: 5
Oppgave 11 (80 poeng) Du skal tenke deg at du er sentral innkjøper i en stor norsk offentlig bedrift (f.eks Universitetet i Oslo, som bl.a. kjøper inn for alle instituttene), og du skal lage et forenklet, menybasert innkjøpssystem for dette. Det er du som innkjøper som er brukeren av systemet, på vegne av bestillere og leverandører. Kort sagt skal du holde rede på Bestillere, Anbud, Tilbud og Leverandører- og sørge for at data du har fått er lagret på filer, slik at gamle datastrukturer kan gjenskapes når systemet startes opp. Detaljer nedenfor. Nye bestillere må registreres i et bestiller-register hos deg, med bestillernummer, e-postadresse, adresse og annen informasjon du trenger om bestilleren. Dette støttes i systemet av metoden registrerbestiller, som du skal skrive. Selve innkjøpsprosessen starter med at du får en bestilling på et visst antall av en vare fra en av de som kan bestille hos deg (eks: 150 stoler til Ifi). Du gir bestillingen et eget anbudsnummer og registrerer den som et Anbud med varenavn, bestillernummer, antall og frist for tilbud. Du legger dette anbudet ut som et offentlig anbud på nettet (wwww.doffin.no) med alle relevante opplysninger for interesserte leverandører. Dette gjøres i systemet ditt ved hjelp av metoden registreretanbud, som du skal skrive. Så kan leverandørene komme med tilbud disse mottar du som e-post og legger manuelt inn i systemet ved hjelp av metoden giettilbud. Når anbudsfristen er over har du en rekke (0 til mange) Tilbud som hver er merket med anbudsnummer, leverandørnummer, tilbudets pris og eventuelle kommentarer fra leverandøren. De leverandørene som inngir tilbud, må være registrert i registeret over godkjente leverandører. Systemet har en metode for å registrere nye Leverandører, som du skal skrive. Når anbudsfristen er utløpt skal du velge ett av tilbudene for anbudet (hvis antall tilbud >0), og avslå de andre. For enkelhets skyld skal du alltid velge det billigste tilbudet. Du informerer bestilleren om det godkjente tilbudet for videre oppfølging, og sender avslagsbrev til de andre leverandørene som har gitt tilbud. Du skal skrive en metode utføretanbud for dette. Systemet du skal skrive har altså metoder for : registrerbestiller, registrerleverandør, registreretanbud, giettilbud og utføretanbud(int anbudsnummer). Ditt system kommuniserer med omverdenen ved å sende e- poster. Du kan anta at en e-post til anbud@doffin.no (med Anbudet som en string du selv bestemmer formatet på), vil legge anbudet ut på nettet. Siden vi ikke skal fjerne informasjon som allerede er lagt inn, må du ha filer for data som allerede er tastet inn, og disse filene skal leses når systemet starter for eksempel bestillere.txt, leverandører.txt, anbud.txt og mottattetilbud.txt. Hver gang du får nye data, åpnes riktig fil (med append), nye data skrives på enden av filen og filen lukkes. Vi tenker oss at du har et HashMap for hver av registrene, og en klasse for hver type (Bestiller, Leverandør, Anbud, Tilbud). Varer som bestilles er en tekst (String). Andre metoder enn de som er nevnt i teksten eller skissen nedenfor skriver du etter behov. Du trenger ikke legge vekt på å teste input fra bruker. Skisse av systemet: 6
import easyio.*; import java.util.*; class Innkjopssystem { public static void main(string [] args) { Innkjop adm = new Innkjop(..); adm.valgmeny(); // end Innkjopssystem class Innkjop { // HashMaps deklareres av deg på formen: // HashMap <String, klasse> // void valgmeny() { // <skal skrives> // gitt av systemet, ikke skriv denne boolean sendepost(string e-postadr,string meldingstekst){. // Disse utføres på vegne av bestillere, skriv kode boolean registrerbestiller(..) { int registreretanbud ( ) { // returnerer anbudsnummeret boolean utføretanbud (int anbudsnummer) { // Disse utføres på vegne av leverandører, skriv kode boolean registrerleverandør(..) { boolean giettilbud(int anbudsnummer) { // Leverandøren oppgir anbudsnummer fra anbudet på nett Innkjop( ) { // <Les evt. gamle data og gjenskap datastrukturene // for disse før systemet starter, skriv kode> // skriv kode for disse: class Bestiller{.. class Anbud { ; class Tilbud { ; class Leverandor{..; // Løsningsforslaget omfatter kun det som ble presisert i // skriftlig/ muntlig tilleggsinformasjon på eksamen, og // viser én av mange mulige løsninger 7
Skriv koden for programmet her (flere sider satt av): import easyio.*; import java.util.*; import java.io.*; class InnkjopSystem { public static void main(string [] args) { Innkjop adm = new Innkjop(); adm.valgmeny(); // end Innkjopssystem class Innkjop { In tast = new In(); // les fra tastatur - viktig Out skjerm = new Out(); // skriv til skjerm - // kan også nytte System.out.print.. int levnum =0, bestnum=0, annum =0; String ldata = "leverandorar.txt", bdata = "bestillere.txt", andata= "anbud.txt", tdata= "mottattetilbud.txt"; // HashMaps deklareres av deg på formen: // HashMap <String, klasse> HashMap <String,Bestillar> be = new HashMap <String,Bestillar>(); //Nøkkel = bestillernummer HashMap <String,Leverandor> lev = new HashMap <String,Leverandor>(); // Nøkkel = leverandørnummer HashMap <String,Anbod> an = new HashMap <String,Anbod>(); // Nøkkel = anbodsnummer HashMap <String,Tilbod> ti = new HashMap <String,Tilbod>(); // Nøkkel = leverandørnummer + +anbodsnummer // int meny() { System.out.println("\nVelg (1-5 eller avslutt:6"); System.out.println(" 1 - registrerbestillar"); System.out.println(" 2 - registrerleverandør "); System.out.println(" 3 - registrereitanbod "); System.out.println(" 4 - utføreitanbod "); System.out.println(" 5 - gieittilbod "); System.out.println(" 6 - Lagre data og Avslutt "); System.out.println(""); int svar = tast.inint(); return svar; 8
void valgmeny() { // <skriv kode her> int svar = 0; int an,an2; while (svar!= 6){ svar = meny(); switch (svar) { case 1 : registrerbestillar(); break; case 2 : registrerleverandør(); break; case 3 : registrereitanbod(); break; case 4 : System.out.print("Gi anbudsnummer:"); an = tast.inint(); utføreitanbod (an); break; case 5 : System.out.print("Gi anbudsnummer:"); an2 = tast.inint(); gieittilbod(an2); break; case 6 : saveandexit(); break; default: System.out.println("Gi et tall 1-6:\n\n"); // end switch // end while tast.close(); // valgmeny // gitt av systemet, ikkje skriv denne boolean sendepost(string epostadr,string meldingstekst){ System.out.println(ePostadr + "har fått epost:"+ meldingstekst); return true;; // LAGRE og avslutt void saveandexit(){; // Desse utførast på vegne av bestillarar, skriv kode boolean registrerbestillar() { Out bfile =new Out(bdata, true); // antar bare ekte nye leverandører bruker denne Bestillar b = new Bestillar(); b.bestnummer = bestnum++; bfile.out(b.bestnummer+" "); be.put(bestnum+" ", b); skjerm.out("gi namn:"); b.namn =tast.inline(); bfile.out(b.namn+" "); skjerm.out("gi adresse:"); b.adr =tast.inline(); bfile.out(b.adr +" "); skjerm.out("gi epostadresse:"); b.epost =tast.inline(); bfile.out(b.epost+" "); skjerm.out("gi andre opplysninger (en linje):"); b.annet =tast.inline(); bfile.outln(b.annet); bfile.close(); return true; // end registrerbestillar 9
int registrereitanbod () {return 1; // returnerer nummeret (dummy) // Denne metoden kunne vært noe enklere løst hvis Tilbodene også hadde // registrert epost-adressen til leverandør. Da ville de to løkkene // merket * vært overflødinge boolean utføreitanbod (int anbodsnummer) { int minpris = Integer.MAX_VALUE; int minleverandør =-1, bestiller=-1; String bestepost=""; String minleverandørnavn="", minleverandørepost=""; // les Tilbod i ti-hashmap med anbodsnummer = anbodsnummer // Fin minpris, velg/finn leverandør (levnummer) for (Tilbod t: ti.values()) { if (t.anbodsnummer == anbodsnummer) { if (t.prisalle < minpris) { minpris = t. prisalle; minleverandør = t.levnummer; // * Gå gjennom Leverandører og finn navn og epost. for (Leverandor l: lev.values()) { if (l.levnummer == minleverandør) { minleverandørnavn= l.namn; minleverandørepost = l.epost; // Gå gjennom anbuds HashMap finn bestillernummer, for (Anbod a : an.values()) { if (a.anbodsnummer == anbodsnummer) { bestiller = a.bestnummer; // Gå gjennom bestiller-hashmap, finn bestillers epost for (Bestillar b : be.values()) { if (b.bestnummer == bestiller) { bestepost = b.epost; //send epost til bestiller om leverandør - eller ingen tilbud. if (minleverandør == -1) { sendepost(bestepost,"bestiller:"+ bestiller+ ", ingen tilbud til ditt anbudnummer: "+ anbodsnummer); else { // finn leverandørnavnet for (Tilbod t: ti.values()) { if (t.levnummer == minleverandør && t.anbodsnummer ==anbodsnummer ){ sendepost(bestepost,"leverandør:" +minleverandørnavn+ " med epost: " + minleverandørepost + "har gitt pris:" + minpris + " kr. og er valgttil anbud:" + anbodsnummer); 10
else if(t.anbodsnummer == anbodsnummer ) { // * Finn leverandørens epost adresse for (Leverandor l: lev.values()) { if ( l.levnummer == t.levnummer ) { // finn epost sendepost(l.epost, "Tilbod på anbud: "+ anbodsnummer + " nådde ikke opp"); return true; // end utføreitanbod // Desse utførast på vegner av leverandørar, skriv kode boolean registrerleverandør() { return true; boolean gieittilbod(int anbodsnummer) {return true;; // Leverandøren oppgir anbodsnummer frå anbodet på nett Innkjop() { // Viser test/ innlesing av gamle data for to av klassene, // de to andre kan løses tilsvarende // Test om gamle data om bestillere finnes på fil System.out.println("leser gamle Bestillar data"); if ( new File(bdata).exists()) { // les gamle data In bfil = new In(bdata); // les bestiller-data; while (! bfil.endoffile()) { Bestillar b = new Bestillar(); bestnum= b.bestnummer = bfil.inint(); b.namn = bfil.inword(); b.adr = bfil.inword(); b.epost = bfil.inword(); b.annet = bfil.inline(); be.put(bestnum+" ",b); // end read old data bestnum++; // dette er nummeret til første 'nye' bestiller // i denne kjøringa bfil.close(); else { Out bfile = new Out(bdata); // lag filen, tom; bfile.close(); // test om gamle data om tilbud System.out.println("leser gamle Tilbud data"); if ( new File(andata).exists()) { // les gamle data 11
In tfil = new In(andata); // les tilbuds-data; while (! tfil.endoffile()) { Tilbod t = new Tilbod(); annum= t.anbodsnummer = tfil.inint(); t.levnummer = tfil.inint(); t.prisalle = tfil.inint(); t.kommentar = tfil.inline(); ti.put(t.levnummer+" ",t); // antar at en //leverandør bare legger inn ett tilbud // end read old data tfil.close(); else { Out tfile = new Out(andata); // lag filen, tom; tfile.close(); // end konstruktor Innkjop // end class Innkjop class Bestillar{ int bestnummer; String namn, adr; String epost, annet; ; class Anbod { int anbodsnummer; int bestnummer; String vare; String tidsfrist; int antall; ; class Tilbod { int anbodsnummer; int levnummer; int prisalle; String kommentar; ; class Leverandor{ int levnummer; String namn; String epost, annet; ; 12
Oppgave 12 (30 poeng) Du skal skrive en metode minsorter som sorterer en heltallsarray etter følgende prinsipp: Vi starter helt fra venstre (med a[0]) og finner det minste element i a[] fra element a[0] til slutten a[a.length-1]. Så bytter du dette element med a[0]. Nå gjentar du dette, men starter med element a[1], finner det minste elementet i a[1] til [a.length-1], som du bytter om med a[1]. Slik fortsetter du til du starter på a[a.length-2]. Når vi kommer helt fram til det siste paret i arrayaen, vet vi at vi har fått sortert arrayen. Brukeren får da sortert en array ved å kalle på metoden minsorter. N.B. Du får ingen poeng for å skrive av sorteringsmetoden i læreboka. Svar: void minsorter (int[] a){ int minst, minstind = 0; for (int i=0; i<=a.length-2;i++) { // a er sortert før a[i] minst = a[i]; minstind = i; for (int j=i+1; j<a.length; j++) { //finn minste bak a[i] if (a[j] < minst) { minst = a[j]; minstind = j; a[minstind] = a[i]; a[i] = minst; // bytt 13
Oppgave 13 (20 poeng) Landet Uqbar har innført akkurat samme Lov om behandling av personopplysninger som i Norge og du skal bruke denne loven til å vurdere følgende: Du, som ellers er selger i Uqbar Cars, har blitt kasserer i sportsklubben Uqbar United og vil nå for første gang i klubbens historie lage et datasystem for å ha nok opplysninger om medlemmene til å drive klubben effektivt og muligens også tjene litt på å selge navn-og-adresselister til firmaer som vil markedsføre sine produkter overfor sportsutøvere, og ikke minst lage salgkampanjer for Uqbar Cars i jobben din. De data du vil sende ut spørreskjema til samtlige medlemmer for å få samlet inn, er (du forteller medlemmene at dette er data for sportsklubben): Navn og adresse. Fødselsdato- og år, samt hvilken by/kommune man er født i. Ugift/gift/samboer. Inntekt siste år. Hvilke(n) sportsgren(er) man driver. Evt. bestenoteringer /premier i sport. En eller to andre interesser (hobbyer). Har/disponerer bil (ja/nei) og hvis ja: hvilket merke og årsmodell Navn på andre i husstanden som også er interessert i sport. Du skal nå drøfte om dette er greie opplysninger som du har rett til å samle inn eller om du må søke Datatilsynet i Uqbar om lov til dette. Begrunn svaret med å vise til konkrete paragrafer som du mener er relevante for dette for de opplysningene du ønsker å samle inn, og hvorfor de ulike paragrafene du nevner er relevante. 1) Viktig: Vurdere om det er sensitive data (mulig innsamling om etnisitet, ved at det spørres om fødeby) og da kommer inn under 2. Slike opplysninger må man søke Datatiulsynet om konsesjon for ( 33) noe som her klart vil bli avslått. 2) Det skal bemerkes at registreringen ikke er saklig begrunnet, brudd på 8-9, da det samles inn langt mer informasjon enn en sportsklubb trenger (eks. inntekt, ekteskapsstatus, fødselsby, bilmerke, navn på andre i husstanden). 3) Data samles klart inn til et annet formål, for UqbarCars, enn man sier til medlemmene og dette er brudd på 11. 14