Second Summer 2002


Chapter Six: Review Exercises. Solutions
Questions:

  1. Which loop statements does Java support? Give simple rules when to use each loop type.

    while, for, do-while.

    A for loop is an idiom for a while loop of a particular form: a counter runs from start to the end, with a constant increment. If your loop does not match this pattern, don't use the for construction. Use a while loop for iterations that do not fit into the for pattern. But if you know where you start, where you're going, and how fast you're going, use a for loop.

    Sometimes you want to execute the body of a loop at least once and perform the loop test after the body was executed. The do loop serves that purpose.

  2. What does the following code print?
    for (int i = 0; i < 10; i++) {
      for (int j = 0; j < 10; j++) 
        System.out.print(i * j % 10);
      System.out.println();  
    } 
    
    0000000000
    0123456789
    0246802468
    0369258147
    0482604826
    0505050505
    0628406284
    0741852963
    0864208642
    0987654321

    i will take all the values from 0 to 9 (including 9,) one by one, and for each one of these values of i the variable j will take all values from 0 to 9 (including 9,) one by one. For each i and j their product is computed and the remainder of this product when divided by 10 will be printed.

    The output will contain 10 lines, with 10 digits on each line. Each line corresponds to one of the 10 values that i will have, and on each line the 10 values will correspond to the 10 values of j for that i. When we move to a new value of i we also print a new line.

    So the output of this program will be in the shape of a matrix, or a table, in which line i and column j will have the result of

    (i * j ) % 10

  3. How often (how many times) do the following loops execute? Assume that i is not changed in the loop body.
    for (i =   1; i <= 10; i++) ...
    for (i =   0; i <  10; i++) ...
    for (i =  10; i >   0; i--) ... 
    for (i = -10; i <= 10; i++) ...
    for (i =  10; i >=  0; i++) ...
    for (i = -10; i <= 10; i = i + 2) ... 
    for (i = -10; i <= 10; i = i + 3) ...

    Let's look at them one by one:

    for (i =   1; i <= 10; i++) ...

    i goes from 1 to 10 one by one, so 10 times.

    for (i =   0; i <  10; i++) ...

    i goes from 0 to 9 one by one, so 10 times.

    for (i =  10; i >   0; i--) ...

    i goes from 10 to 1, backwards, one by one, so 10 times.

    for (i = -10; i <= 10; i++) ...

    i goes from -10 to 10 one by one: 21 steps.

    for (i =  10; i >=  0; i++) ...

    For all practical purposes this is an infinite loop: i starts at 10 and is incremented by one at every step. The loop should start when i reaches 0. Does i reach 0, and if so when (and how)?

    for (i = -10; i <= 10; i = i + 2) ... 

    i starts at -10 and is incremented by 2 every time. The body of the for loop is executed every time i is less than or equal to 10. That means 11 steps: all even numbers in between -10 and 10, including 0 (zero).

    for (i = -10; i <= 10; i = i + 3) ...

    i starts at -10 and is incremented by 3. The loop ends when i becomes strictly bigger than 10. It's easiest to count the values of i for which the loop is executed: -10. -7, -4, -1, 2, 5, 8, that is, the body of the loop will be executed 7 times in all.

  4. Rewrite the following for loop into a while loop.
    int s = 0; 
    for (int i = 1; i <= 10; i++) s = s + 1; 
    
    int s = 0; 
    int i = 1;
    while (i <= 10) {
      s = s + 1; 
      i++;
    }  

  5. Rewrite the following do loop into a while loop.
    int n = 1; 
    double x = 0; 
    double s; 
    do { 
      s = 1.0 / (n * n); 
      x = x + s; 
      n++; 
    } while (s > 0.01); 
    
    int n = 1;
    double x = 0; 
    double s; 
    s = 1.0 / (n * n); 
    x = x + s; 
    n++; 
    while (s > 0.01) {
      s = 1.0 / (n * n); 
      x = x + s; 
      n++; 
    } 

  6. What is an infinite loop? On your computer, how can you terminate a program that executes an infinite loop?

    A loop that runs forever and can be stopped only by killing the program or restarting the computer. Some infinite loops are useful though: as long as we are sure we can end them when we want them. An example is:

    while (true) {
      String input = console.readLine(); 
      if (inputLine == null) break; 
      double x = Double.parseDouble(input); 
      sum += x;
      count += 1; 
    }
    This loop is also infinite, because at least in principle it can last forever. But it's a controlled infinite loop, which can be ended in a disciplined way.

  7. There are two ways to supply input to System.in -- describe both methods. Explain how the "end of file" is signaled in both cases.

    One way is from the keyboard. The end of file (or input) is detected when we type Ctrl-Z or Ctrl-D (depending on the system). The other way is through redirection (or pipes). The output of a program is redirected into the input of the second one. The second program will receive the output of the first and will process it as if it came from the keyboard. The "end of file" character will be generated by the system which will signal the end of output from the first program (or that the first program has ended).

  8. In DOS/Windows and Unix, there is no special "end of file" character stored in a file. Verify that statement by producing a file with known character count, for example, a file consisting of the following three lines:
    Hello
    cruel
    world
    Then look at the directory listing. How many characters does the file contain? Remember to count the newline characters. (In DOS you may be surprised that the count is not what you expect. DOS text files store each newline as a two-character sequence. The input readers and output streams automatically translate between this carriage return / line feed sequence used by the files and the '\n' character used by Java programs, so you don't need to worry about it.) Why does this prove that there is no "end of file" character? Why do you nevertheless need to type Ctrl+Z / Ctrl+D to end console input?

    If there were an end of file character and the program that reports the size of the files would just not report it we wouldn't know. But if the size of a file is reported by counting all the characters inside a file we can prove that no end of file character is stored in a file because since the reported size would not account for it.

    When we redirect a file in an application that reads from standard input the system takes care of sending an end of file character, when the file is finished. The size of the file is known in advance.

    When we type from the keyboard we don't know ahead of time how much we would be typing and so when we decide to signal the end of input we type an end of file character (Ctrl-Z or Ctrl-D, depending on the system).

  9. How can you read input from System.in

  10. Show how to use a string tokenizer to break up the string
    "Hello, cruel world!"
    into tokens. What are the resulting tokens?

    Here's a way to do it:

    StringTokenizer st = new StringTokenizer("Hello, cruel world!"); 
    while (st.hasMoreTokens()) {
      String token = st.nextToken(); 
      System.out.println(token); 
    } 

    This gives us:

    Hello,
    cruel
    world!

  11. Give a strategy for reading input of the form
    name of bridge length of bridge
    Here the name of the bridge can be a single word ("Brooklyn") or consist of several words ("Golden Gate"). The length is a floating-point number.

    You can do it in two different ways: counting the tokens beforehand or not counting them beforehand. Here's a solution that follows the second strategy:

    StringTokenizer st = new StringTokenizer(console.readLine()); 
    String name = "", 
           token = ""; 
    double length = 0; 
    while (st.hasMoreTokens()) {
      name += token; 
      token = st.nextToken(); 
    } 
    length = Double.parseDouble(token); 

  12. What is a "loop and a half". Give three strategies to implement the following "loop and a half":
    loop {
      read employee name 
      if not OK, exit loop 
      read employee salary
      if not OK, exit loop 
      give employee 5% raise 
      print employee data 
    } 
    A loop in which the real test for loop termination is in the middle of the loop, not at the top. This is called a loop and a half because one must go halfway into the loop before knowing whether one needs to terminate it.

    Strategy One: loop while done == false and exit by making done true if not OK.

    Strategy Two: use break when you need to stop the loop.

    Strategy Three: if the loop is inside a method one can use return in place of break and the method would terminate. Alternatively we could also exit the entire program with

    System.exit(0);

    Use a boolean variable, a break statement, and a method with multiple return statemtens. Which of these three approaches do you find clearest?

    I like using a break in most cases as it quickly finishes the loop. If I use a boolean I need to make sure I get to the top of the loop without doing anything else.

    However for larger programs when I use flowcharts I also find using a boolean variable works well for me, in terms of managing the complexity of the program.

  13. What is a sentinel value? Give simple rules when it is better to use a sentinel value and when it is better to use the end of the input file to denote the end of the data sequence.

    A value that is not actual input (but could be) and that is used to detect an end of input (partial or total). Using a sentinel works if if there is some restriction on the range of input values. In many cases, though, there isn't. In that case we should either prompt the user for the end of input (and perhaps accept a keyword) or accept Ctrl-Z or Ctrl-D depending on the operating system.

    Hint: consider the number of data sets and the origin of the data (keyboard input vs. file input).

    I find that it really doesn't matter where the data is coming from, really.

  14. How would you use a random number generator to simulate the drawing of a playing card?

    Random generator = new Random(); 
    int card = generator.nextInt(13) + 1;
    if (card > 10) card += 1; 
    int color = generator.nextInt(4);
    

  15. What is an "off by one" error? Give an example from your own programming experience.

    I was off by one when I tried to compute a random number between 10 and 50, once, in class. But that was not coming from a loop.

    You can be off by one when you try to draw a hollow square of width 40 and height 40 character by character, as in the example for nested loops last week.

    Off by one are errors that happen when the starting point of a condition is not clear, such as starting with a 0 or a 1 and reaching all the way to the upper limit or ending right before it. You can be off by one when you traverse the characters in a string because you need to remember that the characters are indexed starting at 0.

  16. Give an example of a for loop in which symmetric bounds are more natural.

    When you're counting it's easier to start at 1 and go all the way to how many you want to count (for example, n) including that value.

    for (int i = 1; i <= n; i++) {
      // do something... 
    } 
    Give an example of a for loop in which asymmetric bounds are more natural.

    When traversing characters in a string you need to start at zero and the length is not a valid index.

    for (int i = 0; i < s.length(); i++) {
      // work with s.chartAt(i)... 
    } 

  17. What are nested loops.

    When the body of a loop contains another loop we say that the second one is nested into the first one.

    Give an example where a nested loop is typically used.

    Nested loops are used when you need to deal with more than one dimension, or more than just one variable. If you need to compute a cartesian product you need two variables. If you need to get to the entities that populate a two dimensional space you need two variables, and to iterate through all of them you need to use two loops one nested inside the other.

    Example of entities in a two dimensional space: chairs in a cinema hall. Variables that can help us access them: their row and seat number (on that row). If you park in the Atwater garage (wherever that is) and you forgot where you parked you may need to use a pair of nested loops to organize your search (one loop for the floors and another one for the parking spots on each floor to locate your car.


Last updated: Jun 16, 2002 by Adrian German for A201