Sie sind auf Seite 1von 11


(a) Explain the distinction between counting loops and conditional loops, giving examples of the statements used to implement each kind of loop in Java. [20%] (b) Write a Java program that uses a loop (or loops) to display the following pattern (Hint: the Math.abs() method may be useful):
* *** ***** ******* ***** *** *

[40%] (c) The following Java program sums a list of numbers entered at the keyboard:
import sheffield.*; public class SumSomeNumbers { public static void main(String[] args) { EasyReader keyboard = new EasyReader(); int sum=0; for (int i=0; i>=0; i++) { int num = keyboard.readInt("Enter a number: "); if (num==5) break; else if (num==2) continue; sum+=num; } System.out.println("The sum is "+sum); } }


Does the program terminate when the following list of numbers is entered as input?
1 9 2 4 5

If so, what is the output of the program? [10%] (ii) Rewrite the program so that the use of break and continue is avoided. Which version of the program do you prefer, and why? [30%]


A forest is plagued by a parasite, which infects the trees and causes them to defoliate (lose their leaves). Defoliated trees are removed from the forest and new trees are planted in their place, which in turn may become infected by the parasite. The following three rules dene a simple model of the forest environment: 1. An infected area becomes defoliated the following year; 2. A defoliated area becomes green the following year; 3. An infected area infects its neighbours to the north, south, east and west the following year, if they are currently green. A biologist requires a computer program that will use the rules given above to simulate the changes in the forest over a number of generations. The program should represent the state of the forest by a grid of 25 letters. For example, the state

indicates that most of the forest is green (G), with one infected area (I) and two defoliated areas (D). The user of the program should be able to specify the initial state of the forest, and to enter the number of generations for which the simulation will run. Implement the forest simulation as a single Java class, In your answer, you should include the following: (a) The class denition, instance variable(s), class constant(s) and constructor; [15%] (b) A method called getState that reads the initial state of the forest from the keyboard; [20%] (c) A method called showState that displays the state of the forest; [15%] (d) A method called updateState which applies the three rules described above to derive the state of the forest in the next generation; [35%] A main method which runs the simulation for a number of generations specied by the user. [15%]


3. (a) When is it appropriate to use inheritance in object-oriented programming? What alternative to inheritance is sometimes preferable? Comment briey on whether you feel inheritance is appropriate in each of the following scenarios: (i) Modelling the directory structure of a typical operating system; (ii) Modelling shapes for a graphics program. [20%] (b) Explain what is meant by the term polymorphism in object-oriented programming. [10%] (c) A company employs two types of worker. One, a salaried worker, gets paid a xed weekly amount, while the other, an hourly worker, is paid according to the number of hours worked. The system identies each worker by an identity number, and it also stores their surname. The company wishes to develop a payroll system which can be used to compute the total weekly wages bill. Develop a solution to this problem using inheritance and polymorphism. Your solution should contain: (i) Denitions of whatever classes are necessary. Provide a constructor, a method for computing the weekly wage, and a toString method in each case. You do not have to provide set and get methods unless they are required to support the payroll computation. [50%] (ii) A test program which sets up an array of employees and prints out a line for each employee together with the total weekly wages bill. Show what output you expect to obtain from your program. [20%]

4. (a) What are exceptions and errors in Java and how do they differ? [10%] (b) How does Javas exception mechanism help programmers to produce robust code? [10%] (c) Suppose that you have a block of code which has the potential of generating one or more exceptions, and that you have used Javas exception mechanism to make the code robust. Draw diagrams to illustrate the ow of control in each of the following situations: No exception is thrown; An exception is thrown and caught locally; An exception is thrown but not caught locally. [30%] (d) A stack is a data structure with a single access point (the 'top') at which items are added and removed. A nite stack is a stack with a pre-determined limit on the number of items it can store. Develop a Java class to represent a nite stack of integers, complete with a push method, which adds an integer on to the stack, and a pop method, which removes an integer from the top of the stack, together with any other methods you need to support your denition. Use Java's exception handling mechanism to ensure that the stack behaves appropriately under all circumstances. Additionally, write a short test program which demonstrates the robustness of your stack. [50%]


