Presentation is loading. Please wait.

Presentation is loading. Please wait.

Feedback from exercises Arrays Nested loops & 2D arrays

Similar presentations


Presentation on theme: "Feedback from exercises Arrays Nested loops & 2D arrays"— Presentation transcript:

1 Feedback from exercises Arrays Nested loops & 2D arrays
Tirgul 5 Feedback from exercises Arrays Nested loops & 2D arrays

2 Common mistakes in ex3 Not defining String/repeating Strings as consts
many people wrote a method to get the parameter input from the user, but within it - repeated the input procedure 3 times (copy-paste), instead of creating a single method that prints a message, reads and verifies the input (and call it 3 times with a different message). private int getInput(String msg, int minLegalValue, int maxLegalValue)

3 Ex4

4 Arrays – basic use

5 Initializing Arrays At Creation Time
int[] numbers={5,15,5,6,5}; boolean[] bits= {true,false,true}; String[] words = {“hi”,”bye”); Position[] positions = {new Position(1,2),new Position()};

6 Working with the Command Line
Congratulations! We can finally understand the entire signature of the main function.

7 Command Line Arguments
The main method takes a String[] as a parameter. public static void main(String[] args) The contents come from the command line that called the program: java HelloCommandLine how are you 1 2 “how” “are” “you” args

8 Example: public class HelloCommandLine {
public static void main(String[] args){ System.out.println("There are " + args.length + “ arguments"); System.out.println("They are:"); for(int i=0; i<args.length; i++){ System.out.println(args[i]); }

9 Redirecting the Input and Output of Programs
The following saves the output of the program to the file out.txt (instead of printing it): java MyClass arg1 arg2 >out.txt To use input from a file (not from keyboard): java MyClass arg1 arg2 <input.txt Or we can combine: java MyClass arg1 arg2 <input.txt >out.txt These are all very useful features of the shell and work on any command (not just Java).

10 One more helpful shell command
If you are working on CSE computers from outside and would like to transfer a file to yourself maybe the easiest way is to use mutt mutt < -address> -a <file> < /dev/null For example: mutt –a ex4.jar < /dev/null

11 Common Array Errors: public class Test {
public static void main(String[] args) { String[] words; int num = words.length; //no array there yet! words[0]="hi"; words = new String[15]; num = words[0].length(); //no object there yet! words[15]="Hello"; //out of bounds! } Won’t compile crashes the program Exception in thread "main" java.lang.NullPointerException at Test.main(Test.java:7) Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 15 at Test.main(Test.java:8)

12 Arrays of length 0 It is legal to create an array of length 0.
char[] letters = new char[0]; int num = letters.length; //okay. char letter = letters[0]; //out of bounds! Notice the difference from these lines of code: char[] letters = null; //Allowed. int num = letters.length; //null pointer exc. char letter = letters[0]; //null pointer exc.

13 clone() The “method” clone() creates a copy of the array and returns it: int[] nums1 = new int[5]; // …put numbers into the array… int[] nums2 = nums1; int[] nums3 = nums1.clone(); 1 -2 8 nums1 nums2 1 -2 8 nums3

14 Call by Reference vs. Call by Value – Test Yourselves
In function calls, technically, arguments are always passed by-value (copied into a local variable in the function) When complex objects are passed, we get the effect of call by-reference (the local variable is an alias of the original one) The actual reference value is passed by value. The function gets direct access to the original object in the memory, and can influence it.

15 Call by Reference vs. Call by Value – Test Yourselves
We want to swap the values of two variabls using a method: public staic void main(Sting[] args){ int a = 5, b = 10; swapX(a,b); System.out.println(“a=“+a+” b=“+b);l }

16 Call by Reference vs. Call by Value – Test Yourselves
public void swap0(int a, int b){ int temp = a; a = b; b = temp; } Useless public void swap1(int[] a, int[] b){ int[] temp =a; a = b; b = temp; } Useless Which of these is useless?

17 Call by Reference vs. Call by Value – Test Yourselves
We want to swap the values of two variabls using a method: public staic void main(Sting[] args){ int[] a = {5}, b = {10}; swapX(a,b); System.out.println(“a=“+a+” b=“+b);l }

18 Call by Reference vs. Call by Value – Test Yourselves
public void swap2(int[] a, int[] b){ int[] temp =a.clone(); a = b.clone(); b = temp; } Useless public void swap3(int[] a, int[] b){ for(int i=0; i<a.length; i++){ int temp = a[i]; a[i] = b[i]; b[i] = temp; } Useful Which of these is useless?

19 Call by Reference vs. Call by Value – Test Yourselves
Remember that the reference is copied into a local variable in the function (object aliasing). In the useless examples the value of the local reference variables is changed (changing what a,b, temp point to). This doesn’t influence the original object in the memory, or the original reference to it. The useful example changes the values of the object’s properties (the array’s cells).

20 Examples of arrays in action

21 Random Shuffle public static void main(String[] args){
final int NUMBERS = 10; int[] numbers = new int[NUMBERS]; for(int i=0; i<numbers.length; i++){ numbers[i] = i; } shuffle(numbers); System.out.print(numbers[i] + " "); System.out.println(); Load up the array with numbers. Randomly shuffle the array Print the results

22 How do we shuffle? First, we randomly select the element that will appear last in the array, and swap it into place. Then, we’ll select the 2nd to last element, and swap it into place. Etc. We use java.util.Random – an object that selects random numbers.

23 Need to import java.util.Random;
Random Shuffle Need to import java.util.Random; private static void shuffle(int[] numbers) { Random rand = new Random(System.currentTimeMillis()); for(int i=numbers.length-1; i>=1; i--){ swap(numbers, i, rand.nextInt(i+1)); } private static void swap(int[] numbers, int i, int j){ int temp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = temp; This will change the array in the calling method since we are working through references!

24 Nested Loops & 2D Arrays

25 Powers Table We would like to calculate the non-negative powers of the positive integers Notice that there’s a difference between positives and non-negatives Positives integers are 1,2,3, … Non-negatives are 0,1,2,3,… Calculating the powers of a single integer is easy, as demonstrated in 2 more slides We are not going to use Math.pow()

26 PowersPrinter Ctor //this class a prints powers table for numbers 1-highestNumber and powers 0-highestPower public class PowersPrinter { //consts private static final int DEFAULT_HIGHEST_NUMBER = 5; private static final int DEFAULT_HIGHEST_POWER = 2; //members private int highestNumber; private int highestPower; //ctor public PowersPrinter(int highestNumber, int highestPower) { //sets highestNumber if (highestNumber <= 0) { System.err.println("highest number must be positive. set to default value"); this.highestNumber = DEFAULT_HIGHEST_NUMBER; } else { this.highestNumber = highestNumber; } //sets highestPower if (highestPower < 0) { System.err.println("highest power must be non-negative. set to default value"); this.highestPower = DEFAULT_HIGHEST_POWER; else { this.highestPower = highestPower; } Default highest number, power to which the table is generated Highest number, power to which the table is generated

27 PowersPrinter – Table & Rows
Prints a full powers table in a top-down design style. The table consists of single rows //prints a full table public void printTable() { //prints table rows in a loop for (int i = 1; i <= highestNumber; i++) { printRow(i); } //prints a single row public void printRow(int rowNumber) { //prints rowNumber's powers by calling calcPower for (int j = 0; j <= highestPower; j ++) { System.out.print(calcPower(rowNumber, j) + "\t"); System.out.println(""); Prints a single row in a top-down design style. The row consists of single power elements

28 PowersPrinter – A Single Power
Notice that calcPower() is defined static since it only provides an “external” calculation and does not interact with some specific instance data members private static long calcPower(int number, int power) { /* Assumptions: 1) number is positive 2) power is non-negative */ //power of 0 long result = 1; //multiply current result by number - power times for (int i = 1; i <= power; i++) { result *= number; } return result; Since calcPower() is a private method, it’s the programmer’s responsibility to provide this method the right arguments Follows the mathematical definition of the power function. long is another type, very similar to int but capable of representing larger numbers

29 PowersPrinter – Main public static void main(String[] argv) {
//verify that 2 arguments were given if (argv.length < 2) { System.err.println("\nUSAGE: java PowersPrinter <highest-number>" + " <highest-power>\n"); System.exit(-1); } //get user arguments - assuming legal argument types int userHighestNumber = Integer.parseInt(argv[0]); int userHighestPower = Integer.parseInt(argv[1]); //calculates userHighestNumber ^ userHighestPower System.out.println( PowersPrinter.calcPower(userHighestNumber, userHighestPower)); argv is a Strings array and has a length member If the user types non-integer arguments, java will throw NumberFormatException during runtime. The whole program terminates with exit code of -1 on System.exit(-1) No instance needed yet – static method call

30 PowersPrinter – Main (2)
//create an instance of PowersPrinter PowersPrinter pp = new PowersPrinter(userHighestNumber, userHighestPower); //prints a single row int rowNumber = 2; System.out.println("\nSingle row number " + rowNumber); pp.printRow(rowNumber); //prints the full table System.out.println("\nFull table "); pp.printTable(); }

31 PowersPrinter - Analysis
Invoking “java PowersPrinter 3 4” generates the following output : How many multiplications costs the 2nd row (for example) 1 takes 0 multiplications 2 takes 1 (2 = 1 * 2) 4 takes 2 (4 = 1 * 2 * 2) 8 takes 3 (8 = 1 * 2 * 2 * 2) 81 Single row number 2 Full table Total number of multiplications needed for a row of 5 elements is : =10 !!!

32 PowersPrinter2 – A Lighter Version
This is the only method of PowersPrinter2 different from its corresponding method in PowersPrinter public void printRow(int rowNumber) { //set first number to 1 (0 power) long number = 1; //prints rowNumber's powers by multiplying number by rowNumber for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= rowNumber; } System.out.println(""); Instead of invoking calcPower() implements the power calculation algorithm originally placed in calcPower() Now, a row of N elements takes N-1 multiplications Conclusion : Top-down design isn’t always better

33 PowersPrinter3 – Nested Loops
public void printRow(int rowNumber) { long number = 1; for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= rowNumber; } System.out.println(""); public void printTable() { for (int i = 1; i <= highestNumber; i++) { printRow(i); } public void printTableWithNestedLoops() { //prints table rows in a loop long number; for (int i = 1; i <= highestNumber; i++) { //single row number = 1; for (int j = 0; j <= highestPower; j ++) { System.out.print(number + "\t"); number *= i; } System.out.println(""); We separated number declaration from its assignment since it needs to be declared only once We multiply number by i which is equivalent to printRow’s rowNumber argument

34 PowersPrinter3 – Another Look
Generally, i is a legal loop variable name. But renaming it as currentRow makes the code more readable public void printTableWithNestedLoops() { //prints table rows in a loop long number; for (int currentRow = 1; currentRow <= highestNumber; currentRow++) { //inside a specific row number = 1; for (int currentPow = 0; currentPow <= highestPower; currentPow ++) { System.out.print(number + "\t"); number *= currentRow; } System.out.println(""); Rows loop. The current row number is currentRow Actually, we could have left number’s {declaration + assignment} attached, but it’s really unnecessary (re-declaring it again and again) Powers loop. The current power number is currentPow. This power too refers to the current row currentRow

35 Nested Loops  2D Arrays What if we know, we’ll need later to check some powers (within bounds), and The most important thing is the easy / quick access to the power results We wouldn’t like to scan the whole table for the right cell Nor would we like to recalculate the results every time We are willing to “pay” in memory pre-calculate once the whole table, and store it (cache)

36 Same members & constants as in PowerPrinter
PowersTable Class public class PowersTable { //original consts private static final int DEFAULT_HIGHEST_NUMBER = 5; private static final int DEFAULT_HIGHEST_POWER = 2; //original members private int highestNumber; private int highestPower; //new const + member private static final long ILLEGAL_INDICES_ELEMENT = -1; private long[ ][ ] table; //ctor public PowersTable(int highestNumber, int highestPower) { } Same members & constants as in PowerPrinter

37 PowersTable - Constructor
public PowersTable(int highestNumber, int highestPower) { //sets highestNumber if (highestNumber <= 0) { System.err.println("Highest number must be positive. set to default value"); this.highestNumber = DEFAULT_HIGHEST_NUMBER; } else { this.highestNumber = highestNumber;} //sets highestPower if (highestPower < 0) { System.err.println("Highest power must be non-negative. set to default value"); this.highestPower = DEFAULT_HIGHEST_POWER; } else { this.highestPower = highestPower; } //allocates and fills the table createTable(); } This is the only new line

38 PowersTable – createTable
This method is intended for internal use only (it is not part of the API) There’re highestNumber numbers – [1,…, highestNumber]. There’re highestPower +1 powers – [0, …, highestPower] private void createTable(){ //allocates the table table = new long[highestNumber][highestPower + 1]; //fills the rows’ entries in a loop for (int i = 1; i <= highestNumber; i++) { fillRow(table[i-1], i); } We would like to fill the i-th row of table (which index is i-1) with the powers of the number i

39 Heap Diagram Powers’ array are allocated one after the other
3 2 1 3 2 1 4 3 2 1 Rows’ array is allocated 3 2 1 highestNumber highestPower table 5 3 3 2 1 When an object (e.g. PowersTable) is constructed, it is kept in the heap The entries of the long arrays are initialized with 0 – the default long value 3 2 1

40 PowersTable - fillRow private void fillRow(long[] row, int rowNumber) { //power of 0 long number = 1; //other powers - multiply number by rowNumber for (int j = 0; j < row.length; j ++) { row[j] = number; number *= rowNumber; } fillRow() doesn’t know and doesn’t care that the parameter row is only a single row belongs to a 2D array We could have used (highestPower + 1) instead of row.length, since there’re highestPower+1 powers in every row – [0, …, highestPower]

41 What Just Happened Here?
createTable() is about to invoke filleRow(table[1], 2) row is created as a parameter of table[i-1] according to call by value concept table is created in createTable Heap Stack (createTable) Stack (fillRow) table = 87a9f5d i = 2 row = 5a76bfc table[i-1] is sent as fillRow’s argument table[i -1] = 5a76bfc number = 1 row.length = 4 Power of 0 j = 0 number = … Loop begins 1 2 4 8 3 2 1 table[i-1] values were updated !!!

42 PowersTable – Printing A Table
public void printTableWithNestedLoops() { //prints table rows in a loop for (int currentNumber = 1; currentNumber <= highestNumber; currentNumber ++) { //single row – loops over the powers for (int currentPower=0; currentPower<=highestPower; currentPower++) { System.out.print(table[currentNumber -1][currentPower] + "\t"); } System.out.println(""); Simple internal access to table indices

43 PowersTable - calcPower
public long calcPower(int number, int power) { //verify that number is in bounds if ((number < 1) || (number > highestNumber)){ System.err.println("number out of bounds"); return ILLEGAL_INDICES_ELEMENT; } //verify that power is in bounds if ((power < 0) || (power > highestPower)) { System.err.println("power out of bounds"); return table[number - 1][power]; External access to the powers table within Row number-1 contains the powers of number

44 PowersTable - Main public static void main(String[] argv) {
//verify that 2 arguments were given if (argv.length < 2) { System.err.println("\nUSAGE: java PowersTable <max-number> <max-power>\n"); System.exit(-1); } //get user arguments - assuming legal argument types int userHighestNumber = Integer.parseInt(argv[0]); int userHighestPower = Integer.parseInt(argv[1]); //create an instance of PowersTable PowersTable pp = new PowersTable(userHighestNumber, userHighestPower); //prints the full table System.out.println("\nFull table "); pp.printTableWithNestedLoops(); //prints a single power System.out.println("\nThe " + userHighestPower + "-th power of “ userHighestNumber + " is : " + pp.calcPower(userHighestNumber, userHighestPower)); PowersTable (unlike PowersPrinter) has no static methods and an instance must be constructed

45 Extra Slides

46 Static Cascade You got an API, implemented the public members / methods but then comes the hard part – thinking )-:

47 StaticCascadeBad This simple class has:
A single non-static member + getter Some non-static methods Ctor main - static import java.util.Scanner; //This class demonstrates a badly written code with a static cascade problem public class StaticCascadeBad { private String name; //instance name private static Scanner sc=new Scanner(System.in) //ctor public StaticCascadeBad(String name) {this.name = name;} //name getter public String getName() {return name;} //Does action #1. If instance name is david - should print:"david says: Action1 done" public void doAction1() { System.out.println(name + " says: Action1 done");} public void doAction2() { …} public void doAction3() { … } /* Counts from 1 to 10 .Creates a new StaticCascadeBad named by the user, prints a menu that begins with the instance name and performs on this instance an action chosen by the user.*/ public static void main (String[] argv) { countFrom1To10(); System.out.println ("What's the StaticCascadeBad name?"); StaticCascadeBad scb = new StaticCascadeBad(sc.next()); doAction(scb); } This class has a private member that affects its methods output Main code is top-down designed. Private methods need to be implemented doAction needs the instance data and therefore takes it as an argument

48 StaticCascadeBad - count
The programmer doesn’t know when to use static, so he tries without the static first main is static, countFrom1To10 is not … Code Compiler private void countFrom1To10() { for (int i = 0; i < 10; i ++) { System.out.println(i + 1); } StaticCascadeBad.java:59: non-static method countFrom1To10() cannot be referenced from a static context countFrom1To10(); Maybe the static will help? private static void countFrom1To10() { for (int i = 0; i < 10; i ++) { System.out.println(i + 1); } OK!!! Obviously that was the right choice, since this method does not interact with any non-static members or other non-static method

49 StaticCascadeBad - doAction
The programmer concluded from the last example that main can only invoke static method so this method is declared static as well private static void doAction(StaticCascadeBad instance) { //prints menu and get user chosen option int option = printMenu(instance); //performs the chosen action switch (option) { case 1: instance.doAction1(); break; case 2: instance.doAction2(); case 3: instance.doAction3(); default: System.err.println("Illegal action"); } Top-down design again… The right action is invoked on the instance argument

50 StaticCascadeBad - printMenu
The programmer doesn’t know when to use static, and this method is not invoked directly from main so he tries without the static first doAction is static, printMenu is not … Code private int printMenu(StaticCascadeBad instance) { System.out.println(instance.getName() + " says : choose an option"); System.out.println("1) bla bla"); System.out.println("2) bla bla"); System.out.println("3) bla bla"); return sc.nextInt(); } Compiler StaticCascadeBad.java:99: non-static method printMenu(StaticCascadeBad) cannot be referenced from a static context int option = printMenu(instance); Maybe the static will help? private static int printMenu(…) { } OK!!! And one method after the other falls into the hands of the evil static (cascade)

51 The Fixed Code - StaticCascadeFixed
import java.util.Scanner*; //This class is the fixed code of StaticCascadeBad public class StaticCascadeFixed { //similar code to StaticCascadeBad //main public static void main (String[] argv) { countFrom1To10(); System.out.println ("What's the StaticCascadeFixed name?"); StaticCascadeFixed scb = new StaticCascadeFixed(sc.next()); scb.doAction(); } doAction() became a non-static method of this class – Object Oriented Programming

52 doAction – A Comparison
It’s a non-static method that is invoked on a specific object  no argument needed Original Code Fixed Code private static void doAction(StaticCascadeBad instance) { //prints menu and get user chosen option int option = printMenu(instance); //performs the chosen action switch (option) { case 1: instance.doAction1(); break; case 2: instance.doAction2(); case 3: instance.doAction3(); default: System.err.println("Illegal action"); } private void doAction() { //prints menu and get user chosen option int option = printMenu(); //performs the chosen action switch (option) { case 1: doAction1(); break; case 2: doAction2(); case 3: doAction3(); default: System.err.println("Illegal action"); } These methods are invoked on the same object that doAction() was invoked on (this). Similar code correction in printMenu() too

53 Daily Schedule Let’s create a class that represents an appointment schedule We’ll build an object that will hold the appointments for a single day (later we can have several of these objects in order to build an appointment book for the month).

54 The first hour in the day The number of appointments on that day
public class DailySchedule { private int start; private String[] schedule; private int events; public DailySchedule(int startHour, int endHour){ if(startHour > endHour){ //bad input. do our best. endHour = startHour; } schedule = new String[endHour-startHour]; start = startHour; events =0; The first hour in the day The appointments The number of appointments on that day We remember the first hour so we can translate future times to indices in the array correctly.

55 Get the event at a given hour. What if there is no event?
public boolean schedule(String event, int hour){ int index = hour-start; if(index>=schedule.length || index<0 || schedule[index]!=null){ return false; } schedule[index] = event; events++; return true; public String eventAt(int hour){ int index =hour-start; if(index<0 || index>=schedule.length ){ return null; return(schedule[index]); Add a new event at a given hour. Returns true if we could schedule the event Get the event at a given hour. What if there is no event?

56 public String clear(int hour){ int index = hour-start; if(index<schedule.length && index>=0 && schedule[index]!=null){ String event = schedule[index]; schedule[index] = null; events--; return event; } else{ return null; public int numberOfEvents(){ return events; Clears a given hour Returns the number of scheduled events. Could we do without this field? Why use it?

57 public int findEvent(String event){ for(int i=0; i<schedule
public int findEvent(String event){ for(int i=0; i<schedule.length; i++) { if(schedule[i]!=null && schedule[i].equalsIgnoreCase(event)) return i+start; } return NOT_FOUND; public String toString(){ String result = "Daily schedule:\n"; for(int i=0; i<schedule.length; i++){ if(schedule[i] != null){ result = result + (i+start) + “ : " + schedule[i]; return result; Looks for a certain event. Returns a string representation of this object.

58 Example: class MyArray
class MyArray { public static void main(String[] args) { ... } /** * Print the 2D array nicely, surrounded by lines of ### */ public static void print(int[][] ar) { ... } }

59 Class MyArray public static void main(String[] args) { int[][] b = new int[3][2]; print(b); ... }

60 Class MyArray

61 Class MyArray

62 Class MyArray public static void main(String[] args) { ... int[][] a = null; print(a); }

63 Class MyArray

64 Class MyArray public static void main(String[] args) { ... a = new int[3][]; print(a); }

65 Class MyArray

66 Class MyArray public static void main(String[] args) { ... int n = a.length; System.out.println("a has " + n + " rows"); }

67 Class MyArray

68 Class MyArray public static void main(String[] args) { ... a[0] = new int[6]; a[0][2] = 14; a[0][5] = 26; a[1] = new int[0]; print(a); }

69 Class MyArray

70 Class MyArray public static void main(String[] args) { ... a[2] = new int[3]; print(a); }

71 Class MyArray

72 Class MyArray public static void main(String[] args) { ... a[2][0] = 3; a[2][1] = 5; a[2][2] = 13; print(a); }

73 Class MyArray

74 Conclusions The whole 2D array doesn’t need to be initialized all together. A 2D array is an array of arrays. The “sub-arrays” don’t have to be of the same length. All the elements (cells) of the array have to be of the same type. If arr is of type int[][], then arr[0] is of type int[] and arr[1][3] is of type int.

75 class Calendar Remember class DailySchedule?
Lets use it to create an annual calendar.

76 class Calendar class Calendar { private DailySchedule[][] days; public Calendar(boolean meuberet) { days = new DailySchedule[12][]; // 12 months days[0] = new DailySchedule[31]; // January days[1] = new DailySchedule[meuberet ? 29 : 28]; // February days[2] = new DailySchedule[31]; // March ... }


Download ppt "Feedback from exercises Arrays Nested loops & 2D arrays"

Similar presentations


Ads by Google