Homework 9: Bottles Refactored
Concepts
The important concepts in this assignment are how to convert while loops to for loops, how to validate user input, and how to do things with loops in "steps" besides 1.
while
loops can be for
loops and vice-versa
Did you know that all while
loops and for
loops are essentially interchangeable? Consider this while
loop:
while (countdown > 0) {
cout << countdown << "..." << endl;
countdown--;
}
cout << "... fizzle.\n";
Notice the line int countdown
initializes the loop counter, the condition is countdown > 0
and how the last thing the loop does each round is decrement countdown
. How could this be rewritten as a for
loop?
cout << countdown << "..." << endl;
}
cout << "... fizzle.\n";
Notice that each loop component (initialization, condition, modification) are all still present. How would you rewrite the following for
loop into a while
loop?
cout << i << endl;
}
Using while
loops to validate user input
A common requirement of many programs is to continually prompt a user for input until what they enter is valid according to your requirements. For example, say you wanted the user to input a number between 0 and 100.
while (true) {
cout << "Enter a number between 0 and 100: ";
cin >> number;
if (number > 0 && number < 100) {
break;
} else {
cout << "I said between 0 and 100, genius.\n";
}
}
How does this loop work? Step through the logic on your own, imaging an input of 10 and an input of 1000.
This is one of a few common "loop patterns" you should be familiar with. That way, the next time someone at the programming party asks you to validate user input, you immediately think, "Ah, no problem, I'll use a simple while loop." And then you'll both dance.
Stepping through for
loops
Remember that you have total control over what changes during each repetition of a loop. For example, consider the output generated by the following loop:
cout << i << endl;
}
Notice how the loop modifier is declared as i += 2
. What does this loop print to the screen? How about this one:
cout << i << endl;
}
Homework Hint: capturing string input from the console
In this assignment, you will prompt the user to enter some words for the "product" to be used. You might try something like this:
cin >> product;
This would work if the product is just one word like "shampoo" or "water." However, if the user types "tea tree shampoo" or "vitamin water" you'll find that cin
only captures the first word. Why? Remember, cin
is sensitive to the datatype of the receiving variable and what is entered on the console. In the case of strings, cin
will capture every character until it encounters a whitespace character. Hence, only "tea" and "vitamin" would be assigned to the variable product
above.
The solution? Use a more robust input capturing tool: your new friend, getline()
. getline()
is a function or "mini-program" that you can use to capture everything a user types, rather than just the first word. Use it like this:
// ...
string product;
getline(cin, product);
This is like saying, "Hey computer, use getline()
to capture stuff from cin
and assign what you capture to the variable product
." We'll learn more about functions and getline()
later. For now, just realize how you can use it to satisfy this assignment's requirements.
Instructions
In this assignment, you will add three additional features to your song lyric generation program created in 08_bottles. Consider the following user feedback about your program:
- "I'll never forget the words again thanks to your program," says Lisa, "But it would be great if I could tell your program what sort of bottled product to use in the song."
- "Some of my choir friends are jokers and generated lyrics starting with 10,000 bottles and we sang for three days straight," laments Bart, "Can you make it so that the maximum number of bottles is 1,000?"
- "Is there a way to make the program generate lyrics where we can take 2, 3, or 4 bottles off the wall at a time?" asks Maggie.
Your goal for this assignment is to exercise using multiple loops and logic to create an enhanced lyric generation program. An example interaction might look like this:
What kind of product? pomegranate juice
How many bottles (1 - 1000)? 10000000
How many bottles (1 - 1000)? 10
How many are taken at a time (1 - 10)? 0
How many are taken at a time (1 - 10)? 20
How many are taken at a time (1 - 10)? 3
All right, here we go!
10 bottles of pomegranate juice on the wall,
10 bottles of pomegranate juice!
Take 3 down, pass them around,
7 bottles of pomegranate juice on the wall!
7 bottles of pomegranate juice on the wall,
7 bottles of pomegranate juice!
Take 3 down, pass them around,
4 bottles of pomegranate juice on the wall!
...
1 bottle of pomegranate juice on the wall,
1 bottle of pomegranate juice!
Take 1 down, pass it around,
0 bottles of pomegranate juice on the wall!
How might you implement this program? We recommend doing things one step at a time, and we recommend compiling and running after every step.
Step 1: convert the while
loop to a for
loop
Starting with the basic program from 08_bottles, change the main while loop to a for
loop. This is an exercise, and a required item in the rubric below.
Step 2: add the ability to customize the bottled product
Prompt the user for a string, and incorporate their input into the song lyrics.
Step 3: validate the number of bottles
Your program should accept any number between 1 and 1000, inclusively. Perhaps using a while
loop in the manner demonstrated under "concepts" above is a good choice.
Step 4: collect and validate the input for "number taken at a time"
Notice how the program doesn't accept 0
or a number greater than the initial number of bottles. This is similar to step 3, but with a slight twist.
Step 5: modify the number of bottles taken during each round of the song
Use the value the user provides for "how many are taken at a time" in the song lyrics, such that each round results in N
bottles taken from the wall.
Last step: clean up the logic and lyrics
If the number of bottles on the wall is less than the number to be taken, your program should continue the rest of the song by taking only 1 bottle per round until the number of bottles left is 0.
Your song lyrics should reflect proper pluralization. For example, if you "take 3 down" you should "pass them around"; whereas if you "take 1 down," you should "pass it around." In addition, "bottles" and "bottle" should be used appropriately wherever possible.
Requirements and Rubric
This work is worth 65 points.
Requirement | Points | Notes |
---|---|---|
Place your name in the comment header in main.cpp | 2 | |
Correct submission of zip file | 3 | |
Correctly changes main loop from while to for . |
10 | |
Incorporates user's choice of bottled product into lyrics. | 10 | |
Requires that number of bottles is between 1 and 1000. | 10 | |
Requires that the "number taken" is between 1 and the number of starting bottles, inclusively. | 10 | |
Each round correctly subtracts "number taken" from the number of bottles | 10 | |
Never prints a negative number of bottles on the wall | 4 | |
Correctly "takes" only 1 bottle per round when "number to take" is less than the number of bottles left on the wall | 2 | |
Correct pluralization of "pass them around" or "pass it around" | 2 | |
Correct pluralization of "bottle" or "bottles" | 2 |
Concepts Exercised:
© 2011 Yong Joseph Bakos.