Lunds universitet FYTA11 Institutionen för Teoretisk Fysik HT 08 Lösningsförslag till tentamen FYTA11 Javaprogrammering Fredag 9:e januari 2009, 09:00 13:00 Uppgift 1: Leta buggar Titta på klasserna A, B, C samt D nedan. På nästa sida finns klassen ABCD. Om man kommentera bort de satser i main metoden i ABCD som ger kompileringsfel eller exekveringsfel, vad kommer då att skrivas ut om metoden exekveras? Förklara varför de bortkommenterade satser var felaktiga. Nedan visas också relevant information om standardklasen Vector. public abstract class A { public abstract String tostring(); public long tolong() { return 0; public abstract class B extends A { public long tolong() { return 1; public class C extends B { public String tostring() { return "C"; public class D extends C { public long tolong() { return 3; package java.util; public class Vector<E> implements Collection<E> { /** Constructs an empty vector. */ public Vector(); /** Constructs a vector containing the elements * of the specified collection. */ public Vector(Collection<? extends E> c); /** Appends the specified element to the end of * this Vector. */ public boolean add(e e); //... 1
import java.util.*; public class ABCD { public static void main(string [] arg) { long l1 = 1; // 01 double x1 = 10.0; // 02 //A a1 = new A(); // 03 KF: A is abstract //B b1 = new B(); // 04 KF: B is abstract C c1 = new C(); // 05 D d1 = new D(); // 06 Object o1 = new C(); // 07 //A a2 = new B(); // 09 KF: B is abstract B b2 = new C(); // 10 C c2 = new D(); // 11 //D d2 = new C(); // 12 KF: illegal implicit cast A a3 = (A) c1; // 14 B b3 = (B) d1; // 15 C c3 = (C) b2; // 16 //D d3 = (D) b2; // 17 EF: illegal explicit cast //A a4 = o1; // 19 KF: illegal implicit cast D d4 = (D) c2; // 20 //long l2 = x1; // 22 KF: illegal implicit cast double x2 = c1.tolong(); // 23 double x3 = (double) l1; // 24 long l3 = (long) x1; // 25 //System.out.println(b1); // 27 KF: b1 was commented out System.out.println(c1); // 28 prints "C" System.out.println(d1); // 29 prints "C" System.out.println(b2 + " " + l1 + x1); // 30 prints "C 110.0" //System.out.println(b2 + l1 + " " + x1); // 31 KF: can t add b2 + l1 System.out.println(c2 + " " + x1 + l1); // 32 prints "C 10.01" System.out.println(d1 + " " + x1); // 33 prints "C 10.0" //System.out.println(a2.toLong()); // 34 KF: a2 was commented out System.out.println(b2.toLong()); // 35 prints "1" System.out.println(c2.toLong()); // 36 prints "3" Vector<D> vd = new Vector<D>(); // 38 vd.add(d1); // 39 //vd.add(c2); // 40 KF: illegal implicit cast vd.add(d4); // 41 //Vector<A> va = vd; // 42 KF: illegal implicit cast Vector<B> vb = new Vector<B>(vd); // 43 //Vector<C> vc = vb; // 44 KF: illegal implicit cast 2
Uppgift 2: Personnummer Ett svenskt personnummer består av tio siffror (numera egentligen tolv efter som hela årtalet ska skrivas ut, men det bryr vi oss inte om här), där de sex första är födelsedatum på formen yymmdd och de fyra sista består av ett tre-siffrigt löpnummer (där den tredje siffran är udda för män och jämn för kvinnor) samt en kontrollsiffra. Kontroll siffran kan räknas ut på följande sätt. Multiplicera de enskilda siffrorna omväxlande med två eller ett enl. y y m m d d - n n n 2 1 2 1 2 1-2 1 2 Om en multiplikation blir större än eller lika med tio, lägg ihop siffrorna (t.ex. 8 2 = 16 1+6 = 7). Summera alla de resulterande siffrorna och ta 10 minus det resulterande entalet. Detta ger kontrollsiffran. Om entalet är noll blir även kontrollsiffran noll. Här är ett helt exempel: 8 1 2 2 2 8-9 8 7 x 2 1 2 1 2 1-2 1 2 16 1 4 2 4 8 18 8 14 7 1 4 2 4 8 9 8 5 : 48 10 8 x = 2 Skriv en klass med en metod som tar ett argument av typen int[]. Metoden ska kontrollera att heltalsfältet innehåller precis nio siffror mellan noll och nio. Under antagandet att dessa siffror är de första nio siffrorna i ett personnummer ska sedan kontroll siffran returneras som ett heltal. Om det upptäcks något fel med argumenten (fel antal, större än nio,...) ska ett exception av typen PNrException (se nedan) genereras. Notera att modulusoperatorn (%) som ger heltalsresten vid heltalsdivision, är mycket användbar här. Se klassen PNr på sista sidan. public class PNrException extends Throwable { public PNrException() { super("the given numbers do not correspond to a personnummer."); Uppgift 3: Personnummer igen Lägg till en main metod i klassen från den förgående uppgiften som, för varje argument, skriver ut huruvida det är ett giltigt personnummer eller inte. Endast argument på formen yymmddnnnn, yymmdd-nnnn eller yymmdd nnnn accepteras och det ska kollas att sista siffran är korrekt. Notera att metoden public char charat(int i) ger tecknet med ett givet tecken, och att det som returneras är ett heltal motsvarande tecknets UTF8 kod. Notera också att koderna för tecknen 0,..., 9 är i nummerordning. Se klassen PNr på sista sidan. Notera att t.ex. 2!= 2 3
Uppgift 4: Personnummer igen igen Antag att klassen PNr nedan är den i vilken du har implementerat metoderna i de förgående två uppgifterna. Ett objekt av klassen skapar ett fönster med ett textfält (TextField), en etikett (Label) och en liten checkbox (Checkbox). Om man trycker på retur knappen i textfältet genereras en händelse av klassen ActionEvent för TextField objektet. När man klickar i checkboxen ändras den från markerad till omarkerad eller tvärt om, och en händelse av klassen ItemEvent genereras för Checkbox objektet. När objektet och fönstret skapas visar textfältet och etiketten de strängar som angetts i konstruktorerna. På samma sätt får checkboxen en text och visas omarkerad. Skriv de ändringar som krävs för att programmet ska fungera så att om man skriver in ett födelsedatum i textfältet och trycker på returtangenten, så ändras texten på etiketten och föreslår fyra sista siffror som ger ett korrekt personnummer. Om checkboxen är markerad ska de fyra siffrorna motsvara en kvinna, annars ska de motsvara en man. På nästa sida finns en del metoder i relevanta klasser och gränssnitt beskrivna. 4
import java.awt.*; import java.awt.event.*; public class PNr extends Frame implements ActionListener, ItemListener { TextField textfield; Label label; Checkbox checkbox = new Checkbox("Female", false); public PNr() { super("personnummer generator"); textfield = new TextField("yymmdd", 6); label = new Label("nnnn"); setlayout(new FlowLayout()); add(textfield); add(label); add(checkbox); textfield.addactionlistener(this); checkbox.additemlistener(this); pack(); setvisible(true); public void calculate() { String arg = textfield.gettext(); boolean female = checkbox.getstate(); label.settext("nnnn"); if ( arg.length()!= 6 ) return; int [] v = new int[9]; for ( int i = 0; i < 6; ++i ) v[i] = arg.charat(i) - 0 ; v[6] = (int)(math.random()*10); v[7] = (int)(math.random()*10); v[8] = 2*(int)(Math.random()*5); if (!female ) ++v[8]; try { label.settext("" + v[6] + v[7] + v[8] + checksum(v)); catch ( PNrException ex ) { return; public void actionperformed(actionevent e) { calculate(); public void itemstatechanged(itemevent e) { calculate(); 5
public static int checksum(int [] v) throws PNrException { // First check that we have the correct number of digits if ( v.length!= 9 ) throw new PNrException(); // Now go through all digits, multiply and sum int sum = 0; for ( int i = 0; i < 9; ++i ) { // Check that it is a reasonable digit if ( v[i] < 0 v[i] >= 10 ) throw new PNrException(); if ( i%2 == 0 ) sum += (v[i]*2)%10 + (v[i]*2)/10; else sum += v[i]; // Then we re basically done. Just take ten minus the last digit // in the sum (or 0 if the last digit is zero) and return. sum = sum%10; return sum == 0? 0: 10 - sum; public static void main(string[] args) { if ( args.length == 0 ) new PNr(); for ( String arg : args ) { try { int [] v = new int[9]; int checkn = -1; int i = 0; for ( int j = 0; j < arg.length(); ++j ) { if ( j == 6 && ( arg.charat(j) == arg.charat(j) == - ) ) continue; if ( i == 9 ) checkn = arg.charat(j) - 0 ; else if ( i > 9 ) throw new PNrException(); else v[i++] = arg.charat(j) - 0 ; if ( i!= 9 ) throw new PNrException(); if ( checkn == checksum(v) ) System.out.println(arg + " is a proper personnummer"); else { System.out.println(arg + " is not a proper personnummer"); System.out.println("checksum should be " + checksum(v)); catch ( PNrException e ) { System.out.println(arg + " is not a proper personnummer"); 6