Repeating Actions The "while" and "for" Controls Sections 4.1 & 4.2 (Also: Special Assignment Operators and Constants)
Overview Conditional control review Testing for yes or no Repeating the test Sentinel loops (while) Counting loops (for) increment, decrement and special assignment Nesting loops
Yes or Whatever! Recall "Do you want fries with that?" accepts "yes" in any case "yes", "YES", "Yes", "Yes, please.", … if (resp.toLowerCase().startsWith("yes")) { order.add("fries"); } …treats anything else as no "no", "nope", "nah", … "sure", "yeah", "yup", … "what", "pardon me?", "ummm", …
What Do We Want? Ideally? That’s too hard! How about Anything that means yes yes Anything that means no no Anything else try again That’s too hard! How about Yes yes No no
Getting a Yes/No Answer System.out.print("Do you want fries with that? "); String resp = kbd.next().toLowerCase(); kbd.nextLine(); if (resp.startsWith("yes")) { order.add("fries"); } Want them to answer "yes" or "no" So if they give a different answer? Ask them again
Asking Again First answer is wrong ask them again Right first time doesn’t ask again Do you want fries with that? yup Please say yes or no: yes A B Do you want fries with that? sure Please say yes or no: yes A B Do you want fries with that? nope Please say yes or no: no A B Do you want fries with that? yes A do the A step; possibly do the B step
Asking Again // A – done first System.out.print("Do you want fries with that? "); resp = kbd.next(); kbd.nextLine(); if (!resp.equalsIgnoreCase("yes") // not yes && !resp.equalsIgnoreCase("no")) {// and not no // B – possibly done System.out.print("Please say yes or no: "); resp = kbd.next(); kbd.nextLine(); } if (resp.equalsIgnoreCase("yes")) { order.add("fries");
Asking Again Again Second answer is wrong ??? uses that wrong answer which is not equalsIgnoreCase("yes"), so no! Maybe it should ask again again Do you want fries with that? yup. Please say yes or no: yeah. A B Do you want fries with that? yup. Please say yes or no: yeah. Please say yes or no: I did! Please say yes or no: YES! A B do the A step; as necessary do the B step
Getting a Yes/No Answer // A – done first System.out.print("Do you want fries with that? "); resp = kbd.next(); kbd.nextLine(); while (!resp.equalsIgnoreCase("yes") // not yes && !resp.equalsIgnoreCase("no")) {// and not no // B – possibly repeated System.out.print("Please say yes or no: "); resp = kbd.next(); kbd.nextLine(); } if (resp.equalsIgnoreCase("yes")) { order.add("fries"); Just change the "if" to "while"
The "while" Control Java Syntax while (condition) { repeatedAction(s); } if the condition is true, do the repeated action. then repeat as necessary! (keep doing the repeated action until the condition becomes false) if condition starts out false, body gets skipped
Note: No "else" for "while" You can change an if to a while if the data is bad, ask again if the data is still bad, ask again … You can’t change an if-else to a while if the data is bad, ask again, otherwise use it if the data’s still bad, ask again, otherwise use it just do the "use it" part after the loop
Exercise: Getting a Valid Grade What did you get on the test? 1000 Grade must be 0 to 100: 999 Grade must be 0 to 100: 9998 Grade must be 0 to 100: 98 What did you get on the test? 100 What did you get on the test? 0 What did you get on the test? -10 Grade must be 0 to 100: 100 A B A A A B do the A step; as necessary do the B step
Things to Notice In both examples: needed to get first answer before the loop (loop initialization) see if the input is not what we’re looking for (loop test) last command in loop is to get new input (loop update) it’s the same variable in initialization, test and update (the loop control variable)
Parts of a (while) Loop Initialization System.out.print("You have a disability? "); resp = kbd.next(); kbd.nextLine(); Initialization Happens before the "while" command Gets the first data value (Example: the user’s first answer to the question) loop control variable: resp
Parts of a (while) Loop Test In parentheses after the "while" while (!resp.equalsIgnoreCase("YES") && !resp.equalsIgnoreCase("NO")) { Test In parentheses after the "while" Is the test to keep going Is opposite of when to stop (Example: Stop when is resp is YES or NO; i.e. Keep going if resp is not YES and it’s not NO) loop control variable: resp
Parts of a (while) Loop Process System.out.print("Yes or no? "); Process This is the thing we want to do to each data value (Example: Tell user what we’re looking for.)
Parts of a (while) Loop Update Last thing to do in the loop!!! resp = kbd.next(); kbd.nextLine(); Update Last thing to do in the loop!!! Get the next data value (Example: the user’s next response) loop control variable: resp
Initialization & Update System.out.print("You have a disability? "); resp = kbd.next(); kbd.nextLine(); resp = kbd.next(); kbd.nextLine(); Usually the Same Especially if it’s an input command. (There are often slight variations.) loop control variable: resp
Loop Execution Initialization is carried out Loop condition is tested if test passed Body is executed Update command is executed Goes back to loop condition Continues until test fails "termination condition"
On the Importance of Updates It’s important that you do it! Sop("…isability?"); r = kbd.next(); while (!r.equals("yes") && !r.equals("no")) { Sop("Yes or no? "); // missing update! } You have a disability? yup Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no? Yes or no?
On the Importance of Updates It’s important that you do it last! Sop("…isability? "); r = kbd.next(); while (!r.equals("yes") && !r.equals("no")) { r = kbd.next(); Sop("Yes or no? "); } You have a disability? yup hello? Yes or no? what? Yes or no? yes Yes or no? People with disabilities should contact the department of social services at the address below.
Not Just for Bad Input Can use while loops for good data, too recall JavaAverage bad input loop ends Enter a number: 10 Enter another number or -1 to quit: 20 Enter another number or -1 to quit: 30 Enter another number or -1 to quit: 40 Enter another number or -1 to quit: -1 The average of the positive numbers you entered is 25.0. A B C D
Getting an Average System.out.print("Enter a number: "); // A num = kbd.nextInt(); kbd.nextLine(); while (num >= 0) { // no negative #s System.out.print("Enter … quit: "); // B num = kbd.next(); } System.out.println(); // C System.out.println("The average … is …."); // D Still need to sum the numbers and calculate the average….
Loop Processing Extra stuff that needs doing inside loop For each of the numbers, we must... ...add it to a running sum, and... ...count it Remember: inside the loop, you only have one piece of data add it to the running sum (not them) count it (not them)
Adding and Assigning Recall that we use + to add, = to assign totalTax = provTax + fedTax; provTax + fedtax just adds the numbers totalTax = saves the answer We can put the two steps together sum += num; += add and assign add these numbers together and save the answer saved in the variable on the left so same as sum = sum + (num);
Special Assignment Operators Works for all the math operators var += expr add expr to var var -= expr subtract expr from var var *= expr multiply var by expr var /= expr divide var by expr var %= expr (exercise) var must be a variable expr can be an expression courseGrade += LAB_WEIGHT * labPercent;
Counting Adding one to a variable is very common that’s what counting is! Could use += to add one... count += 1; ...but that’s five keystrokes We can do it in two count++; ++ add one to this variable called "increment"
Increment & Decrement These operations that are common in loops var++ add one to var ++var add one to var var-- subtract one from var --var subtract one from var You will see both prefix & suffix versions they are slightly different the difference doesn’t matter to us
JavaAverage Review Needs S.o.p commands! int sum, count, num; double ave; sum = 0; count = 0; num = kbd.nextInt(); kbd.nextLine(); // LCV init. while (num >= 0) { // LCV test. sum += num; // add num to sum count++; // count num num = kbd.nextInt(); kbd.nextLine(); // LCV upd. } ave = (double)sum / (double)count; Needs S.o.p commands!
Exercise Track the variables’ values a b c a = 1; 1 ? ? a++; b = a + 6; b--; c = b * 5; c += a; a *= 10; b /= 2; c %= 4; a *= b + c; note: sums b and c before it multiplies
Definite or Indefinite Repeat unknown number of times ABBBBBBCD, ABBBBCD, ACD, ABCD, ... "indefinite iteration" or "data controlled loop" usually a while loop Repeat known number of times ABBBC, ABBBC, ABBBC, ABBBC, ... "definite iteration" or "count controlled loop" can be done with a while loop but there is a better way!
Count-Controlled It’s not the data that tells us to stop just count how many times it’s done Enter your A1 grade: 100 Enter your A2 grade: 98 Enter your A3 grade: 87 Enter your A4 grade: 99 Enter your A5 grade: 100 Enter your A6 grade: 80 Your average is 94.0. A B C loop control variable: the assignment number!
Count-Controlled while Loop int sum, asgn, grade; double ave; sum = 0; asgn = 1; // LCV initialized while (asgn <= 6) { // LCV tested grade = kbd.nextInt(); kbd.nextLine(); sum += grade; asgn++; // LCV updated } ave = (double)sum / 6; Needs S.o.p commands! Question: why not divide by asgn instead of 6? Question: why (double)sum?
The for Control Count-controlled loops very common Want a shorter/easier way to make them All loop control actions in one place initialization (usually = 1) test (usually < something or <= something) update (usually ++) The "for" loop control
Count-Controlled for Loop int sum, asgn, grade; double ave; sum = 0; for (asgn = 1; asgn <= 6; asgn++) { // LCV i/t/u grade = kbd.nextInt(); kbd.nextLine(); sum += grade; } ave = (double)sum / 6; Needs S.o.p commands!
Easy Mistake to Make Change number of assignments to 10 int sum, asgn, grade; double ave; sum = 0; for (asgn = 1; asgn <= 10; asgn++) { grade = kbd.nextInt(); kbd.nextLine(); sum += grade; } ave = (double)sum / 6; What went wrong? How can we prevent that kind of mistake?
Constants Literals Named / Symbolic constant numbers: 3, 22, 3.14159 characters: ‘a’, ‘A’, ‘&’ strings: "Hello, world!" Named / Symbolic constant identifier must be declared public static final int NUM_ASGN = 6;
Constants Constant declarations go inside the class but not inside the method(s) public class CircleCalculation { public static final int NUM_ASGN = 6; public static void main(String[] args) { … }
Why Named Constants Easier to read and understand Changing value easier one change instead of many coincidental equality is not a problem is this 100 the max grade or the max enrolment? Compiler can catch the mistake Typo: 3.14519 for 3.14159 computer: "OK." Typo: NUM_AGSN for NUM_ASGN computer: "Huh?"
Naming Styles Use meaningful names Use multiple words as appropriate Naming conventions variableName CONSTANT_NAME
Exercise Declare Java constants for the maximum allowable enrolment for a course (which is 100) the number of feet in a mile (5280) the number of cm in an inch (2.54) the name of a data file (numbers.txt)
Loop using Constant Still needs S.o.plns! public static final int NUM_ASGN = 6; public static void main(String[] args) { int sum, asgn, grade; double ave; sum = 0; for (asgn = 1; asgn <= NUM_ASGN; asgn++) { grade = kbd.nextInt(); kbd.nextLine(); sum += grade; } ave = (double)sum / NUM_ASGN; Still needs S.o.plns! Exercise: change the number of assignments to 10.
while vs. for Same four parts of loop Initialization, test, processing, update while loops & for loops do exactly the same initialize; while (test) { process; update; } for (initialize; test; update) { process; }
Count Controlled Loops The "for" control is used when you know ahead of time how many iterations you want we wanted six assignment grades: six iterations count the iterations: count controlled loop In general, NUM_ITERATIONS iterations for (iter = 1; iter <= NUM_ITERATIONS; iter++) { (loop body = actions to be repeated) } iter is the loop control variable; NUM_ITERATIONS is how many iterations we want.
Exercises Write a loop to print out "Hello" 10 times (each "Hello" on its own line) Write a loop to print out the numbers from 1 to 20 on a single line separate the numbers by spaces end the line when you’re done
Find Maximum of N Numbers Initialization initialize maximum to something small Count the numbers Processing get the next item update the max Math.max returns the bigger of the two numbers you give it int max, n; max = Integer.MIN_VALUE; for(n = 1; n <= N; n++) { num = kbd.nextInt(); max = Math.max(max, num); } Integer.MIN_VALUE is the smallest integer Java knows
Exercise Change this loop into a loop to find the minimum value int max, n; max = Integer.MIN_VALUE; for(n = 1; n <= N; n++) { num = kbd.nextInt(); max = Math.max(max, num); } What’s the name of the largest integer Java knows? What’s the name of the function that finds the smaller of two numbers?
Exercise Change this loop to be data-controlled stop when negative number is entered int max, n; max = Integer.MIN_VALUE; for(n = 1; n <= N; n++) { num = kbd.nextInt(); max = Math.max(max, num); } Enter positive integers below. Enter -1 to end. 10 20 30 40 11 12 13 5 -1 The largest positive number you entered was 40.
Loops with Conditionals For each positive integer the user enters, say whether it’s divisible by 5 stop when enter a negative number System.out.println("Enter some numbers below: "); num = kbd.nextInt(); while (num >= 0) { // TODO: say whether num is divisible by 5 // get next number } kbd.nextLine();
Expected Output Pattern: Enter some numbers below: 49 49 is NOT divisible by 5. 95 95 is divisible by 5. 72 72 is NOT divisible by 5. -1 Print Read NotDivisible Divisible Pattern: Print, Read, repeat ((Divisible OR NotDivisible), Read) Remember: need to read before the loop! Otherwise first test is testing garbage!
Loops with Conditionals whether divisible if-else control num = kbd.nextInt(); while (num >= 0) { // say whether num is divisible by 5 if (num % 5 == 0) { System.out.println(num + " is … by 5."); } else { System.out.println(num + " is not … by 5."); } // get next number
Note the Indentation Each level 4 more spaces 8 12 16 num = kbd.nextInt(); while (num >= 0) { // say whether num is divisible by 5 if (num % 5 == 0) { System.out.println(num + " is … by 5."); } else { System.out.println(num + " is not … by 5."); } // get next number 8 12 16 Remember the Format command!
Loop + Conditional Execution whether divisible if-else control while (num >= 0) { // say whether num is divisible by 5 if (num % 5 == 0) { System.out.println(num + " is … by 5."); } else { System.out.println(num + " is not … by 5."); } // get next number num = kbd.nextInt(); 78 90 84 95 100 80 is divisible by 5 is divisible by 5 is divisible by 5 is divisible by 5 is NOT divisible by 5 is NOT divisible by 5
Exercise Write a loop to read in six grades Use a for loop (why?) print "Good work!" if that grade is 90+ Use a for loop (why?) Enter your grade on A1: 100 Good work! Enter your grade on A2: 80 Enter your grade on A3: 95 Enter your grade on A4: 78 Enter your grade on A5: 84 Enter your grade on A6: 90
Loops inside Loops Draw four lines with 20 stars on each line four lines all the same a "for" loop each line: twenty stars, all the same another "for" loop line ends after the twenty stars ********************
Drawing One Line Need a line of 20 (or whatever) stars 20 times (print out one star) then end the line // for each of the 20 stars for (int star = 1; star <= 20; ++star) { // print that star System.out.print("*"); } // end that line (after all the stars) System.out.println(); ********************
Drawing Multiple Lines Need 4 lines 4 times (print out one line) // for each of the four lines for (int line = 1; line <= 4; ++line) { // print one line … // same code as before … // including the loop! } ********************
Loops inside Loops Draw four lines with 20 stars on each line // for each of the four lines for (int line = 1; line <= 4; ++line) { // for each of the 20 stars for (int star = 1; star <= 20; ++star) { // print that star System.out.print("*"); } // end that line (after all the stars) System.out.println();
Inner and Outer Loops One loop (inner) inside another (outer) inner // print a rectangle for (int line = 1; line <= height; line++) { // print a line of stars for (int star = 1; star <= width; star++) { // print a star System.out.print(‘*’); } System.out.println(); outer loop inner loop Notice that it doesn’t matter what you name the loop control variable, so long as you stick with the one name for each loop.
Identify the Pieces and Patterns Write nested loops to read numbers (integers) until a negative number is read print that many "Hello"s on one line How many hellos? 5 Hello! Hello! Hello! Hello! Hello! How many hellos? 3 Hello! Hello! Hello! How many hellos? 7 Hello! Hello! Hello! Hello! Hello! Hello! Hello! How many hellos? -1
Inner and Outer Loops Outer loop Inner loop Read numbers until a negative number is read while loop: Print out a given number of "Hello"s told number before start for loop: for (int i = 1; i <= num; ++i) { S.o.p.("Hello! "); } System.out.println(); S.o.p.("How many Hellos? "); num = kbd.nextInt(); kbd.nextLine(); while (num >= 0) { // inner loop goes HERE } Change S.o.p. to System.out.print
Identify the Pieces and Patterns Write nested loops to read three valid assignment scores and calculate their average valid = between 0 and 100 (inclusive) Enter your A1 score: 67 Enter your A2 score: 789 That’s not valid. Try again! Enter your A2 score: 79 Enter your A3 score: 1000 Enter your A3 score: 100 Your average: 82.0%
Declaring Variables in Loops You can actually declare variables inside loop (and conditional) bodies for (a = 1; a <= NUM_ASGN; a++) { System.out.println("Enter grade:"); int grade = kbd.nextInt(); kbd.nextLine(); sum += grade; } that variable belongs to the loop! cannot be used outside the loop
"Scope" of a Variable Cannot use variable outside its scope ! for (a = 1; a <= NUM_ASGN; a++) { System.out.println("Enter grade: "); int grade = kbd.nextInt(); kbd.nextLine(); sum += grade; } S.o.pln("Last grade was " + grade); Cannot find symbol: variable grade ! The "scope" of grade
Declaring Loop Control Variable Often declare LCV of for loop in the loop for (int aa = 1; aa <= NUM_ASGN; aa++) { System.out.println("Enter grade: "); int grade = kbd.nextInt(); kbd.nextLine(); sum += grade; } S.o.pln("Last assignment was " + aa); Cannot find symbol: variable aa ! The "scope" of aa
Using Local Variables Good idea if the variable is not supposed to be used outside a narrow context outside the grade reading loop, who needs to know any particular grade? after counting to 6 (or whatever), who needs to know what number we’re on? If you need the variable after the loop, then you must declare it before the loop and if you don’t need it after, declare it inside!
Questions