CS16, Summer 2012

Lab04:
Repetition structures


Goals for this lab

By the time you have completed this lab, you should be able to

Step by Step Instructions

Step 0: Get together with your assigned lab partner

By now you should know the drill: Choose who will be the first pilot and who will start as navigator, and then remember to switch (at least once) during the lab. But you should probably know the long-term goal too:

Each partner should participate in both roles in approximately equal parts over the course of the quarter. We realize it is not possible to equally split time in every lab, but it's worth trying, and it is possible to make up for unequal splits in future labs. We trust you will try to meet this goal. Thanks!

If your assigned partner is more than 5 minutes late, ask the TA to pair you with someone else for this week.

Step 1: Create a directory for this lab in the pilot's account

This lab's first pilot should log in. You will (both) work in this account for the rest of the lab.

Create a ~/cs16/lab04 directory and make it your current directory.

Don't start ch. While you will use it to translate some structures, this lab does not include any work to be done at the ch prompt. You should have a terminal window open though.

Step 2: Practice writing a while loop

In this week's homework you practiced writing while loops to learn their general structure, but did not exploit their primary purpose which is: to continue executing as many times as necessary to complete a task, without knowing beforehand how many times that will be.

You also learned how there are three important steps to writing a successful while loop: (1) initialization; (2) condition; (3) change of state. For example, the following code keeps selecting and printing random integers that range from 1 to 100, until it finds a value that is evenly divisible by 10. Then it prints a newline:

int num;
srand(time(NULL));
num = 1;                   /* initialize to step set up true condition */
while (num%10 > 0) {       /* evaluate condition */
    num = 1 + rand()%100;  /* change state, so eventually false condition */
    printf("%d ", num);
}
printf("\n");

That code segment is saved as findtens.ch in ~kyledewey/cs16/lab04/ and you can translate it with ch, even without copying it to your own directory. Here are a few runs executed from the cs16 class account:

-bash-4.2$ ch ~kyledewey/cs16/lab04/findtens.ch
63 7 13 83 33 18 31 3 84 42 40
-bash-4.2$ ch ~kyledewey/cs16/lab04/findtens.ch
42 84 100
-bash-4.2$ ch ~kyledewey/cs16/lab04/findtens.ch
77 28 91 28 97 35 93 65 75 6 15 48 52 25 43 78 99 5 83 98 25 70

Go ahead and try it yourself.

Now you write and test a while loop. Use emacs (or your favorite editor) to create a file named enter5.ch with the features specified below, and save it in your ~/cs16/lab04 directory. The idea is to keep asking the user to enter a value, until they enter a 5:

  1. Declare an int named value to store the user's input value.
  2. Initialize value to anything except 5.
  3. Begin a while loop that will continue as long as value is not equal to 5. The body of this loop will have more than one statement, so start a block too.
  4. Use printf to prompt the user to enter a 5.
  5. Use scanf to read the user's input into value.
  6. Terminate the block.

Save it.
Then use ch to translate and test it. If something doesn't work correctly, then fix the problem before going to Step 3. Here is what a sample run should look like:

-bash-4.2$ ch ./enter5.ch
enter 5: 3
enter 5: -1
enter 5: 5
-bash-4.2$
Note: Although unlikely in this case, in ch you can interrupt a runaway loop (one that won't quit executing) by typing ctrl-Z (control key and z at the same time).

Step 3: Convert a while loop to a do/while loop

Recall that a do/while loop checks the condition at the end of the structure, not at the beginning like a while loop. Therefore, a do/while loop always executes at least one time, and the initialization step can occur inside the loop body instead of before the loop begins.

Here is a rewrite of the random number code from above that uses a do/while loop:

int num;
srand(time(NULL));
do {
    num = 1 + rand()%100;
    printf("%d ", num);
} while (num%10 > 0);
printf("\n");

Now rewrite the loop you wrote for Step 2. First make a copy of your enter5.ch named do5.ch. One way is to use cp as follows before starting your editor (e.g., emacs):

-bash-4.2$ cp enter5.ch do5.ch

Or you can open enter5.ch with your editor, and save it as do5.ch before making any changes. Either way, make the following changes (and then save and test the new version):

  1. There is no need to initialize value before starting the loop, so delete that part. (Of course, you still must declare the variable.)
  2. Change the beginning of the loop to just "do" instead of the "while(condition)" you have there now.
  3. Add the "while(condition)" part immediately after the block terminator ("curly brace") at the end of the loop - and end this line with a semicolon.

Save it.
Then use ch to translate and test it. If something doesn't work correctly, then fix the problem before going to Step 4.

Step 4: Practice writing a for loop

First: switch roles between pilot and navigator if you did not already do that.

When the number of iterations are known before the beginning of a loop, most programmers prefer using for loops than either while or do/while loops. A for loop header has three fields that are specially designed to (1) perform an initialization step one time, right before the first iteration; (2) check a condition at the beginning of each iteration, and only enter the loop body if this condition is true; and (3) perform a change of state at the end of each iteration, before going back to recheck the condition.

For example, the following for loop will print the values 1 to 10:

int value;
for (value = 1; value <= 10; value++)
    printf("%d\n", value);

Here the value is set to 1 before anything else happens. The value is compared to 10 at the beginning of every iteration, and the loop continues until the value exceeds 10. And value is increased by 1 at the end of every iteration.
Thought question: What do you think this value equals after the loop ends?

Now write and test a for loop of your own, and learn something about character codes at the same time: Print all of the characters represented by the ASCII codes ranging from 33 ('!') through 47 ('/').

Create a file named codes.ch with the following features, and save it in your ~/cs16/lab04 directory:

  1. Declare a variable (as either char or int) to store an ASCII code.
  2. Write a for loop header and make its three fields accomplish (1) initializing the variable to '!' or its corresponding ASCII code value; (2) checking the condition that this variable is not greater than '/' or its corresponding ASCII code value; and (3) incrementing the variable by one each iteration.
  3. Write the loop body as just one line that prints the current character and a space to separate it from the next character.
  4. Print a newline after the loop is done.

Save it.
Then use ch to translate and test it. If something doesn't work correctly, then fix the problem before going to Step 5. Here is what a sample run should look like:

-bash-4.2$ ch ./codes.ch
! " # $ % & ' ( ) * + , - . /
-bash-4.2$

Step 5: Upgrade the random number guessing program from last week's lab

Here's a chance to apply some of what you learned in the preceding steps. You will start with a version of last week's program that already includes some of the optional features suggested in that lab. You will make two important changes to it: (1) let the user decide the maximum random value; and (2) let the user keep guessing until the correct value is entered. We will not tell you which types of loops to use - decide that on your own.

Save a copy of this guess4.c skeleton in the original pilot's lab04 directory. You can cp a copy from the instructor's account:

-bash-4.2$ cp ~kyledewey/cs16/lab04/guess4.c ~/cs16/lab04/

Read through the program to familiarize yourself with it, then change it to make it behave like our solution, as exemplified by the following run (after guess4.c was compiled):

-bash-4.2$ ./guess4
Enter maximum value - must be greater than 1: 0
Enter maximum value - must be greater than 1: 1
Enter maximum value - must be greater than 1: 10
Guess a number between 1 and 10: 5
Too low. Try again.
Guess a number between 1 and 10: 8
Too high. Try again.
Guess a number between 1 and 10: 7
Correct! Bye.

Use emacs (or another editor of your choice) to make the following changes:

  1. Replace "YOUR NAME(S)" at the top with your names.
  2. Notice that right now max is set to 1, but it should become greater than 1 by letting the user choose its value. So write a loop that keeps prompting the user to "Enter maximum value - must be greater than 1:" and reads the user's input until an appropriate quantity is entered.
  3. Write the beginning of a loop (after the statement that finds a random target value), and then terminate this loop right before the return statement at the end of the main function. Make sure this loop will continue executing as long as the user's guess does not equal the target, and that it will stop executing when the user guesses correctly.

You can use ch to test your program. Then make an executable version of it to run for the TA:

-bash-4.2$ make guess4

Step 6: Show off your work and get credit for the lab

Submit your code with the turnin program. You MUST have both your name and your partner's name in the file in order to receive credit. Remember that the original pilot needs to do this step, since that is whose account you have been using in Cooper Lab.

Bring up a terminal window on CSIL, and cd into the original pilot's cs16 directory, and cd again into the lab04 directory. Then type the following to turn in all four files that you created in Steps 2-5 above:

turnin lab04@cs16 enter5.ch do5.ch codes.ch guess4.c

Respond "yes" when the program asks if you want to turn in (be sure to read the list of files you are turning in), and then wait for the message indicating success.


Evaluation and Grading

Each student must accomplish the following to earn full credit for this lab:

Deadline for lab submission: Wednesday 7/25 (11:59pm)

Note that to be eligible for late turn-in with credit, you MUST have attended your entire lab period.


Optional Extra Challenge


Adapted by Kyle Dewey from a lab prepared by Michael Costanzo.