COM6470 MOCK EXAM SOLUTIONS 1. (a) Bookwork. (b) Marks awarded for class constant, computation of the number of stars and spaces in each row, nested for structure and use of print vs println. The following is one possible solution.
public class Diamond { static final int MAX_ROW=3; public static void main(String[] args) { for (int row=-MAX_ROW; row<=MAX_ROW; row++) { int r=Math.abs(row); for (int col=0; col<r; col++) System.out.print(" "); for (int col=0; col<2*(MAX_ROW-r)+1; col++) System.out.print("*"); System.out.println(); } } }

(c)(i) Yes, sum is 14. (ii)

import sheffield.*; public class SumSomeNumbers2 { public static void main(String[] args) { EasyReader keyboard = new EasyReader(); int sum=0; int num = keyboard.readInt("Enter a number: "); while (num!=5) { if (num!=2) sum+=num; num = keyboard.readInt("Enter a number: "); } System.out.println("The sum is "+sum); } }

The alternative version is shorter and neater. Marks awarded for use of while and if within the loop, with pre-read of the rst number (do-while doesnt work for this problem).

2. (a) Marks for constant, two-dimensional array and constructor.

public class Forest { private static int GRID_SIZE = 5; private char[][] grid; public Forest() { grid=new char[GRID_SIZE][GRID_SIZE]; } }


Marks for nested loop, do-while to read valid letters.

public void getState() { EasyReader keyboard = new EasyReader(); for (int row=0; row<GRID_SIZE; row++) { System.out.println("Enter row "+row); for (int col=0; col<GRID_SIZE; col++) { char c; do { c = keyboard.readChar(); } while (c!=G && c!=I && c!=D); grid[row][col]=c; } } }


Marks for nested loop and use of print vs. println.

public void showState() { for (int row=0; row<GRID_SIZE; row++) { for (int col=0; col<GRID_SIZE; col++) System.out.print(grid[row][col]); System.out.println(); } }


Marks for use of switch to check the identity of each grid element and tests for identity of neighbouring elements. It is important that a new copy of the grid is created and returned; the rules wont be properly applied if the original grid is updated element-byelement.

public void updateState() { char[][] newgrid = new char[GRID_SIZE][GRID_SIZE]; for (int row=0; row<GRID_SIZE; row++) for (int col=0; col<GRID_SIZE; col++) { switch(grid[row][col]) { case I : newgrid[row][col]=D; break; case D : newgrid[row][col]=G; break; case G : boolean south=(row>0 && grid[row-1][col]==I); boolean north=(row<(GRID_SIZE-1) && grid[row+1][col]==I); boolean west=(col>0 && grid[row][col-1]==I); boolean east=(col<(GRID_SIZE-1) && grid[row][col+1]==I); if (north || south || east || west) newgrid[row][col]=I; else newgrid[row][col]=G; } } grid=newgrid; }


A loop to simulate the number of generations required by the user, calling the methods above in sequence.
public static void main(String[] args) { Forest f = new Forest(); f.getState(); System.out.println("Starting state is:"); f.showState(); EasyReader keyboard = new EasyReader(); int maxGeneration = keyboard.readInt("How many generations? "); for (int g=1; g<=maxGeneration; g++) { System.out.println("Generation "+g); f.updateState(); f.showState(); } System.out.println("done."); }

3. (a) Bookwork. Should mention composition as an alternative. Directory structure probably not suited to inheritance, but shape modelling certainly is. (b) Bookwork.

(c)(i) One approach is to use an abstract class to represent workers, ensuring that it has an abstract method to compute the wage. Subclasses for salaried workers and hourly paid workers then provide details specic to these worker types. An alternative (less exible) approach is to dene a concrete class representing salaried workers, then implement a subclass specialised for hourly workers (for an analogy, see the shopping Item and ItemByWeight classes in the lecture notes). Note that an abstract class can still have a concrete constructor; it is called from the subclasses to initialise the inherited instances variables for the ID and surname. The instance variables in the abstract class should be protected.

