susan eisenbach1 lecture 1 : introduction to programming in java lecturer : andrew phillips this is...
TRANSCRIPT
Susan Eisenbach 1
Lecture 1 : Introduction to Programming in Java
Lecturer : Andrew PhillipsThis is the 1st lecture on Java programming. This course is
primarily about writing imperative programs.
In the next course you will learn to write object oriented Java programs.
2
Textbooks
No textbook is required. For programming beginners:
Java Software Solutions: Foundations of Program Design John Lewis and William Loftus Addison Wesley, 2002.
For experienced programmers:Learning the Java Languagehttp://java.sun.com/docs/books/tutorial/java/index.html
Thinking in Java, Bruce Eckel, Prentice Hallhttp://www.mindview.net/Books/TIJ/
3
A statement written in Java
println(“Hello World!");
Commented version/* Susan Eisenbach * 17 November 2003 * Hello World */String exclaim = “Hello World!";println(exclaim);
every statement isterminated with a ;
4
Java print() and println() Text can be printed on the screen using print() or println().
Using println() puts a new line at the end of the text. print("7*3"); println("="); println(7*3); This code prints: 7*3= 21
5
Concatenating output with + String drink = "slammers"; print("I like ");println(drink);
This code prints: I like slammers println("I like Tequila " + drink);
This code prints: I like Tequila slammers println("6/9 = " + 6/9 + " or " +6.0/9.0);
This code prints: 6/9 = 0 or 0.6666666666666666
6
Comments There are two ways of commenting code. Comments starting with // and terminated by end of line// Susan Eisenbach
// 17 November 2003
// Hello World Comments enclosed in /* *//* Susan Eisenbach
* 17 November 2003
* Hello World
*/
good to make severallines of comments standout in your program
7
A method written in Java
int bigger(int a, int b){//post: returns the larger of the 2 valuesif (a > b) {return a;}
else {return b;}} method bodies are
surrounded by { }
if and else branches are surrounded by { }
argument typesarguments
result type
8
Returning from a method and conditionals
int bigger(int a, int b){
//post: returns the larger of the 2 values
if (a > b) {return a;}
else {return b;}
}
conditionals - using the keywords if and
optionally else
results have to be returnedusing the keywordreturn
predicate (test) must be in brackets()
9
A Java program must contain a main method The main method starts the execution of a program. It doesn’t return anything, so the return type is void.
A println statement can be made into a program as follows:
void main(){println("Hello World!");
} By custom the main method is the first method in a
program.
10
/*Susan Eisenbach *17 November 2003 *chooses the largest of 3 numbers */void main(){ print("Type in your 3 numbers -> "); println(biggest(readInt(),readInt(),readInt()));}int bigger(int a, int b){//post: returns the larger of the 2 values if (a > b) {return a;} else {return b;}}int biggest(int a, int b, int c){//post: returns the largest of the 3 values return bigger(a, bigger(b,c));}
11
Variable declarations Variables are names of storage locations. Variables can
be declared of the following types:int double boolean char String
They must be declared before they are used. int j;double cost;String firstname;
Variables can be initialised in declarations.int total = 0;char answer = 'y';double start = 0;double sum = 0.0;boolean finish = false;
12
The assignment statement
Initialisation is a form of assignment. Assignment gives a variable a value. variables can have their values changed
throughout a program.total = total + 1;
total = total / 2;
answer = 'n';
13
Assignment - don't use too many variables
Poor style Better style
int i = 6;
int j = 5;
int k;
k = i+j;
println(k);
int i =6;
int j = 5;
println(i+j);
superfluous
14
Summary This lecture introduced the syntax of the Java
language for coding solutions to the problems set.
We have seen– methods with { }– statement terminator ;– variables– conditionals – if (predicate) {…} else {…}– assignments– input/output– main method– complete Java program
Susan Eisenbach 15
Lecture 2: Recursion
Lecturer : Susan EisenbachFor extra material read parts of
chapters 1,3 and 11of
Java Software Solutions
16
Recursive Approach
Define the base case(s) Define the recursive case(s)
– Split the problem into subproblems– Solve the subproblems– Combine the results to give required answer
17
Java method
int factorial(int n){assert(n >= 0 && n < 17):"argument must be >= 0";//post: returns n! if (n==0) {return 1;} else {return n*factorial(n-1);}}
18
What does assert do?
assert(n >= 0 && n < 17):
"argument must be >= 0";
evaluates the predicatetrue? – continue to execute the code
false? – print the string on the screen andstop the program
Do not execute code which you know may crash or loop forever
19
When should you have an assertion? If you write a method that expects something special of
its inputs then you need to put as a precondition whatever needs to be true before the code can be run.
The precondition should be coded (if possible) as an assertion.
Assertions can also be written without the String message. In this case, if the assertion fails then your program stops with an AssertionError.
If the user has given a method arguments that meet the precondition and the code is correct then the postcondition to the method will hold. Postconditions are written as comments at the top of the method after the word post.
20
Java method -> Java program
void main(){print("Factorial of which number? "); println("Answer = " + factorial(readInt()));
}int factorial(int n){assert(n>= 0):"argument must be >= 0";//post: returns n! if (n==0) {return 1;} else {return n*factorial(n-1);}} Rewrite this program with a more efficient fact method.
21
Methods Java has methods that return results Java also has methods that don't return any
values, they just execute some code. – their return type is void.– they frequently consume input and/or
produce output– The special main method must be void.
Both types of methods can be recursive. Java programs can never be recursive.
22
Menu method
void menu(){
//post: menu appears on the screen
println( "Enter 0 to quit" );
println( "Enter 1 to add" );
println( "Enter 2 to subtract" );
println( "Enter 3 to multiply" );
println( "Enter 4 to divide" );
}
23
Using switch to process a menu
void processMenu(int reply){ switch(reply){ case 0: {println("Bye"); break;} case 1: {println(readInt()+readInt()); break;} case 2: {} case 3: {} case 4: {println("not implemented");break;} default: {println("not possible!");}
}}
each case in curly brackets
Break prevents cases falling through
default case if integer does not match other cases (not required)
int (or char) used to choose which case to execute
24
Question Rewrite processMenu to produce the correct answer on
the screen for each of the operations Notes
– only read in the numbers once– you can put ifs and switches inside each other or
themselves– tell the user there is an error if reply < 0 or reply >
4
25
Input There are many ways of reading input in Java Whitespace is what you get when you hit the
space bar or the enter keys. We are using the IO class which contains:
– readInt() –ignores whitespaces, stops after last digit – readDouble() –ignores whitespaces, stops after last digit – readString() –ignores whitespaces, stops on first whitespace
after the string – readChar()–ignores whitespace, then reads one character– read() – reads next character (even if it is whitespace)
readSomething() consumes the newline character.
26
Developing a recursive program Specification:
– The program should accept a line of text and print it out in reverse order.
Remember:– A program cannot be recursive only a method can.
The main program calls the method reverse://method reverse:Read a character //progress one char closer to newlineif newline not yet reached then //guard the recursive call
reverse print Character
27
IMPORTANT
Guard your recursive calls. Not guarding your recursive calls can lead
to infinite recursion. Make sure there is progress towards the
terminating condition between invocations of the recursive routine.
Comment both the guard and the progression.
28
The program
void main(){print(“Type in your word to reverse ->");reverse();
}void reverse(){//post: reads in a string terminated by newline ('\n')// and prints it out in reverse orderchar ch = read(); //progress one char closer to newline if (ch != '\n') { reverse(); print(ch);
}}
29
reverse();
void reverse(){
char ch;
ch = read();
if (ch != '\n'){
reverse();
print(ch);
}
}
ch ='c'reverse()
reverse()
ch='o'reverse()
ch='d'reverse()
Program: Input cod Output
ch='\n'
d
print(ch)print(ch)
o
print(ch)
c
30
Summary A method that calls itself is recursive. Methods can be recursive, programs cannot. Recursive methods can be used to produce a single result. Void methods are used when the same operation is to be
performed on different data and the result wanted is output on the screen.
In order that the repetition may be finite, within every recursive method there must appear a terminating condition to guard the recursive call and a progression to distinguish one call from another.
Switch statements are used rather than conditionals when there are several choices based on an integer or character.
Susan Eisenbach 31
Lecture 3 : Arrays and For Loops
Lecturer : Susan Eisenbach
For extra material read parts of chapters 3 and 6 of Java Software Solutions.
This is the 3rd lecture on Java in which arrays and for loops are examined.
32
What is an array?
Arrays are called vectors and matrices by non-computing people
Arrays can be one or more dimensional Elements of an array are all of the same type
and referred to by an index Arrays are used for problems which deal with
large quantities of data Perform the same operations on each item
33
double[] vector = new double[10];
Array variable declarations
it’s an array
the name of the array is vector
each element is a double
{
get space tohold 10 doubles
34
If we want to store the sentence “Thanks for all the fish” we would use:
String[] words = new String[5];
Array variable declarations
“Thanks”
“for”
“all”“the”
“fish”
35
int[][] matrix = new int[5][4];
Array variable declarations
This is an array of arrays
36
double[] vector = { 0.1, 1.2, 0.0, 34.6,-3.0, 34.1, 0.0, 0.4, 0.8, 0.1}; String[] words = { “Thanks", “for", “all", “the", “fish“};
Arrays can be initialised at declaration
37
Getting the size of an array To get the size (no. of elements) of an array, you write arrayname.length The length of the array is determined by the number of
values provided between {}. for example if boolean[] answers = {true,false,true,true};
then answers.length is 4 Note that length is not a method and so does not have (). It is built into Java.
Once created, the size of the array cannot change. The length of the array must be specified when created.
38
Array variable declarations (cont.)
How do you declare and initialise a data structure for the following?
Susan Eisenbach
Antony John Field
Christopher
John Hogger
String[ ][ ] fullNames = { {"Susan","","Eisenbach"},{"Antony","John","Field"},{“Christopher",“John","Hogger"}
};
39
Referencing array elements Each array element is referenced using the array
identifier followed by an index expression which uniquely indexes that element
The first element of an array is at 0, the last at length – 1 Example array references: firstName = fullNames[2][1];
vec[1] = mat[1][0]+mat[1][1]+mat[1][2]+ mat[1][3]+mat[1][4];
if (i==j) {mat[i][j] = 1;} else {mat [i][j] = 0;}
40
Using arrays: You can pass arrays as arguments to methods:
void printNames(String[][] names) You can return arrays as results from methods:
String[][] copy(String[][] names)Do not assign complete arrays:
secondYears = firstYearssince any change to firstYears will happen to secondYears as well (more on this later).
41
Bounded iteration Arrays hold a large number of elements of the same type Frequently the same operation is performed on each element All the elements of an array can be traversed using a control
construct known as the for loop. Using a for statement is called looping or iteration and causes repetitive executionfor (i = lowerbound; i <= upperbound; i++) {
loop body}
for (i = upperbound; i >= lowerbound; i--) {loop body
}
42
for (i = lowerbound; i <= upperbound; i++) { loop body
}
for (i = upperbound; i >= lowerbound; i--) { loop body
}
Bounded iteration
first value of iusually 0
on each loop iterationi=i+1
on each loop iterationi=i-1stops executing the loop when
i hits this value
43
A for loop example for loops are ideal for traversing arrays - each iteration of the loop accesses
an element of the array a program to calculate the mean of an array of doubles:void main(){
double[] vec = {1,0,3,0,5,0,7,-2,9,10}; println( mean(vec) );}double mean(double[ ] v){//post:returns the average of the elements in v double total = 0;int i; for (i =0; i < v.length; i++) { total = total + v[i]; } return total/v.length;}
44
When trying to understand what some piece of Java code does you hand execute all the code working out what the values of the variables are:
mean total i v[0] v[1] v[2] v[3] v[4]
1 0 3 1 5 void main(){ double[] vec = {1,0,3,1,5}; println( mean(vec) );}double mean(double[] v){int i; double total = 0.0; for (i =0;i<v.length;i++) { total = total + v[i]; }; return total/v.length;}
0
01
2345
11
45
10
2
45
Nested for loops a 2-dimensional array requires 2 for loops to traverse it:int sum(int[ ][ ] m){//post: returns the sum of the elements of mint theSum = 0; int i; int j; for (i = 0; i<m.length; i++){ for (j = 0; j<m[i].length; j++){ theSum = theSum + m[i][j]; } } return theSum;}
an n-dimensional array requires n for loops to traverse If int mat[50][100] is passed to sum, what is the value
of m.length? For each i, what is the value of m[i].length?
46
void main(){ String[][] students ={
{"BEng", "Homer", "Marge", "Bart", "Lisa", "Maggie"}, {"MEng","Kenny","Kyle","Stan","Butters","Cartman"}, {"BSc", "J.D.", "Elliot", “Dr Cox", "Turk"}, {"MSci", "Frodo", "Gandalf", "Gollum", "Bilbo"} };
printNames( students );}void printNames(String[ ][ ] names){int i; int j;
for (i = 0; i < names.length; i++) { print(names[i][0] + ": "); for (j = 1; j < names[i].length; j++) { print(names[i][j] + " "); } println(); } }
What is the value of names.length? For each i, what is the value of names[i].length?
47
Summary Arrays are data structures suitable for problems
dealing with large quantities of identically typed data where similar operations need to be performed on every element.
Elements of an array are accessible through their index values. Arrays using a single index are called vectors, those using n indices are n-dimensional arrays. A 2-dimensional array is really an array of arrays. A 3-dimensional array is an array of arrays of arrays, etc.
48
Summary Arrays have a type associated with them: the
type of the elements. The index is always a non-negative integer.
Space has to be allocated explicitly for arrays. Either they are initialised with values and then the right amount of space is allocated or the keyword new is used to specify the allocation of space.
Repetition of the same operation is called iteration or looping. A for loop can be used to do the same operation to every element of an array.
Susan Eisenbach 49
Lecture 4 : Using Arrays
Lecturer : Susan EisenbachFor extra material read parts of chapters 3 and 6 in
Java Software Solutions.This is the 4th lecture in which code is developed
that uses arrays. The parameter passing mechanism is examined in some detail.
50
Consider a game to play noughts and crosses Assuming that each space on the board can have
an 'X', an 'O' or a ' ', write an array declaration to hold a board, initialising it all to empty.
char[][] board = {{' ',' ',' '}, {' ',' ',' '}, {' ',' ',' '}
}; Write a statement that puts an 'X' into the middle
squareboard[1][1] = 'X';
51
Write a method initBoard which returns a new board filled with spaces.
char[][] initBoard(){
char[][] b = {
{' ',' ',' '},
{' ',' ',' '},
{' ',' ',' '}
};
return b;
}
52
boolean isFull(char[][] b){ int r; int c; for (r = 0; r < 3; r++){ for (c = 0; c < 3; c++){ if (b[r][c] == ' ')
{return false;} } } return true;}
Write a predicate isFull which returns true iff there are no empty spaces on the board.
X
O
X O
X
O X
O
X
53
Checking for a winner
After each move a check has to be made whether the current player has won.
A player has won if their piece fills one of the diagonals, one of the rows or one of the columns.
X
O
X O
X
O X
O
X
54
Write a predicate isDiagonal that takes as arguments an X or O and a board and returns true iff one of the diagonals is filled with the piece.
boolean isDiagonal(char ch, char[][] b){ assert (ch='X' || ch='O'); return b[0][0]== ch && b[1][1]== ch && b[2][2]== ch || b[0][2]== ch && b[1][1]== ch && b[2][0]== ch;}
X
O
X O
O
X
55
Write a predicate hasFullRow that takes as arguments an X or O and a board and returns true iff one of the rows is filled with the piece.
boolean hasFullRow(char ch, char[][] b){ assert (ch='X' || ch='O'); boolean found; int r; int c; for (r = 0; r < 3; r++){ found = true; for (c = 0; c < 3; c++){ found = found && b[r][c] == ch; } if (found) {return true;} } return false;}
X
O
X O
X
O X
OX
56
boolean hasFullCol(char ch, char[][] b){ // pre: assert: ch='X' || ch='O'; boolean found; int r; int c; for (c = 0; c < 3; c++){
found = true; for (r = 0; r < 3; r++){ found = found && b[r][c] == ch; }
if (found) {return true;} } return false;}
Write a predicate hasFullCol that takes as arguments an X or O and a board and returns true iff one of the columns is filled with the piece.
X
O
X O
X
O X
OX
57
Exercises to do yourself:
Write the predicate hasFullCol that takes as arguments an X or O and a board and returns true iff one of the columns is filled with the piece using only one loop.
Rewrite the code in the slides with the board as a one dimensional array. How much harder is it to write thepredicates?
X
O
X O
X
O X
O
X
58
Put them together to produce a predicate isWinner
boolean isWinner(char ch, char[][] b){return
isDiagonal(ch,b) || hasFullRow(ch,b) || hasFullCol(ch,b);
}X
O
X
O
X
O
X
O
X O
X
O X
O
X
59
You could (mouse) click on the square on the screen and the coordinates could be converted into the appropriate noughts and crosses index.
This requires very sophisticated input routines. Simpler to read in coordinates for the square
from the keyboard and then convert them to the appropriate array indices.
So if a user wants the middle square, it is b2 or 2b and the bottom left-hand corner is c1 or 1c
How do you get which square the next player wants?
X
O
X O
X
O X
O
X
a
b
c
1 2 3
60
You need to know if the character the user typed in is for a row or a column
Write a predicate IsRow which takes as an argument a character and returns true iff the argument is an 'a', a 'b' or a 'c'.
boolean isRow(char c){ return 'a' <= c && c <= 'c';} Write a predicate IsCol which takes as an argument a
character and returns true iff the argument is a '1', a '2' or a '3'.
boolean isCol(char c){ return '1' <= c && c <= '3';}
61
Convert input characters into numbers that can be used for array indices
Write a method convert that takes a character that is a valid row or column and returns the appropriate number to use for the row index or column index. So if '2' is passed as an argument to convert it returns 1.int convert(char c){ assert (isRow(c) || isCol(c);
if (c=='1' || c=='a') {return 0;} if (c=='2' || c=='b') {return 1;} return 2;
}
62
Arguments to methods We have been passing arguments to methods. You can pass anything to a Java method, except
another method. In Java methods, arguments are passed by
value. When invoked, the method receives the value of the variable passed in, creates a local copy, works on it and then discards it when the method ends.
This means that a method cannot change the value of its arguments.
63
What happens when you pass a variable to a method and change its value within the method?
void main(){ int a = 1; int b = 2;
println("a & b = " + a + b);swap(a,b);println("after swap " + a + b);
}void swap(int a, int b){ //post: method does very little int temp = a; a = b; b = temp; println("inside swap " + a +b);}
b = 2
temp = 1a = 2b = 1
a & b = 1 2
println
println
inside swap 2 1
println
after swap 1 2
a = 1
64
When a method is called the runtime system of any language holds method data in a stack
b = 2
temp = 1
println
println
println
a = 1
Aa = 1, b = 2push
push Aa = 1 , b = 2 , temp = 1a = 2
2 b = 11pop
65
Summary A predicate is a method that returns a boolean
result. It is sensible to name predicates starting with is, are, can or some other similar word.
We have developed a variety of methods to write a noughts and crosses game.
In Java methods, arguments are passed by value. When invoked, the method receives the value of the argument, creates a local copy, works on it and then discards it when the method ends.
This means that a method cannot change the value of its arguments.
Susan Eisenbach 66
Lecture 5 : Classes
Lecturer : Susan EisenbachFor extra material look at chapters 2 and 4 of Java
Software Solutions.This is the 5th lecture in which classes and objects
are introduced.
67
Arrays When you want to group many of the same type
of element together in Java you use an array. You access elements in an array by index
(position of element). Sometimes you want to group a few items of
(possibly) different types together.
68
In Java there are classes Classes can be used like arrays, (although they are much
more powerful as you will see later in the course) Classes contain fields and fields are accessed by name
(not position like arrays)class Applicant{String name;int grade1;int grade2;int grade3;
} Classes are types. You create the type with the class
declaration and then you need to declare variables of the type you have created.
69
Using variables of type Applicant
Classes can be passed as arguments and returned from methods
boolean areSame(Applicant a1, Applicant a2) What is the difference between the two statements?
– println(me.name + (me.grade1 + me.grade2 + me.grade3));
– println(me.name + me.grade1 + me.grade2 + me.grade3);
Applicant me;me.name = "Susan";me.grade1 = 2;me.grade2 = 2;me.grade3 = 0;
Susan4
Susan220
70
Rewrite the class declaration for Applicant so the three grades are held in an array. Draw a diagram of your new class.
grade1name grade2 grade3Susan 02 2
Draw a diagram of an Applicant.
class Applicant{ String name; int[] grades = new int[3];}
name grades
0 1 2Shakil 10 10 10
Using variables of type Applicant
71
Example of an array of classes
0
1
2
.
.149
:
good style to putclass declarationsat top of program
class Applicant{ String name; int[] grades = new int[3];}void main(){Applicant[] firstYears = new Applicant[150];
}
Wing 10 10 10
Anita
Bintal
Carl
10 10 10
10 10 10
10 10 8
72
How do you access the fifth person's second A level result? firstYears[4].grades[1] How do you write a method that takes firstYears as an
argument and returns the index to the first student with name "Dimitri" and –1 if there is no Dimitri in firstYears.
int find(String name, Applicant[] aa){int i;
for(i=0; i<aa.length; i++){if (name == aa[i].name) {return i;}
}return -1;
}
You need to be able to access elements
73
Read in the coordinates for the square and convert them to the appropriate array indices.
So if a user wants the middle square, it is b2 or 2band the bottom righthand corner is c3 or 3c
Back to noughts and crosses –getting the user's input
X
O
X O
X
O X
O
X
a
b
c1 2 3
74
Declare a class to hold the coordinates of a move The coordinates need to be integers so they can
index the board array.
Next write a method getMove which reads the user's input from the keyboard. If it isn't a legal input (forget whether the square is occupied) then prompt again and read in the user's input. Continue this until correct input is typed in. The method should return a Coord.
class Coord{int row;int col;
}
75
Declare getMove
getMove takes no arguments (it reads its inputs from the keyboard) and returns a Coord.
What local variables are needed by getMove?
-two variables to hold the input characters
-a variable to hold the coordinates of the move to be returned
char c1, c2;
Coord move;
76
What is the algorithm for getMove?c1 = readChar()c2 = readChar()
if isRow(c1) && isCol(c2) move.row = convert(c1) move.col = convert(c2) return moveelse if isCol(c1) && isRow(c2)
move.row = convert(c2) move.col = convert(c1) return move else println("bad coordinates, re-enter-->") return getMove()
77
getMove in Java
Coord getMove(){Coord move = new Coord();char c1; char c2;
c1 = readChar();c2 = readChar();if (isRow(c1) && isCol(c2)){
move.row = convert(c1); move.col = convert(c2);return move;
}else{
if (isCol(c1) && isRow(c2)){ move.row = convert(c2); move.col = convert(c1); return move;}else{ println("bad coordinates, re-enter-->"); return getMove();}
}}
78
Summary
A class is used to group a few items of (possibly) different types together.
Access is by field name (not position). To access the field f in class C we write C.f It is good style to place all the class declarations
at the very top of the program before the main method.
Susan Eisenbach 79
Lecture 6 : Objects
Lecturer : Susan EisenbachFor extra material read chapter 4 of Java Software
Solutions.This is the 6th lecture in which primitive types and
objects are introduced.
80
Primitive values ints, doubles, Strings and chars are
primitive. Java has many other number types that are also
primitive. Primitive variables are names for storage
locations that contain the values of the variables.
What happens when during the execution of your program checking the expression a==b where a and b are both ints is reached?
81
Primitive values
What happens is the bit pattern that is the value at the storage location called a is compared with the bit pattern at the storage location called b.
If they are identical the value of the expression is true otherwise it is false.
int a = 3; int b = 4; a==b?
0…0…011
0…0…100
==
???
a b
82
Objects Arrays and classes are not primitive. They are data
structures and stored as objects. Objects (of an array or class type) need to have their
space explicitly allocated before they can be used. For arrays you do this explicitly by using new. If you look at the Java code for class declarations you
will see the word new. This word means create the object on the heap.
Object variables are names for storage locations that contain a reference or pointer to the data structure.
The actual data structure is stored in a part of memory called the heap.
83
heap
How objects are stored Consider the following declarations:int[] v1 = {1,1,1,1};
int[] v2 = {1,1,1,1}; What are the values of v1 and v2 ? They are references
(or addresses 10000 and 11000) to locations in the heap.
1 111
(but in binary)1111
(but in binary)address10000
address11000
v1 v2
84
What gets printed and why?
void main(){ int[] v1 = {1,1,1,1}; int[] v2 = {1,1,1,1}; if (v1 == v2) {println("same");} else {println("different");} v2 = v1; v1[0] = 10; if (v1 == v2) {println("same v2[0]=" + v2[0]);} else {println("different");}}
different same v2[0]=10
1 111 1 111
v1 v2
10
85
Take care with = and == If you wish to assign one object to another then
you must do it component at a time. Otherwise you will just have 2 names (known as aliases) for the same object.
Instead of writingme = you;
you should writeme.name = you.name;me.grade1 = you.grade1 etc. Then you
will have two different objects with the same values.
86
Using arraycopy to copy arrays arraycopy copies source to destination What gets printed?
int[] v1 = {1,1,1,1};int[] v2 = {2,2,2,2};int i;arraycopy(v1,v2);v1[0] = 10;for (i=0; i < v2.length; i++){print(v2[i]);
}
1111
87
What happens when you pass an object to a method and alter the object?
void main(){
int[] p = {1,2};
println("p[0] & p[1] = "+p[0] +p[1]);
swap(p);
println("after swap "+p[0] +p[1]);
}
void swap(int[] p){
int temp = p[0];
p[0] = p[1];
p[1] = temp;
println("inside swap "+p[0] +p[1]);
}
p =
1 2
temp = 1
12
p[0] = 2p[1] = 1
p[0] & p[1] = 1 2
println
println
inside swap 2 1
println
after swap 2 1
88
What happens when you pass an object to a method and alter the object?
The address of the object is passed to a method .
Like arguments, this is copied and the local copy is worked on and then discarded at the end.
However the object lives in the heap and there is no such thing as a local heap.
Any alterations to the heap that happen during the execution of a method are permanent.
89
Summary
Variables declared as a class or array type are objects and not primitive. This means they are actually references to memory addresses in the heap.
Tests for equality and assignment have to be undertaken subcomponent by subcomponent.
Arrays can be assigned using arraycopy. Objects are held on the heap and are
permanently changed when changed in a method.
Susan Eisenbach 90
Lecture 7 : Simulation and while loops
Lecturer : Susan EisenbachFor extra material read chapter 3 of Java Software
Solutions.This is the 7th lecture in which a simulation program for a vending machine is developed and while loops
are introduced.
91
Simulation
Computer programs are regularly written to simulate something real.
You have probably all played simulation games (e.g. a computer game of solitaire or a flight simulator) but simulation is also used to help understand some real process that is too difficult to understand any other way
There is an entire course in the third year for understanding how to write simulation programs called "Simulation and Modelling" –Tony Field.
92
Vending Machine We will now develop a program to simulate a
vending machine that sells sweets. Here is the interaction between the machine and
the user– Machine: lists sweets with numbers and prices– User: inputs number of choice– Machine: lists price of chosen item– User: inputs money – Machine: gives change (in fewest possible number of coins)
Two simplifications on reality:– our vending machine always has all the coins it needs to give the
appropriate change– our users always put in at least enough money
93
Sample Vending Machine Interaction********** Vending Machine ************** *** Choose From the Following *********** 1. Mars Bars 30 p * 2. Twix 35 p * 3. Mini Skittles 10 p * 4. Crisps 44 p * *****************************************Please make your choice 4 Please pay in 44 pence, paid in 60 Your change in the fewest possible coins: 1 one pence 1 five pence 1 ten pence
94
Declare variables to hold the choice, the payment and the cost.
In the program the prices of the sweets must be known. Declare and initialise a variable to hold the prices of the sweets.
First step in implementing: declarations for the data
int choice;int payment;int cost;
int[] prices = {30,35,10,44};
95
In order to give the appropriate change in coins, the values of each of the coins must be known. Declare and initialise a variable to hold the values of all coins.
In order to print out the change, the coin names must be known. Declare and initialise a variable to hold the names of all the coins.
First step in implementing: declarations for the data
String[] coinNames = {"one pence", "two pence", "five pence", "ten pence", "twenty pence", "fifty pence", "one pound", "two pounds};
int[] values = {1,2,5,10,20,50,100,200};
96
The hardest problem
Given an amount it will be necessary to convert it into the (fewest) coins needed to make up that amount. So we need a method that does the following:– 3 {1,1,0,0,0,0,0,0}– 65 {0,0,1,1,0,1,0,0} – 48 {1,1,1,0,2,0,0,0} , etc.
To do this the array of values is also required, since we need to know the value of each of the coins.
97
Declaring coins
Write the declaration for a method called coins which takes as arguments the amount (assume it is > 0) and the values of the coins. Include your pre and post conditions.
int[] coins(int n, int[] values)assert (n > 0);//post: the fewest coins whose values sum to // equal n is returned
98
How do you solve the problem?
You need to create a local (just in the method) array money to return from the method containing the different numbers of coins.
You need a local variable whatsLeft that contains the amount you haven't yet put into money.
walk over the array values from right to leftmoney[i] = whatsLeft / values[i]whatsLeft = whatsLeft % values[i]
return money
99
In Java
{ int[] money = new int [8]; int whatsLeft = n; int i; for (i = money.length-1; i>=0; i--){ money[i] = whatsLeft / values[i]; whatsLeft = whatsLeft % values[i]; } return money;}
100
What if you want to be able to do the converse of coins? Declare a method sum which takes as an argument an
array money containing the number of each of the coins and which returns the sum of the coins. Also pass values as an argument to calculate the sum. Include any pre or post conditions.
What is the algorithm for the body of the method?
int sum(int[] money, int[] values)//post: the monetary value of money is returned
total = 0walk over the array money (from left to right)
total = total + money[i]*values[i]return total
101
Write the method sum in Java
int sum(int[] money, int[] values){//post: returns the monetary value of money int total = 0; int i; for (i = 0; i<money.length; i++){ total = total + money[i]*values[i]; } return total;}
102
You need to be able to print out the change in words Declare a method printMoney, which takes an array with the
money to be printed and an array of the names of the coins and prints on the screen the number of each of the coins.
What is the algorithm for the body of the method?
void printMoney(int[] m, String[] names)//post: the names and numbers of the coins// in M are printed on the screen
walk over the array money (from left to right)if money[i]>0 println money[i] : names[i]
103
The method printMoney in Java
void printMoney(int[] m, String[] names){//post: the names and numbers of the coins// in M are printed on the screen int i; for (i = 0; i < m.length; i++){ if (m[i] > 0) { println(m[i] + " " + names[i]); } }}
104
Finally, the main programvoid main(){//all the declarations go here println("********* Vending Machine **************"); println("******* Choose From the Following ******"); println("1: Mars Bars 30 p *"); println("2: Twix 35 p *"); println("3: Mini Skittles 10 p *"); println("4: Crisps 44 p *"); println("****************************************"); print("Please make your choice"); int choice = readInt(); int cost = prices[choice-1]; print("Please pay in " + cost + " pence, paid in "); int payment = readInt(); println(payment); println("Your change in the fewest possible coins: "); printMoney (coins(payment - cost, values), coinNames);}
105
While loops for loops are ideal to use with arrays, where you
know exactly the number of iterations. When you want repetition and you don't know in
advance how many times the repetition will occur you can use recursion or a while loop construct.
It is a matter of taste whether you use while loops or recursion when you don't know beforehand how many times you need to repeat.
Like recursion generalised loops can go infinite. When writing code you must ensure that your code will terminate.
106
While Loops
while (condition){ body of loop}the body of loop includes something that will make the
condition go false eventually A loop where the condition cannot become false is an
infinite loop. The loop below will not stop.while (true){ body of loop}
107
Example of a generalised loop
void main(){char answer = 'y'; char buf = ' ';showInstructions();while ( answer == 'y‘ || answer == ‘Y’ ){
playGame(); print("Do you want to play again(y/n)? "); answer = readChar(); buf = readChar() ;
} println("thanks for playing");}
buf is needed to hold theReturn character which isnever used, just discarded
108
Example of a generalised loop The rest of the code:
void showInstructions(){println("instructions go here");
}void playGame(){println("the whole game goes here");
}
How would you implement this recursively? Trace the code with the input y y k. In addition
to the column for the variable answer have a column for the methods being executed, a column for input and a column for output.
109
method in ans output methodmain y
ShowInstructions instructions go here
playGame the whole game goes here
main y y Do you want to play again(y/n)? y
playGame the whole game goes here
main y y Do you want to play again(y/n)? y
playGame the whole game goes here
main k k Do you want to play again(y/n)? k
thanks for playing
110
Summary
When you want repetition and you don't know in advance how many times the repetition will occur you can use recursion or a while loop construct.
Use for loops with arrays since you know the bounds.
A simulation program for a vending machine was developed.
Susan Eisenbach 111
Lecture 8 : The Design of Algorithms
Lecturer : Susan Eisenbach
This is the 8th lecture on Java in which we look at how to design programs.
112
Sorting an unknown number of numbers In the tutorial question last week you were
asked to sort 10 numbers. This is quite a restrictive problem. How would you sort any number of numbers
(say up to 100)? Firstly you need to know how many numbers
you are going to sort. There are three ways of doing this. You can type
in the number of numbers, followed by the numbers. These can be processed with a for loop.
113
Sentinel values If you don't want to count the numbers first and
there is at least one value that could not be in the list (say if you were sorting non-negative numbers any negative value would do, otherwise a very large or very small number that wouldn't be in your data for example –9999) put it at the end.
For example, if you are sorting the numbers 1, 6, 4, 0, 7, 8
The list 1, 6, 4, 0, 7, 8, -1 is entered and the first 6 numbers are sorted.
The value –1 (which mustn't be sorted) is called a sentinel value.
114
How do you read in the list? You need to declare the array at its maximum size.
You need to declare an integer variable to hold the actual length of the list, which you get by counting.
This will have to be passed to the sort method. You need a boolean variable that is true iff you should
continue reading numbers.
You need a double variable to hold the number that is read in.
double[] vector = new double [100];
int len = 0;
boolean goOn = true;
double buf;
115
Now you need a while loop to read in the numbers
while (goOn){buf = readDouble();goOn = len < 100 && buf > -1;if (goOn) {
vector[len] = buf;len = len + 1;
}} It is important not to store the sentinel value in
the array
116
The special End of File character
When input comes from a file rather than the keyboard after all the input has been consumed a system predicate isEOF is set to true.
When input comes from the keyboard you can set this predicate to true in 2 ways– by typing in ^Z (pronounced Control Z)(windows) or ^D (linux)– by pressing the EOF button on the rhs of the input panel
This predicate can be used to stop reading in values.
117
Now you need a while loop to read in the numbers
double[] vector = new double[100];
int len = 0;
while (!isEOF() && len < 100){
vector[len] = readDouble();
len = len + 1;}
118
The programming process programming without much thought only works
for small problems many different schemes exist to systematise
programming they encourage programmers of diverse abilities
and experience to produce programs of uniform quality
we'll use a three-stage process which provides a framework to:– generate consistent, understandable programs – allow scope for individual programmers to apply their
own problem-solving skills.
119
The programming process requirements specification : What should the
program do? results in a document known as the
requirements specification or specification This is written in formal logic and/or concise
English.I know you believe you understand what you think I said,
but I am not sure you realise that what you heard is not what I meant.
Anon
120
The programming process
design : How will the program satisfy these requirements? – data - information the program manipulates– algorithms - methods to manipulate the data results in
the design documentation or design implementation : design is transformed
into code– coding - should be routine, results in the "finished
product" - tangible code – testing - does the program perform according to spec?
121
Design documentation
design is an iterative process, progressively more detailed decisions are made:– data – algorithms
the process of refining the algorithms with detail is known as
stepwise refinement or top down design documents required:
– data declarations - for the data – pseudo-code - for the algorithms
122
Specification of a calculator Concise verbal statement to start:
The program should accept two numbers, separated by an arithmetic operator, and should produce the correct arithmetic result, if this is calculable.
Forms the basis of a discussion between programmer and client to fill in details.– What is a number?– What is an arithmetic operator?– What sums are calculable?– What form should the sum be in?– What should the program do if the result is not calculable?– How many calculations should the program do?
123
Refining the requirements specificationThe program should accept two numbers, separated by an
arithmetic operator, and should produce the correct arithmetic result, if this is calculable.
Numbers are non-negative whole numbers. Arithmetic operators are +, -, * and /.Calculable means that the result must be finite, whole and
non-negative.Input consists of number operator number return.Input may be separated by spaces and is separated from
the result by a new line. It is assumed that the user types in correct data.A potentially incalculable result will produce the error
message: "cannot calculate".
124
The data
What does a program do? It consumes input and produces output. The first stage of design is to figure out what inputs to the program are and what the outputs from the program are.
All inputs and outputs identifiers (names) need to be declared and defined
Data types are those that are recognised by Java and written in Java
Comments are after //
125
Inputs and outputs
inputs are from the keyboard– first– op– sec
outputs are to the screen– result– errorMessage
program called calculator
126
Data declarations for the calculator
String errorMessage = "cannot calculate";int first; char op; //one of: + - * / int sec;int result;
Now all we need to do is define a calculator //performs simple arithmetic on //non-negative integers
127
Pseudo-code We need a language to write our algorithms in. This could be Java but then you need to worry
about syntax details. Instead we will use a language called pseudo-
code. It has no predefined syntax. It is close enough to Java to translate obviously.
It is close enough to English that you don't have to worry about fussy details of syntax.
Everyone's pseudo-code is slightly different. There has already been some pseudo-code used.
128
Stepwise refinement When writing the algorithm whenever things get
complicated make up a name and hive the complication off to another process to be dealt with later. (Use indents instead of brackets and semicolons)
calculator: read first, op, sec if the expression is calculable then evaluate the expression put the result else put errorMessage
129
Extend data declarations to include Expression
class Expression{ int first; char op; //'+','-','*','/' int sec;
}
130
Now define evaluate
evaluate: pre IsCalculable switch on op '+' : result first + sec '-' : result first - sec '*' : result first * sec '/' : result first / sec
131
Now isCalculable Turn isCalculable into something that is obviously
a predicate - a boolean methodswitch on op
'-' : result first >= sec '/' : result sec != 0 '+', '*' : result true
: result falseor
return op == '+' || op == '*' || op == '-' && first >= sec || op == '/' && sec != 0
132
Design complete For first year programs, the data declarations (extended
with anything new that comes out of the pseudo-code) and pseudo-code form the design.
Before proceeding to write the code, reread the specification. Check that the design meets the specification and change the design if it does not.
It should be straightforward to turn the design into code. The class, variable and method declarations should come
from the data declarations. The code should come from the pseudo-code. Amend the
pseudo-code and data declarations if you decide on any changes. Programming is an iterative process and there will be changes.
133
Declarations
class Expression{
int first;
char op;
int sec;
}
String errorMessage = "cannot calculate";
Expression expr;
134
isCalculable (both versions)
boolean isCalculable (Expression e){return e.op == '+' or e.op == '*' ||
e.op == '-' && e.first >= e.sec || e.op = '/' && e.sec != 0;
}boolean isCalculable( Expression e ) {switch ( e.op ) {
case '-' : {return e.first >= e.sec;}case '/' : {return e.sec != 0;}case '+' : {return true;}case '*' : {return true;}default : {return false;}
} }
135
Evaluate:
int evaluate (Expression e){) assert (isCalculable(e)); switch ( e.op ) {
case '+' : { return e.first + e.sec; }case '-' : { return e.first - e.sec; }case '*' : { return e.first * e.sec; }case '/' : { return e.first / e.sec; }default : { println(Why?")}
} }
136
Finally, the program:
void main(){
Expression expr ;
expr.first = readInt();
expr.op = readChar();
expr.sec = readInt();
if (isCalculable(expr))
{println(evaluate (expr));}
else {println(errorMessage);}
}
137
Summary
To be able to solve a problem by computer you must be able to decide what the problem is and how it should be solved.
Programs written in Java must be designed before they are committed to code.
The first step in solving a problem is to understand what the problem is; this is called the specification stage.
138
Summary(cont.) How a problem should be solved should be tackled
after completely determining what the problem is. How to solve the problem comes next - the design. The method of stepwise refinement consists of
decomposing a problem into simpler sub-problems. This data needs to be decided on as well. An algorithm describes how the inputs to a
process produce the outputs. Algorithms are described in pseudo-code.
Susan Eisenbach 139
Lecture 9 : Designing InputLecturer : Susan Eisenbach
This is the 9th lecture on Java in which we look at the kinds of difficulties reasonable
input causes a programmer.
140
Back to the calculator The specification of a calculator was too rigid.
Any reasonable calculator program would be more flexible about its input. The original specification said:
Input consists of number operator number return. Input may be separated by spaces and is separated from the result by a new line. It is assumed that the user types in correct data.
More reasonably would have been a specification that included:
If the user fails to type in correct data then an error message "not an expression" will be output.
141
Altering the previous declarationsThe data declarations:class Expression{
int first; char op; int sec;
}String notCalculable = "cannot calculate"String syntaxError = "not an expression" The program declaration:calculator //program performs arithmetic on non-negative ints The method declarations:evaluate = int evaluate(expression) pre isCalculableisCalculable = boolean isCalculable(expression)
What happened to result?
142
Pseudo-code
The only change needed in the main program is that instead of using the Java readInt, readChar and readInt to read in an expression it should be hived off to its own method to be sorted out. Pseudo-code isn't wonderful for such fiddly details so the code is also provided.
143
Calculator:
readExpressionif the expression
isCalculable evaluate the expression print the resultelse print notCalculable
All the real work needs to be done in readExpression
expr=readExpression();
if isCalculable(expr){
println
(evaluate(expr));
}else{
println
(notCalculable);
}
144
How do we do input? Previously our input was done with the statements:
expr.first = readInt(); expr.op = readChar(); expr.sec = readInt();
If you type in:x + 2
You never want your users to see wrong answers or messages you didn't write.
Could not read integer, incorrectly formatted number (x)
145
Why?
Our input routine must be able to deal with receiving syntactically incorrect data and outputting the error message
"not an expression" readInt terminates on any non-numeric
character. Given the input x + 2 readInt reads in the x,
the first non-numeric character, rejects it as a number, and terminates the entire program.
146
Converting numeric character strings to numbers readInt() reads in numbers as strings and then
converts what it has to a numeric value. How does it convert "345" into 345? You process the characters from left to right. string left value of number
"345" 0 "45" 10*0+3 = 3 "5" 10*3 + 4 = 34 "" 10*34 + 5 = 345
3 4 5 0334345
147
How do we convert the character '5' to the number 5? Java has many built in methods that will do this.
Kenya doesn't have these methods. All characters have ascii values.
– '0' is 48 – '1' is 49– '2' is 50, etc
So the ascii value of ('5') minus the ascii value of ('0') is equal to
You can get the ascii value of a character by assigning it to an integer variable.
So if c is a char, c – 48 will be the value you want.
5
148
Switches can be used to convert a character to a numeric value. Write a method that takes a character in the range '0'
<= character <= '9' and returns the numeric value, eg '0' 0, etc. Use a switch statement.
int convert(char c){assert (isDigit(c));
switch (c) {case '0' : {return 0;}case '1' : {return 1;}case '2' : {return 2;}case '3' : {return 3;}case '4' : {return 4;}case '5' : {return 5;}case '6' : {return 6;}case '7' : {return 7;}case '8' : {return 8;}case '9' : {return 9;}default : {println("how?");}
}}
this only works ifthe character is a digit
149
isDigit for the assertion
Write a predicate (boolean method) isDigit that returns true iff a character is in the range '0' to '9'.
boolean isDigit(char c){return '0' <= c && c <= '9'
}
150
Buffering input If you wish your program to print out all error messages
then you have to read in the characters and convert them into numbers yourself.
To write a calculator which will accept both 31+4 and 31 + 4 we need to process a character at a time and convert the characters into numbers where appropriate.
3 1 + 4 \n
{ {
3 1 + 4 \n
{ {first number character terminating
number
151
There are three ways we can write readExpression:
read one character at a time and process it as it arrives read the complete input line into an array of char and
then process it do not use String, because you cannot process
characters in it and because readString() will only read up to the first space
you will only know that you have finished a number when you are looking at the character that follows:– 3 1 + 4– 3 5+4
in the first example you need to read in the ' ' to know that the number is 31. In the second example you need to read in the '+' before you know that the number is 35.
152
Processing a line at a time If we wish to process a line at a time then
readExpression will need to be rewritten: readLine if isValid //number operator number convert line to expression else println syntaxError readExpression readLine, isValid and convert still need to be
written.
153
if isValid //number operator number convert line to expression This says divide the problem in two. First walk over
the array of characters checking that you have characters that will convert to what you want, then convert the entire string.
Dealing with error filled input is difficult and this simplifies the task since you only do the conversion on syntactically correct input.
You can only use this technique if your input data can be looked at more than once without consuming it.
154
In Java
Expression readExpression(){char[] line = new char[20]; Expression e;line = readLine();
if (isValid(line)) {e = convert(line); return e}
else{ println(syntaxError); return readExpression();}
}
155
Alternatively you could have a readExpression which is done a character at a time:
readNum if okay readOp if okay then readNum if not okay println syntaxError throw away rest of line readExpression where readNum and readOp still need to be
written.
156
Summary Design is an iterative process so the designer may need
to return to an earlier stage for amendments and additions.
There are frequently several ways to solve a problem. To find the best way solve the problem in the ways you think are good and then compare the solutions for clarity.
Errors identified and corrected at the design stage are less expensive than those that survive to the implementation stage and beyond.
Some program somewhere has to convert characters typed in into numbers used in programs.
Anything but the simplest input is difficult to do.
Susan Eisenbach 157
Lecture 10: Testing and Debugging Lecturer : Susan Eisenbach
For extra material read part of Chapter 10 of
Java Software SolutionsThis is the 10th lecture in which how to test whether a program fulfils its specification
and how to debug it, if it doesn't are covered.
158
Testing test that your program does what it was required to
do go back to the specification test at the limits of data ranges alter program if it fails with any legal input data document what the program does in situations where
the specification does not describe the intended behaviour
the program should never be allowed to crash or rubbish (an incorrect answer or inappropriate error message) be allowed to appear on the screen
draw up a test table
159
The specification for Calculator The program should accept two numbers, separated by an
arithmetic operator, and should produce the correct arithmetic result, if this is calculable.
Numbers are non-negative whole numbers. Arithmetic operators are +, -, * and /. Calculable means that the result must be finite, whole and
positive. Input consists of number operator number return. Input may be separated by spaces and is separated from the
result by a new line. If the user fails to type in correct data then an error message
"not an expression" will be output. A potentially incalculable result will produce the error message:
"cannot calculate".
160
Test dataInput
Expected Outcome
Comment
3+3 6 correct addition
10-2 8 correct subtraction
3* 4 12 correct multiplication
21 /3 7 correct exact division 22/3 7 correct whole num. division
4- 11 cannot calculate appropriate error message
22/0 cannot calculate appropriate error message
0/0 cannot calculate appropriate error message
2&3 not an expression appropriate error message
3^4 not an expression appropriate error message
161
Not so straightforward test data
Input
Expected Outcome
Comment
-3 ??? outside of specification
6+ ??? outside of specification
+ ??? outside of specification
= ??? outside of specification a-b ??? outside of specification
0*0 0 at limits of specification
biggest number - biggest number
0 at limits of specification
biggest number *1 biggest number at limits of number range
biggest number +1
overflow error outside of specification
biggest number *10
overflow error outside of specification
162
Test as you code bugs (technical term) are errors in programs bugs are difficult to find in complete programs test each method as soon as you have written it two ways of testing methods: test harnesses - write a small program to test
each method incremental testing - use the whole program to
test each new method either way, testing as you go takes up less time
then post testing
163
Example test harness to test evaluate
class Expression{int first;char op;int sec;
}void main(){Expression e;
e.first = readInt(); e.op = readChar(); e.sec = readInt();println(evaluate(e));
}
int evaluate( Expression e ) { switch ( e.op ) {
case '+' : {return e.first + e.sec; }case '-' : {return e.first - e.sec; }case '*' : {return e.first * e.sec; }case '/' : {return e.first / e.sec; }
}return 0;
}
164
Alternatively, use incremental testing
Write the declarations and main program first. All declarations for methods have to be written
as well. These should include comments. The bodies of each method should be trivial.
These are called stubs. Execute the program. If there is a bug then fix it. Then replace one stub at a time. Each time
testing the code. Bugs can always be isolated to the latest added
code.
165
Example stubs for testing the main program
Expression readExpression(){Expression e;
e.first = 2;e.op = '*';e.sec = 21;return e;
}
boolean isCalculable( Expression e ) {return true;
}
int evaluate( Expression e ) {assert (isCalculable(e));
return 42;}
166
Calling the stubsString notCalculable = "cannot calculate";
class Expression {int first = 0;char op;int sec = 0;
}
void main(){Expression expr;
expr = readExpression();if ( isCalculable(expr) ) {println("= " + evaluate( expr ) );}else {println( notCalculable );}
}Expression readExpression(){stub code goes here}boolean isCalculable( Expression e ) {stub code goes here}int evaluate( Expression e ) {stub code goes here}
code beingtested
167
Debugging complete code
when a program goes wrong you need:– what code was being executed– what data was being used
insert debugging code need to produce a trace main program entered
isCalculable entered
evaluate entered
<crash>
168
Permanent tracing code use a boolean constant at the top of the code
boolean tracing = true; at the start of each method foo include: if (tracing) {println( "foo entered" );} at the end of each void method include: if (tracing) {println( "foo exited" );}
¿ Why don't non-void methods get this code as well? When you don't want to see the trace you change the
value of tracing to false.
169
Debugging data
Need to print out values of possible offending variables
Use another boolean constant for this: boolean debug = true ;
Insert code where it might be needed: if debug {println("ch = " + ch);} Write methods to print out classes: void printExpression(Expression e)
170
Summary Test throughout program development to ease finding
bugs. Use test harnesses and stubs to find bugs in methods. Test a program against its requirements. Test with typical data, then at limits then outside the
specification. If a program does not work properly it needs to be
debugged. Insert debugging code to find the source of the error. Do this systematically.
Trace your program by hand. Time spent this way will be less than the time spent sitting at the machine looking for bugs.
Susan Eisenbach 171
Lecture 11 : Abstract Data Types Lecturer : Susan Eisenbach
For extra material read Chapter 12 ofJava Software Solutions
This is the 11th lecture on Java in which we define abstract data types and describe an actual use.
172
Another Calculator We will consider a program which can deal with a "long"
expression defined as follows:Expression=Operand,{Operator,Operand,} "="Operand = intOperator =‘+’ | ‘-’| ‘*’ | ‘/’| ‘^’
The expression now corresponds to any arithmetic expression with several operators but without brackets.
In the simplest case do 'left-to-right’ evaluation. Thus 3 + 4 - 5 + 6 = ( 3 + 4 ) - 5 + 6 = ( 7 - 5 ) + 6 = 2 + 6 = 8 The ideas embodied in the first Calculator could be
adapted to give pseudo-code along the following lines.
173
Start Off Calculation: read first operand read operator calculate. write out the result which is held in first operand.calculate: if operator isn't "=" read second operand evaluate the expression assign the result to first operand read operator calculate.What is wrong with this?
174
PrecedenceLeft-to-right evaluation only applies to operations of the same
precedence. Consider the expression a + b * c ^ d / e =Precedence rules
^ highest* / high+ - low= lowest
The program will need to scan the input expression and can safely evaluate subexpressions from left to right until a higher-precedence operator is encountered.
The current evaluation will have to be suspended until the higher-precedence operation has yielded a result.
175
Operations Required
1. Insert a subexpression2. Remove the most recently inserted
subexpression3. Examine the most recently inserted operator. Better to have two data structures one for
numbers one for operators. This data structure is called a stack. Have you seen another data structure
that looks like a stack?
176
Stack Operations
isEmpty returns true iff the stack has no elements in it.
empty returns an empty stackstack = empty | push( item, stack)
top returns the top element of the stack. push takes a stack and an item and returns
the stack with item added at the top. pop takes a stack and returns it with the top
element removed.
177
User defined types Java cannot provide every data structure that is
needed by every programmer. Java lets you create new data structures using
its classes. When accessing elements of these user defined
data structures methods are used. So instead of getting elements with x[i], like
arrays or x.i like fields in classes, the programmer has to write methods to get items from the user defined data structures.
178
class NumStack{//provides a stack of integers//declarations needed: the data structure goes here
boolean isEmpty(){code goes here}
Stack empty(){code goes here}//post: isEmpty(empty())
int top (){code goes here}assert (! isEmpty()):"no top of an empty stack";
Stack push (int item){code goes here}//post top(result)=item
Stack pop(Stack s){code goes here}assert (isEmpty(s)):"cannot pop an empty stack";}
179
Using NumStack When using NumStack nums (and OpStack ops),
you don't use the actual data declarations, because that doesn't model the data structure and may be changed.
You use the access methods that need to be written: isEmpty, empty, pop, push and top.
So you write nums.push(3) to push 3 onto nums (and ops.top() to get the top element).
Use is independent of the implementation of the method.
180
calculate: if there is another item (operand or operator) if it is an operand push it onto the numberStack, skip over the item, calculate the rest of the expression else if the operatorStack isEmpty or its top is of lower precedence than the item's precedence push the item onto the operatorStack, skip over the item calculate the rest of the expression else pop the top two operands and the top operator, evaluate the expression formed, push the result onto the numberStack, calculate the rest of the expression
181
1
Example: calculate 1+3*4 /2 =
4
3 *
+
12 /
2
6
7
if there is another item (operand or operator)
if it is an operand
push it onto the numberStack, Skip over the item,
calculate the rest of the expression
else if the operatorStack isEmpty or its top is of
lower precedence than the item's precedence
push the item onto the operatorStack,
skip over the item
calculate the rest of the expression
else pop the top two operands and the top op,
evaluate the expression formed,
push the result onto the numberStack,
calculate the rest of the expression
182
An array implementation of a stack
Declaration of this stack:
‘-’ ‘*’ ‘/’‘+’
5
1 2 3 4 5 6
183
An array implementation of a stack
Data declarations of this stack:class Stack{
int items = new int[20];
int pointer = 0;
//methods go here
}
pointer = ___ when the stack is emptypointer = ___ when the stack is full
184
Modelling data relationships
Arrays and records don't model everything. In Java you can define your own structures. Whether or not Java data structures are suitable
follow a three stages process for establishing any data-store:– Discern the need for a data store and establish its
characteristics and the interrelationships of its components.– Make arrangements to create a data store within the program
which faithfully reflects the real-world structure. – Produce code to manage the structure - i.e. to examine the data
store and to insert and remove items.
185
Important jargon In general these operations will not be as simple as for
arrays and each operation will be realised as a separate method, called an access method.
In Java you can consider the use and creation of the data structure entirely separately.
The programmer can consider how the data store will be accessed without needing to bother about the practical details of controlling and manipulating storage - i.e. in the abstract. For this reason, the collection of operations is often known as an abstract data type.
Using abstract data types is a major tool for program decomposition in modern programming practice.
186
Summary When designing a data structure a programmer must:
– establish those characteristics dictated by the problem– create a data structure that has these characteristics – produce code to manage the structure.
Operations designed to manage a data structure are called access methods. A collection of such operations, all applicable to a particular type of data structure, is called an abstract data type.
A stack is an example of an abstract data type. Arithmetic expressions can be evaluated, by using stacks to store
both numbers and operators until needed.The use of the stacks ensures that the correct order of operations is observed.
Next term you will look at many different abstract data types since they are a very powerful programming tool.