SOFTWARE DEVELOPMENT 1 Control Structures 2018W (Institute of Pervasive Computing, JKU Linz)
WHAT IS CONTROL FLOW? The control flow determines the order in which instructions are executed. Default: from top to bottom. This default behavior can be changed with control structures: 1. Composition: execute a sequence of instructions 2. Selection: choose from at least two alternatives continue with the next instruction or jump to another instruction 3. Iteration: repeat a block of instructions (loop, Schleife); at the end of the block: either jump back to the start of the block and repeat it or continue with the next instruction after the block Selection or iteration are also called branching (Verzweigung), since the control flow branches at this point. Software Development 1 // 2018W // 2
JAVA CONTROL FLOW Composition / Sequence Default behavior If there is no explicit branching order, Java executes the following instruction Branching: Selection If if-else if-else if-else if- - else switch Branching: Iteration While do-while for Software Development 1 // 2018W // 3
COMPOSITION :: EMPTY INSTRUCTION Syntax: ; An empty instruction is simply stated by a single semicolon. It has no effect whatsoever. Purpose: to fill syntactic holes: Insert an instruction where one is expected, but we do not want anything to happen. Software Development 1 // 2018W // 4
COMPOSITION :: BLOCK Syntax: { Instruction1; Instruction2;... Composition is grouping of several instructions in a single block. Instructions in the block will be executed sequentially. The block is syntactically similar to an instruction: it is allowed wherever single instructions are allowed. Variable declarations within a block are only visible and valid within the block. Software Development 1 // 2018W // 5
BLOCK :: PRIMITIVE INSTRUCTIONS Variable declarations Type nameofthevariable; Type nameofthevariable = initialvalue; Declaration of a local variable is an instruction Local variables are only visible from the point of their declaration to the end of the enclosing block. Expressions as instructions expression; An expression terminated by an semicolon is an instruction. The return value is discarded. Watch for side effects! Software Development 1 // 2018W // 6
VISIBILITY: VARIABLES IN BLOCKS public void withdraw(int amount) { int balance = 12345; System.out.println("Balance: " + balance); Local variables are only visible within the block in which they were declared, and in enclosed blocks. if (amount > 0) { // balance is visible in sub-blocks int newbalance = balance - amount; // after the declaration newbalance is also visible System.out.println("After withdrawal: " + newbalance); // newbalance NOT visible anymore! int newbalance = balance amount - 1; // beginning with the declaration, a new variable newbalance is visible System.out.println("After fees: " + newbalance); Software Development 1 // 2018W // 7
CONDITIONAL BRANCHING (IF-ELSE) First the condition is evaluated If the result is true, instruction1 is executed, if the result is false, instruction2 is executed if ( condition ) instruction1; else instruction2; The else part is optional: If there is no else part and the condition evaluates to false, nothing happens. condition Since it is impossible for a condition to be both true and false, only one of the two instructions will be executed, never both. true false instruction1 instruction2 Software Development 1 // 2018W // 8
CONDITIONAL BRANCHING (IF-ELSE) // Read a single character from the system input int keycode = System.in.read(); // If the user pressed enter (code 13), // then do nothing (skip the following) if (keycode!= 13) { IF with instruction block no ELSE part // If a letter has been entered, output it as character if (keycode >= 'a' && keycode <= 'z') System.out.println("Letter pressed: " + (char)keycode); // otherwise output just the numeric key code else System.out.println("Other key pressed, code is " + keycode); IF-ELSE with single instructions with ELSE-part SWE1.03 / IfSample1.java Software Development 1 // 2018W // 9
CONDITIONAL BRANCHING (IF-ELSE) int temperature = 50, month = 10; String assessment = null; // IF without block { if (temperature < 0) "dangling else" part // inner IF if (month < 5 month > 9) assessment = "cold"; of 1. or 2. IF? else assessment = "very odd"; belongs to 2. IF // IF with block { else if (temperature < 40) { // Dangling ELSE: ELSE always belongs to the directly preceding IF! if (month < 5 month > 9) if (temperature > 20) assessment = "unusually warm"; else assessment = "appropriate"; else assessment = "hot like hell"; // IF without ELSE: if there isn't yet an assessment, set to "typical" if (assessment == null) assessment = "typical"; System.out.println("The temperature is " + assessment + " for this time of year."); Software Development 1 // 2018W // 10 SWE1.03 / IfSample2.java
CONDITIONAL BRANCHING (IF-ELSE) "DANGLING ELSE" // Problem: // Alternative 1: if (num > 0) if (num < 10) System.out.println("option 1"); else System.out.println("option 2");? /* In this example we assume, that the else is part of the inner * if-statement. "option 2" should only be displayed, if num > 0 * and num >= 10, which can be combined to num >= 10. */ // Alternative 2: if (num > 0) if (num < 10) System.out.println("option 1"); else System.out.println("option 2"); /* Here it seems the "else" is part of the outer if-statement; * "option 2" should only be displayed if num <= 0... */ Software Development 1 // 2018W // 11
CONDITIONAL BRANCHING (IF-ELSE) "DANGLING ELSE" Solution (in Java) Indentation is just for readability. It has no influence on the control flow! For the compiler both examples are identical! Compiler needs to decide for one of the two alternatives. Which one?: Alternative 1 This phenomenon (choosing one else-alternative from two possible if-statements) is called dangling else Rule: else always belongs to the closest preceding if, that is within the current block Software Development 1 // 2018W // 12
SHORT-CIRCUIT-EVALUATION // Short-Circuit-Evaluation for &&: // second condition is not evaluated, if the first one is false if (x!= 0 && y / x > 0) z = 0; // equivalent to if (x!= 0) if (y / x > 0) z = 0; // Short-Circuit-Evaluation for : // second condition is not evaluated, if the first one is true if (x == 0 y / x > 0) z = 1; // equivalent to if (x == 0) z = 1; else if ( y / x > 0) z = 1; Software Development 1 // 2018W // 13
SWITCH STATEMENTS expression needs to evaluate to one of the primitive numeric data types byte, short, int, char, or to a String, or an Enumeration constantx are constants (literals, final variables) of the same data type as expression switch ( expression ) { case constant1: instructions ; case constant2: instructions ; instructions is a sequence of instructions First, expression is evaluated... Then all instructions, starting from the first constant that matches the result from expression, are executed Software Development 1 // 2018W // 14
SWITCH STATEMENTS If no constant matches the result of expression, the instructions starting from the default marker are executed The default part is optional. If no constant matches and there is no default, execution continues after the switch block A break instruction immediately leaves the switch block and continues execution after the block If a instruction sequence is not terminated with break, execution will continue with the instructions from the next case! This is only needed in exceptional cases: do not forget the break! switch ( expression ) { case constant1: instructions ; break; case constant2: instructions ; break;... default: instructions ; Software Development 1 // 2018W // 15
SWITCH STATEMENTS :: EXAMPLES int number = 27; // display the last digit as text switch (number % 10) { case 0: System.out.println("zero"); break; case 1: System.out.println("one"); break; case 2: System.out.println("two"); break; case 3: System.out.println("three"); break; case 4: System.out.println("four"); break; case 5: System.out.println("five"); break; case 6: System.out.println("six"); break; case 7: System.out.println("seven"); break; case 8: System.out.println("eight"); break; case 9: System.out.println("nine"); break; SWE1.03 / SwitchSample1.java Software Development 1 // 2018W // 16
SWITCH STATEMENTS :: EXAMPLES int month = 2, days; boolean leapyear = false; // Determine number of days for month: switch (month) { case 4: case 6: case 9: case 11: days = 30; break; case 2: if (leapyear) days = 29; else days = 28; break; default: days = 31; System.out.println(days + " days"); SWE1.03 / SwitchSample2.java Software Development 1 // 2018W // 17
CONDITIONAL BRANCHING (SELECTION) :: SUMMARY if statements allow to execute instructions only if a condition matches (resolves to true) With the optional else part it is possible to specify alternative instructions to execute if the condition does not match To match an expression with multiple different values, it is more convenient to use a switch statement switch statements are only applicable to certain data types and constant values if ( condition ) instruction1; else instruction2; switch ( expression ) { case constant1: instructions ; break; case constant2: instructions ; break;... default: instructions ; Software Development 1 // 2018W // 18
ITERATION :: LOOPS Loops are required to execute an instruction (or instruction block) several times Syntax: Generally a part for initialization The body of the loop, containing instructions A termination condition Different types of loops: Count-controlled loops Condition-controlled loops Infinite loops minimum of zero or minimum of one loops Statements: while, do-while, for Software Development 1 // 2018W // 19
WHILE LOOPS First the condition is evaluated If it resolves to true, the instruction is executed and then the control flow returns to evaluating the condition If the condition resolves to false, execution continues after the loop If condition resolves to false from the start, the instruction is never executed In the instruction (or instruction block) some element from the condition needs to be changed. If nothing is changed, the loop will never terminate: Infinite loop while ( condition ) instruction; condition true instruction false Software Development 1 // 2018W // 20
WHILE LOOPS :: EXAMPLES // Count-controlled loop: count from 1 to 10 int index = 1; // initialization while (index <= 10) { // termination condition // body System.out.println("This is line number " + index); index++; // Condition-controlled loop: Terminates when the random number // generator returns a number greater 10 int number = 0; // initialization while (number <= 10) { // termination condition // body number = (int) (Math.random() * 20); System.out.println("Random number from 0 to 19: " + number); SWE1.03 / WhileSample1.java Software Development 1 // 2018W // 21
WHILE LOOPS :: MINIMUM OF ZERO // "minimum of zero" loop: // Read an arbitrary amount of numbers from the user and sum them up. // Stop if the user enters a negative number. Since the first value // is entered before the while loop, it is possible that the loop body // is never executed. int next, total = 0; next = Input.readInt(); // initialization while (next >= 0) { // termination condition // body total = total + next; next = Input.readInt(); Class Input: Provides several helper methods to make reading inputs easier Is not part of the Java API! Download from the department homepage. Required in the exercise. System.out.println("Sum: " + total); SWE1.03 / WhileSample2.java Software Development 1 // 2018W // 22
WHILE LOOPS :: EXAMPLE GCD gcd(x,y) = greatest common divisor of x and y x if x = y gcd(x,y) = gcd(x-y, y) if x > y gcd(x, y-x) if y > x because from x=t*f1 and y=t*f2 infer (x-y) = t*(f1-f2) or: x if y = 0 gcd(x,y) = gcd(y, x mod y) otherwise Software Development 1 // 2018W // 23
WHILE LOOPS :: EXAMPLE GCD int divisor, a, b, x, y, z; System.out.println("Enter two numbers: "); a = x = Input.readInt(); b = y = Input.readInt(); //read 2 numbers Version 1 while (a!= b) { if (a > b) a = a - b; else b = b - a; System.out.println("GCD = " + a); // gcd(a,b) = a if a = b // = gcd(a-b,b) if a > b // = gcd(a,b-a) if b > a Version 2 while (y!= 0) { z = x % y; x = y; y = z; System.out.println("GCD = " + x); SWE1.03 / WhileSampleGcd.java Software Development 1 // 2018W // 24
DO-WHILE LOOPS Similar to while loop, but with reversed order of body and condition: First the body is executed (at least once) Then the condition is checked while ( condition ) do instruction; instruction; while ( condition ); condition instruction true instruction false true condition false Software Development 1 // 2018W // 25
DO-WHILE LOOPS :: EXAMPLE // Condition-controlled loop: // Enter numbers until their sum exceeds 20. int total = 0; // initialization do { // body total += Input.readInt(); System.out.println("Subtotal: " + total); while (total <= 20); // termination condition System.out.println("Total: " + total); Do-while loops are very similar to while loops: Can be used for both condition- and count-controlled loops Somewhere in the body a variable of the condition needs to be changed, so the loop terminates SWE1.03 / DoWhileSample.java Software Development 1 // 2018W // 26
FOR LOOPS for ( initialization; condition; increment) instruction; First, the initialization is executed once Then the condition is evaluated If true, the instruction is executed, then the increment, and after that execution returns to evaluating the condition If the condition resolves to false, execution resumes after the for loop Software Development 1 // 2018W // 27
FOR LOOPS For loops are very convenient for count-controlled loops. Every for loop can be rewritten to a while loop: for ( initialization; condition; increment) instruction; is identical to initialization; while (condition) { instruction; increment; Software Development 1 // 2018W // 28
FOR LOOPS :: EXAMPLES // Ouptut 10 lines with line numbers: // The count variable i is declared within the loop and // only visible within! for (int i = 1; i <= 10; i++) System.out.println("Line " + i); // Here variable i is not valid anymore // Output the powers of 2 for (int i = 1; i <= 256; i *= 2) System.out.print(i + " "); System.out.println(); // Run through a list: // Output all Java system properties import java.util.iterator; import java.util.set; Set propertynames = System.getProperties().stringPropertyNames(); for (Iterator i = propertynames.iterator(); i.hasnext();) { String propertyname = (String) i.next(); String propertyvalue = System.getProperty(propertyName); System.out.println(propertyName + " = " + propertyvalue); SWE1.03 / ForSample.java Software Development 1 // 2018W // 29
ENHANCED FOR LOOPS It is very common to execute instructions for each element of a set or array. Therefore an enhanced for loop was introduced for this case: for ( elementvariable : set ) instruction; set is a collection (list, array, ) of elements. Each element in set is assigned once to elementvariable and then the instruction executed. The set can be an array, a container class from the Java-Collection framework, or any custom class that implements the interface Iterable. (More about that in later chapters.) Example: Output all Java System properties (same as previous slide) for (Object propertyname : propertynames) { String propertyvalue = System.getProperty((String)propertyName); System.out.println(propertyName + " = " + propertyvalue); Software Development 1 // 2018W // 30
THINGS TO CONSIDER WHEN WRITING LOOPS Loops can be nested indefinitely, however you should be careful: this can easily lead to an immense amount of repetitions: for (int i = 0; i < 1000; i++) for (int j = 0; j < 1000; j++) for (int k = 0; k < 1000; k++) instruction; In this case, instruction will be executed 1.000.000.000 times! Infinite loops will make your program hang. Try to avoid them. Some examples: for (;;) ; while (true) ; for (int i = 0; i!= 5; i += 2) System.out.println(i); Software Development 1 // 2018W // 31
BREAK AND CONTINUE LOOPS while ( condition ) { instructions ; continue; instructions ; break; instructions ; continue will immediately redirect the control flow to the end of the loop and begin evaluating the condition again. break terminates the loop and resumes execution after the loop. Jumps like these will usually make your code hard to read, try to use them only where absolutely necessary. Software Development 1 // 2018W // 32
BREAK AND CONTINUE LOOPS // Enter numbers until the total exceeds 50. As soon as the total // exceeds 20, a subtotal should be displayed. int total = 0; do { System.out.print("Enter a number: "); total += Input.readInt(); // leave loop, when 50 is reached if (total > 50) break; // if the total is still below 20, jump to the beginning of // the loop, to avoid displaying the subtotal if (total <= 20) continue; System.out.println("Subtotal: " + total); while (total <= 50); System.out.println("Total: " + total); // Identical program without break, continue: total = 0; do { System.out.print("Enter a number: "); total += Input.readInt(); if (total > 20 && total <= 50) System.out.println("Subtotal: " + total); while (total <= 50); System.out.println("Total: " + total); break, continue is here not necessary! SWE1.03 / BreakSample1.java Software Development 1 // 2018W // 33
LABELED STATEMENTS If several loops are nested, it can necessary to label them: label: loop label is any identifier, and it is only visible within the loop. break label terminates the according loop. continue label resumes with the condition of the according loop. If break or continue are used without specifying a label (as it is mostly the way), it always means the inner most loop. Software Development 1 // 2018W // 34
LABELED STATEMENTS :: EXAMPLE // 2-dim. array [y-axis][x-axis] with sensor data double[][] sensordata = { { 1, 2, 3, {-1, 0, 1, {-5, -3, -2; // Check if the array contains a negative value. // Stop looking as soon as one has been found. boolean foundnegative = false; yloop: for (int iy = 0; iy < 3; iy++) { for (int ix = 0; ix < 3; ix++) { if (sensordata[iy][ix] < 0) { foundnegative = true; break yloop; break requires label, otherwise it would only leave the inner loop. if (foundnegative) System.out.println("Found a negative value."); else System.out.println("All is well..."); SWE1.03 / BreakBsp2.java Software Development 1 // 2018W // 35
VISIBILITY OF LOCAL VARIABLES { //... int a; test: for (a = 0; a < 100; a++) { int b; for (int c = 0; c < a; c++) { System.out.println(a * c); int d = 7; System.out.println(a * d); a is visible test is visible b is visible c is visible d is visible Software Development 1 // 2018W // 36
LOOPS :: EXAMPLES // Application to show the ASCII Charset public class ShowCharset { public static void main(string[] args) { System.out.println("ASCII Charset:"); for (int i = 2; i < 8; i++) { for (int j = 0; j < 16; j++) { char c = (char) (16 * i + j); System.out.print(c); System.out.println(); ASCII Charset: Char codes 0 127 are defined, but 0 31 are control characters which we do not want to display SWE1.03 / ShowCharset.java Software Development 1 // 2018W // 37
LOOPS :: EXAMPLES public class FactorialLoops { public static void main(string[] args) { int n = 5; int factorial = 1; //calculate n! with for-loop for (int i = 1; i <= n; i++) factorial = factorial * i; System.out.println(n + "! = " + factorial); factorial = 1; //calculate n! with while-loop int i = 1; while (i <= n) { factorial = factorial * i; i++; System.out.println(n + "! = " + factorial); factorial = 1; //calculate n! with do-while-loop i = 1; do { factorial = factorial * i; i++; while (i <= n); System.out.println(n + "! = " + factorial); SWE1.03 / FactorialLoops.java Software Development 1 // 2018W // 38
SOFTWARE DEVELOPMENT 1 Control Structures 2018W (Institute of Pervasive Computing, JKU Linz)