public abstract class Worker { protected int id; protected String surname; public Worker(int i, String s) { id = i; surname = s; } public abstract double weeklyWage(); }

The class for representing salaried workers:

public class SalariedWorker extends Worker { private double weeklyWage; public SalariedWorker(int i, String s, double w) { super(i,s); weeklyWage = w; } public double weeklyWage() { return weeklyWage; } public String toString() { return surname+ ID=+id+ (weekly wage = +weeklyWage+); } }

The class for representing workers paid by the hour:

public class HourlyWorker extends Worker { private double hourlyRate; private int hoursWorked; public HourlyWorker(int i, String s, double r, int h) { super(i,s); hourlyRate = r; hoursWorked = h; } public double weeklyWage() { return hourlyRate*hoursWorked; } public String toString() { return surname+ ID=+id+ (hourly rate = +hourlyRate+, hours worked = +hoursWorked+); } }


A suitable test program is shown below. The details are not too important so long as the array is declared to be an array of Worker instances, it is initialised with examples of both types of worker, and the total wage bill is computed by calling the weeklyWage method for each array element.
public class ComputeWagesBill { public static void main(String[] args) { Worker[] staff = { new HourlyWorker(12,Bender,4.90,45), new SalariedWorker(34,Fry,250.0), new HourlyWorker(56,Zoidberg,5.50,60), new SalariedWorker(78,Leela,320.0)}; double sum=0.0; for (int i=0; i<staff.length; i++) { System.out.println(staff[i]); sum+=staff[i].weeklyWage(); } System.out.println(Total weekly wage bill is +sum); } }

This produces the following output:

Bender ID=12 (hourly rate = 4.9, hours worked = 45) Fry ID=34 (weekly wage = 250.0) Zoidberg ID=56 (hourly rate = 5.5, hours worked = 60) Leela ID=78 (weekly wage = 320.0) Total weekly wage bill is 1120.5

4. (a) An exception is an unusual situation from which it may be possible to recover, e.g. attempting to read data from a le that cannot be located. An error is an unrecoverable condition (e.g. running out of memory). (b) The exception handling mechanism makes code more robust by separating the code for normal running of the program from code for handling exceptional conditions. Other approaches (e.g., using multiple conditional statements to check for errors) mix the normal and exceptional code together, and tend to cause big increases in program size. Bookwork - see the diagrams in the exception handling notes. The stack itself is just an array of integers, of a size given in the constructor. We provide the push and pop methods, and also isEmpty and isFull to decide when to throw an exception.
public class Stack { int[] items; int size; public Stack(int s) { items = new int[s]; size = 0; }

(c) (d)

public boolean isEmpty() { return size==0; } public boolean isFull() { return size==items.length; } public int pop() throws StackException { if (isEmpty()) throw new StackException("Can't pop from an empty stack"); else return items[--size]; } public void push(int i) throws StackException { if (isFull()) throw new StackException("Can't push onto a full stack"); else items[size++]=i; } }

The following exception is also required. An ideal solution would give a hierarchy of three exceptions; StackException and two subclasses called StackFullException and StackEmptyException. However, the following single class is sufcient for full marks:
public class StackException extends Exception { public StackException() { super(); } public StackException(String s) { super(s); } }

The following test class can be used to illustrate the operation of the stack. The important points are that a stack is created, and its push and pop methods are called within a try/ catch block.
public class TestStack { public static void main(String[] args) { Stack stack = new Stack(5); try { for (int i=0; i<4; i++) stack.push(i); for (int i=0; i<5; i++) System.out.println(stack.pop()); } catch (StackException e) {

e.printStackTrace(); } } }

Output from this program:

3 2 1 0 StackException: Can't pop from an empty stack at Stack.pop( at TestStack.main(

If we replaced the rst loop with:

for (int i=0; i<20; i++) stack.push(i);

Then the following output is obtained:

StackException: Can't push onto a full stack at Stack.push( at TestStack.main(