Tutorial 3 (Jan 26): Loop Variations, Printf, Debugging, Formatting Code
Sorry for the delay posting the material up, as I've been extremely busy.
For this class, we went through a program called Change.java, with no loops. The program asked the user for a number between 0 and 100, which represented the cents in a price (eg. $0.xx). The program then told the user how many dimes and pennies were necessary to make up the change. For example, if the price was $0.42, the change would be 5 dimes and 8 pennies.
We then went through five variations of the program, each using loops differently. These programs were identical in behavior, and the user is unable to tell the difference when using the program.
- Infinite While Loop with Break
We created a While loop around the code which we wanted to repeat. In this case, the code to repeat is "ask the user for input, do something with input, display output." Since the condition is just while(true), the loop would execute infinitely. If you used Eclipse, any code after the loop would have an error, stating "Unreachable Code". This meas that there is no way to exit the loop, so any code after the loop would never be executed.
To fix the error, we added a break in the loop. We want to stop looping if the user enters "-1", so we add the conditional ie. if statement to check if the (input==-1). If input is -1, we break out of the loop. Any code in the loop which comes after the break will not get executed. By having the break between "getting the user input" and "doing something with the input", we check that the input is valid (between 0 and 100) before we do something with it. - While Loop with Sentinel
Sometimes we prefer not to use an infinite loop or break statements, because if we have many "entry points" and "exit points" for the loop, it can get confusing. If we put the sentinel into the loop condition, we no longer need to check for the sentinel in the loop, nor do we need to use break. A problem here is that we are asking the user for the first input when the first loop executes, but we are checking the loop condition before the loop executes. That means that the input variable is not yet initialized when we check the loop condition. We can fix this by initializing the variable properly (so that the loop condition is true and the loop can run at least once), or we can copy all the code inside the loop and paste it above the loop. By duplicating the code inside the loop, we ensure it runs at least once, before we check the loop condition and start looping. - Do-While Loop
At the end of 2), we duplicated the code in the While loop so that it runs at least once. This is important to note, because a While loop can run zero or more times. In comparison, a Do-While loop will run one or more times. In a Do-While loop, you "do" everything inside the loop once, before you check the loop condition at the end of the loop. Although you rarely have to use a Do-While loop, they can be helpful in some cases, especially when your loop condition depends on something you manipulate inside the loop. For example, you might open a new connection to a server in your loop, and the loop condition checks if the connection is not connected. - For Loop
In the handout, there are three examples of more common for loops. For loops are most commonly used to repeat code n number of times, where you either known n or you will determine n before the loop. The examples include a) counting from 0 to 49 (eg. 50 times), b) counting from 10 to 38 (increasing the loop control variable by 2 every loop), and c) counting from 0 to (someVariable-1). In practice, someVariable might be the length of an array or some number you ask the user for.
In the Change.java program, we don't know how many times the user wants the loop to execute, until they enter -1. As such, we don't use a typical for loop. Instead, we will demonstrate two less-used cases of the for loop.
The first one is a for loop with no loop control variable or loop condition. This is a special case of the for loop which is equivalent to while(true), essentially becoming an infinite loop. - For Loop with Sentinel
The other way we can use a for loop here is to put the sentinel inside the for loop. Instead of defining an upper boundary to count to, we set the condition to "when the loop control variable, ie. the user input, is equal to -1." Rather than adding to or subtracting from the loop control variable, we ask for a new user input every loop. This is similar to saying while(input!=-1){//get new input}.
Printf
We briefly covered how to use printf to format the price (42) before displaying it to the user as $0.42. In our example, we used %.2f to tell the program we want to display a float, with 2 decimal precision. Printf can also be used to format and display other types of variables, such as hexadecimal numbers or exponents.
Debugging
Debugging is an extremely vitally crucially important aspect of programming. When you write a simple program, you may be lucky enough to have no problems on your first try. However, it is extremely common to have errors in your code. For syntax errors and some other detectable errors such as unreachable code or uninitialized variables, your IDE can usually warn you about them. Fixing these also counts as debugging. However, for logic errors or errors which are correct syntactically, you often have to trace through the code manually. For simple programs, you can try different inputs by hand and write down the expected value of certain variables at different stages in your code. The IDE simplifies this process with break points and watches.
A break point tells the program where to pause execution, so you can examine the state of the program at that particular point. In Eclipse (and many other IDEs), you can set a break point by double-clicking the line number on the left of the code editor. You may also find the option under a Debug menu.
A watch is often combined with break points to trace variables. If you want to see how price in Change.java changes throughout the program, you can add watch the variable price. There is usually a small window with all the variables you are watching, where you can enter the variables you want to watch. Another way is to first set a break point, and run the program until the break point is reached. The program will pause, and list all the variables which have a value at that point in your program. You can right-click these variables and select "watch" to add them to your watch list.
Formatting Code
Although I covered this briefly in the email sent out in the first week of tutorials, it is important so I will cover it here as well.
Formatting code improperly is an telltale sign of a poor programmer. In your future classes, and in the industry, you will be expected to work with teams of varying sizes. TAs and instructors have to mark your code, classmates have to share and work on your code, and future coworkers will depend on your code as well. If your code has any errors or is incompatible with their code, they may have to trace through your code to see what's wrong. If your code is formatted properly, it's like reading a book with no spaces or punctuation; it's extremely frustrating, especially because formatting code legibly is a simple matter.
In Eclipse, if you highlight your code and press <CTRL+SHIFT+F> (<CMD+SHIFT+F> on Macs), it will attempt to indent your code properly. Your program has many nested blocks of codes (eg. Program > Class > Main Function > Loop > If). Every time you nest a block of code, you should be indenting it. When your nested code ends, you can reduce the indent so that a reader can easily tell where blocks of code start and end. If I can easily tell where an if statement or while loop starts and ends, I can trace and debug it much more easily. Indents can usually be achieved by pressing <TAB>, while reducing the indent can often by done with <SHIFT-TAB>. In many IDEs, you can select multiple lines of code, then use <TAB> or <SHIFT-TAB> to adjust the indent for the entire block of highlighted code.
The other thing to note is white spaces. While white spaces do not affect how the computer runs your code, they should be used to clearly mark where blocks of code begin and end. If you declare many variables, you may want to group or separate them with blank spaces, then comment them to indicate what groups of variables are for. There are no strict rules on how to use blank spaces, but the bottom line is you want your code to be very easy to read.