By the time you have completed this lab, you should be able to
while
loop to perform an action over and over
again until a goal is reacheddo/while
loop to go back and redo an action as
many times as necessary to reach a goalfor
loop to perform an action a specific number
of timesBy 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.
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.
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:
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).
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):
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.
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:
'!'
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.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$
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:
YOUR NAME(S)
" at the top with your names.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
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.cRespond "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.
Note that to be eligible for late turn-in with credit, you MUST have attended your entire lab period.
Optional Extra Challenge
- Don't really have time for more programming right now, but do have a few minutes to play with the guess4 program? Then try some larger problems when you run the program, like maximum 1000 or even 1000000. It's not as hard to guess as you might think - just use a "binary search" technique, wherein you always guess the value in the exact middle of the known range. This technique will take no more than log2max tries, so 10 or fewer tries if max is 1000, and 20 or fewer tries if max is 1000000. Here we apply the technique for maximum 100 (just takes six tries):
-bash-4.2$ ./guess4 Enter maximum value - must be greater than 1: 100 Guess a number between 1 and 100: 50 Too low. Try again. Guess a number between 1 and 100: 75 Too high. Try again. Guess a number between 1 and 100: 63 Too high. Try again. Guess a number between 1 and 100: 56 Too low. Try again. Guess a number between 1 and 100: 59 Too high. Try again. Guess a number between 1 and 100: 58 Correct! Bye.- Why not let the program count the user's tries? Then it can report how many tries it took the user to guess the random number. Change a copy of guess4.c (name it guess4a.c for example) to do that. You will need a variable to store the count; to initialize this variable to 0 before the guessing loop; and to increment the count by one in the loop body. Then add a closing print statment to report it.
- How about asking the user if they want to play again instead of just exiting the program after just one game? That will require another whole loop structure that completely contains all of the code from before the random value is selected to after the loop in which the user guesses. It will also require a variable to store the user's answer to a question such as "More games?" and you should change the current print statement that says "Bye."
- Or maybe print more ASCII codes, neatly in a table showing both characters and codes side-by-side? Modify a copy of codes.ch (or even better, convert it to a whole program named allcodes.c, for example) to print all of the ASCII codes from 33 to 126 (
'~'
). But don't just print all the characters on a single line by themselves. Instead print a neat table like the following (just the first 3 and last 3 lines of the table are shown):char int ! 33 " 34 [89 more table lines here] | 124 } 125 ~ 126
Adapted by Kyle Dewey from a lab prepared by Michael Costanzo.