CSCI 261 Programming Concepts (C++)

Winter/Spring 2012

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:

int countdown = 10;
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?

for (int countdown = 10; countdown > 0; countdown--) {
    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?

for (int i = 0; i < 23; i++) {
    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.

int number;
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:

for (int i = 0; i < 10; i += 2) {
    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:

for (int i = 10; i > 0; i -= 2) {
    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:

string product;
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:

#include <iostream>
// ...
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:

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:

Hello friend! I will generate song lyrics for you.
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: