6: More Loops and Functions

What We Will Cover


Continuations

Questions from last class?

What will be output after the following C++ statements have executed?

int count = 1;
while (count <= 3) {
    cout << count << " ";
    count++;
}
  1. 1 2
  2. 1 2 3
  3. 2 3
  4. 1 2 3 4

Homework Questions?

Homework Discussion Questions (Thursday)

  1. Did the use of functions shorten or lengthen the program? Why?
  2. Did the use of block comments clarify how to use a function?

6.1: Processing Input

Learner Outcomes

At the end of the lesson the student will be able to:

  • Use sentinel values to terminate a loop
  • Describe the advantages of using a Boolean variable to control a loop
  • Use do-while statements to repeat sections of code
  • Develop strategies for processing input and handling errors

6.1.1: Input Validation

  • Input validation is a common use for if statements
  • We use an if statement to test if the user has entered reasonable input
  • For example, if we want the user to enter a number greater than or equal to 1, we use code like:
    if (guess < 1) {
        cout << "Error: guess must be >= 1\n";
        return 1;
    }
    

Checking for cin Failure

  • Another problem arises if the user enters a string when we expect a number
  • For instance, in our guessing game program, we get incorrect results if the user enters "seven"
    int guess;
    ...
    cin >> guess;
    
  • The problem is that cin cannot convert the word "seven" into the number 7
  • When this happens cin fails, sets an error flag and skips the rest of the input operation
  • We can detect the failure condition using code like:
    if (cin.fail()) {
        // the stream failed
    }
    
  • Another way to test for cin failure is:
    cin >> guess;
    if (cin) {
        // the stream did not fail
    } else {
        // the stream failed
    }
    
  • Using cin by itself is the same as using cin.fail()
  • Yet another commonly used strategy is:
    if (cin >> guess) {
        // the stream did not fail
    } else {
        // the stream failed
    }
    
  • If cin >> guess fails to read a correct value then this expression returns the same thing as cin.fail()
  • To clear the failed state you need to both clear the flags and the input buffer
  • For instance:
    cin.clear();
    cin.ignore(1000, '\n');
    

Example Program with Input Validation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
using namespace std;


int main() {
    const int ANSWER = 7;

    int guess = 0;
    cout << "I'm thinking of a number between"
         << " 1 and 10.\nCan you guess it?\n\n"
         << "Enter your guess: ";
    cin >> guess;

    if (cin.fail()) {
        cout << "Error: you must enter numbers\n";
        return 1;
    }

    if (guess < 1) {
        cout << "Error: guess must be >= 1\n";
        return 1;
    }

    if (guess > 10) {
        cout << "Error: guess must be <= 10\n";
        return 1;
    }

    if (ANSWER == guess) {
        cout << "*** Correct! ***\n";
    } else {
        cout << "Sorry, that is not correct.\n";
    }
    return 0;
}

More Information on Some cin Functions

6.1.2: Processing a Sequence of Inputs

  • Recall our guessing game program
  • One version went something like this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;


int main() {
    const int ANSWER = 7;

    int guess = 0;

    string repeat = "y";
    while ("y" == repeat) {
        cout << "I'm thinking of a number between"
             << " 1 and 10.\nCan you guess it?\n\n"
             << "Enter your guess: ";
        cin >> guess;

        if (ANSWER == guess) {
            cout << "*** Correct! ***\n";
        } else {
            cout << "Sorry, that is not correct.\n";
            cout << "Try again: ";
        }
        cout << "\nDo you want to play again? (y/n) ";
        cin >> repeat;
    }
    cout << "Game over\n";

    return 0;
}

Terminating the Input

  • Whenever we read a sequence of input values, we need to have some way of terminating the input loop
  • We could use a separate variable and input statement as we have done before:
    string repeat = "y";
    while ("y" == repeat) {
        // ... statements to repeat
        cin >> repeat;
    }
    
  • However, when entering numbers (or other data) repeatedly, answering an extra question each time through the loop becomes irritating
  • One way to avoid asking an extra question is to use a sentinel value
  • A sentinel is someone that watches for something to happen, like a sentry
  • Similarly, a sentinel value is a special number (or other data) used to signal termination of a loop
  • To use a sentinel value, we must restrict the input in some way
  • Some commonly used sentinel values for numeric input are 0 or -1
  • However, if our application suggests another value, then we should use that value
  • For instance, in our guessing game application, a useful sentinel value is the guess value
  • The following update of our guessing game shows a loop with a sentinel value

Example Application Using a Sentinel Value for the Loop Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;


int main() {
    const int ANSWER = 7;

    int guess = 0;
    cout << "I'm thinking of a number between"
         << " 1 and 10.\nCan you guess it?\n\n"
         << "Enter your guess: ";

    while (guess != ANSWER) {
        cin >> guess;

        if (ANSWER == guess) {
            cout << "*** Correct! ***\n";
        } else {
            cout << "Sorry, that is not correct.\n";
            cout << "Try again: ";
        }
    }
    cout << "Game over\n";

    return 0;
}

6.1.3: do-while Statements

  • Sometimes we want to execute the body of a loop at least once and perform the loop test after the body was executed
  • For this we can use the do-while (or just do) loop
  • do {
       statements
    } while (test); //loop condition
    
  • Where:
    • statements: the statements to execute the first time and repeatedly while the test remains true
    • test: the test condition to evaluate
  • The loop test is placed after the body and executes at the end of the loop
  • The loop always executes at least once (minimum of at least one iteration)
  • One common use of a do-while loop is to validate user input
  • The following code shows an example where we force the user to enter a positive value

Example do-while Loop Used to Validate Input

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
using namespace std;

int main() {
    double input = 0.0; // initialize value
    do {
        cout << "Enter a positive number: ";
        cin >> input;
        if (input < 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input < 0.0); // test condition at end
    cout << "You entered: " << input << endl;

    return 0;
}

When to Use do-while Statements

  • We can use the do-while loop whenever we want to force a minimum of one iteration
  • Note that we can accomplish the same control flow with a while loop
  • However, in some cases we can save a statement by using a do-while loop

6.1.4: Using Boolean Variables

  • Another way to control loop termination is to use a Boolean variable
  • Boolean variables are named after George Boole (1815-1864), a pioneer in the study of logic
  • You specify a Boolean variable using the bool type, which can hold just one of two values: true or false
    bool truth = true;
    bool lies = false;
    
  • Question: How does George Boole order lunch? (see here)
  • Question: What type of tests does George Boole give? answer
  • Recall that we can test for users entering words when we want numbers using cin.fail()
  • The advantage of using boolean variable is that we can check multiple conditions as shown in the following example

Example Application Using a Boolean Variable for the Loop Test

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;

int main() {
    double input = 0.0;
    bool more = true;
    do {
        cout << "Enter a positive number: ";
        cin >> input;
        if (cin.fail()) {
            cout << "You must enter digits, not words\n";
            cin.clear();
            cin.ignore(INT_MAX, '\n');
        } else if (input < 0.0) {
            cout << "You must enter a positive number\n";
        } else {
            more = false;
        }
    } while (more); // test condition
    cout << "You entered: " << input << endl;

    return 0;
}

Simplified Boolean Test Conditions

  • Recall that test conditions in loops and if statements evaluate to either true or false
  • For this reason, most professional programmers consider the following test conditions amateurish:
    while (more == true)  // avoid
    while (more != false) // avoid
    
  • The reason is that == true and != false are not needed for correct operation
  • Instead, we can simplify either test condition to:
    while (more)
    
  • However, if using a relational operator is clearer for you then do so

6.1.5: Extracting Digits From a Number

  • One use for a sentinel-controlled loop is to generate a check digit
  • Check digits are often used in bar codes such as the ISBN (International Standard Book Number) and POSTNET postal codes
  • To generate the check digit we need to extract each digit from an integer
  • Then we sum all the single digits and apply a formula to generate the check digit
  • An easy way to extract the last digit of an integer number is to take the remainder after dividing by ten:
    int input = 12345;
    int digit = input % 10;
    cout << digit << endl;
    
  • If we divide the number by 10 and repeat the process, the divided number eventually reaches zero:
    int input = 12345;
    int digit = input % 10;
    cout << digit << endl;
    input = input / 10;
    digit = input % 10;
    cout << digit << endl;
    ...
    
  • Since this is a repetitive process, we can repeat it with a loop
  • Also, since input eventually reaches 0, we can use 0 as a sentinel value to control loop termination
  • We can see how in the following example

Example Application to Separate Integer Digits

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;

int main() {
    int input = 0;
    cout << "Enter a positive integer: ";
    cin >> input;

    cout << "Count\tDigit\tInput\n";
    int count = 1;
    while (input != 0) {
        int digit = input % 10;
        input = input / 10;
        cout << count << ":\t" << digit << "\t"
             << input << endl;
        count++;
    }

    return 0;
}

6.1.6: Summary

  • In this section we looked at using loops to process user input:
  • One way was to use a sentinel value to control loop termination
  • A sentinel value is a special number (or other data) used to signal termination of a loop
  • The advantage of using a sentinel value is we can avoid asking questions like, "Do you want to run again?
  • We looked at how to process a running total with a sentinel-controlled loop
  • We also looked at using a Boolean variable to control loop termination
  • The bool data type can store just one of two values: true or false
  • The advantage of a Boolean variable is that we can check multiple conditions to determine when to exit a loop
  • Another looping statement is the do-while loop, which tests the condition at the end of the loop body:
    do {
       statements
    } while (test); //loop condition
    
  • Testing at the end ensures a minimum of at least one iteration
  • In addition, we looked at an example of extracting digits from a number using a sentinel-controlled loop

Exercise 6.1

In this exercise we use a loop, the modulus operator, and integer division to generate check digits from user input. In addition, we validate user input to ensure our extraction works.

Specifications

  1. Copy the following program into a text editor, save it as sumdigits.cpp, and then compile and run the starter program to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    int main() {
        // Enter your code here
    
        return 0;
    }
    
  2. Add code to get user input into an integer variable named input. When you run the program after adding this code, the output should look like:
    Enter a positive integer: 12345
    

    Note that the underlined numbers above shows what the user enters. For more information see section 2.4.7: Input and Output.

  3. Add the following code after the user input statements:

    Extract and sum digits

    This loops extracts each digit using the modulus operator and integer division. For more information see section 6.1.5 Extracting Digits From a Number.

  4. Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
    Enter a positive integer: 12345
    The sum of the digits 5 4 3 2 1
    

    Notice that each digit is displayed one at a time separated by a space. For more information see section 6.1.5: Extracting Digits From a Number.

  5. During the loop, the sum of the digits was collected. Add a statement to print the sum to the console. When you run the program after adding this code, the output should look like:
    Enter a positive integer: 12345
    The sum of the digits 5 4 3 2 1 is 15
    

    Summing the digits uses a variable to accumulate each digit for each repetition of the loop. For more information see lesson: 5.1.5: Accumulating Values.

  6. We only want to sum positive integers in this example. Read section 6.1.3: do-while Statements and place your input statements in a do-while loop like the following after the first line of main():

    do-while loop example

    Make sure you leave alone the previous loop to extract each digit using a while loop.

  7. Compile and run your modified program and make sure your program runs like:
    Enter a positive number: -12345
    You must enter a positive number
    Enter a positive number: 12345
    The sum of the digits 5 4 3 2 1 is 15
    
  8. One problem that remains with our program is that a user may enter words rather than digits. To correct this we can test with cin.fail(). Read section 6.1.4: Using Boolean Variables and add a condition to check for the user entering words rather than digits using a Boolean variable to control a do-while loop like the following:

    do-while loop with boolean variable

    Notice the change in the loop condition as well as the changes to the if-else statements. The Boolean variable lets us test multiple conditions for exiting the loop.

  9. Compile and run your modified program and make sure your program runs like:
    Enter a positive number: one hundred twelve
    You must enter digits, not words
    Enter a positive number: -12345
    You must enter a positive number
    Enter a positive number: 12345
    The sum of the digits 5 4 3 2 1 is 15
    
  10. Submit your program source code to Blackboard as part of assignment 6.

Check Yourself

As time permits, be prepared to answer these questions. You can find more information by following the links after the question.

  1. What C++ statement do you use to validate input? (6.1.1)
  2. What is a test condition you can use to see if cin has failed? (6.1.1)
  3. What is a good test to validate that the user did not enter a string after the following statements execute: (6.1.1)
    double x;
    cout << "Enter a number: ";
    cin >> x;
    
  4. What two statements can you use to fix cin if it has failed due to bad input? (6.1.1)
  5. What is a sentinel value? (6.1.2)
  6. What is the advantage of using a sentinel value to terminate a loop? (6.1.2)
  7. What is the difference between a while and a do-while loop? (6.1.3)
  8. What is the advantage of using a Boolean variable to terminate a loop? (6.1.4)
  9. Why does number % 10 extract the last digit of a number? (6.1.5)

6.2: More About Strings and Characters

Learner Outcomes

At the end of the lesson the student will be able to:

  • Iterate through a string and extract each character
  • Convert characters to digits
  • Use string functions

6.2.1: Reviewing Strings and Characters

  • Remember that a string is a series of characters enclosed in double quotes such as:
    "Hello"  "b"  "3.14159"  "$3.95"  "My name is Ed"
  • We can store text in a variable of type string, like:
    string firstName;             // declaration
    firstName = "Edward";         // assignment
    string lastName = "Parrish";  // declaration + assignment
    cout << firstName << " " << lastName << endl;
    
  • On the other hand, a character is a single letter, number or special symbol
  • We enclose characters in a single quote, rather than a double quote, like:
    'a'   'b'   'Z'   '3'   'q'   '$'   '*'
  • Also, you can store a a single character using a variable of type char, such as:
    char letterA = 'A';
    char letterB = 'B';
    
  • Each character is stored as a number, using its ASCII code
  • By declaring a char variable or using single quotes, C++ knows to treat the number as a character
  • Thus, when you print a character, you see a letter rather than a number:
    char letter = 'A';
    cout << letter << 'B' << endl;
    
  • As you can see, a string is made up of characters and characters are numerical codes
  • We can use this information to work with characters and strings

6.2.2: Indexing a String

  • Strings are stored in a character sequence starting at 0 (zero)

  • You can access any individual character of a string variable using [ ]
  • The general syntax is:
    stringVariable[index];
    
  • Where:
    • stringVariable: the name of your string variable
    • index: the nuber of the character position
  • For example:
    string str = "abcdef";
    char firstLetter = str[0];
    cout << firstLetter << str[1] << endl;
    
  • The above code displays:
    ab

6.2.3: String Functions

  • Strings are a special type of variable called objects, just like a Turtle
  • An object is a data type that can have functions associated with it
  • These functions are called member functions and are called using dot notation
  • The syntax for calling a member function of a string object is:
    stringName.functionName(arguments)
    
  • Where:
    • stringName: the name of the string variable
    • functionName: the name of the member function
    • arguments: the input values, if any
  • Once you create a string variable, you can use its member functions

Some Commonly-Used Functions

  • length(): Returns the number of characters in a string
    string str = "Hello";
    cout << "The number of characters is " << str.length()
         << ".\n";
    
  • substr(i, n): Returns a substring of length n starting at index i
    string greeting = "Hello, World!\n";
    string sub = greeting.substr(0, 4);
    cout << sub << endl;
    
  • The position numbers in a string start at 0. The last character is always one less than the length of the string
  • H e l l o , W o r l d ! \n
    0 1 2 3 4 5 6 7 8 9 10 11 12 13
  • string w = greeting.substr(7, 5);
    H e l l o , W o r l d ! \n
    0 1 2 3 4 5 6 7 8 9 10 11 12 13

Using String Functions

  • Consider the problem of extracting the initials from a person's name
  • What would be an algorithm for solving this problem?
  • To implement this algorithm, we can use the string function substr()
  • The following program implements an algorithm for extracting the intials from a person's name
  • What other technique could you use to extract the initials?

Program to Create Initials

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
using namespace std;

int main() {
    string first;
    string middle;
    string last;
    cout << "Enter your full name (first middle last): ";
    cin >> first >> middle >> last;
    string initials = first.substr(0, 1)
        + middle.substr(0, 1) + last.substr(0, 1);
    cout << "Your initials are " << initials << "\n";

   return 0;
}

6.2.4: Iterating Strings

  • Recall that member function length() returns the number of characters in a string variable:
    string s = "abcdef";
    unsigned n = s.length();
    
  • Since a string's length is always 0 or a positive number, the length() function returns an unsigned int type
  • After we know the length, it is easy to iterate through the individual characters of a string using a counting loop:
    string msg;
    cout << "Enter a message: ";
    getline(cin, msg);
    for (unsigned i = 0; i < msg.length(); i++) {
        cout << "Char[" << i << "]: " << msg[i] << endl;
    }
    

6.2.5: Converting Characters to Digits

  • Recall that a character is stored by the computer as a number using its ASCII code
  • In the ASCII table, notice the ASCII codes for the digit characters:
    Decimalchar
    48'0'
    49'1'
    50'2'
    51'3'
    52'4'
    53'5'
    54'6'
    55'7'
    56'8'
    57'9'
  • Since each character is a numerical code, we can convert a char to a number
  • For example:
    char digit = '9';
    int num = digit - 48;
    cout << num << endl;
    num = num * 4 + 6;
    cout << num << endl;
    
  • Since a string is a series of characters, and each character is number, we can convert a string to anumber as well
  • For example:
    string str = "123";
    char ch0 = str[0];
    char ch1 = str[1];
    char ch2 = str[2];
    int digit1 = ch0 - 48;
    int digit2 = ch1 - 48;
    int digit3 = ch2 - 48;
    int num = digit1 * 100 + digit2 * 10 + digit3;
    cout << num << endl;
    
  • Since converting strings to number is repetitious, we can use a loop
  • We will explore converting strings to numbers in the next exercise

6.2.6: Summary

  • A string is a series of characters enclosed in double quotes
  • We can store text in a variable of type string, like:
    string s1 = "Hello Mom!";
  • A character is a single letter, number or special symbol
  • We can store a a single character using a variable of type char, such as:
    char letterA = 'A';
    char letterB = 'B';
    
  • Each character is stored as a number, using its ASCII code
  • Strings are stored in a character sequence starting at 0 (zero)

  • You can access individual characters of a string using []
  • Strings are a special type of variable called objects, just like a Turtle
  • Because a string is an object, it has member functions
  • We looked at the member functions:
    • length(): Returns the number of characters in a string
      string s = "Hello";
      cout << s.length() << endl;
      
    • substr(i, n): Returns a substring of length n starting at index i
      string greeting = "Hello, World!\n";
      string sub = greeting.substr(0, 4);
      cout << sub << endl;
      
  • We can iterate through a string using a loop and the length() member function:
    string s = "abcdef";
    for (unsigned i = 0; i < s.length(); i++) {
        cout << "Char[" << i << "]: " << s.at(i) << endl;
    }
    
  • Also, we looked at how to convert a char to a number
  • Since each character has a numerical code, we can convert a char to a number
  • For example:
    char digit = '9';
    int num = digit - 48;
    cout << num << endl;
    
  • Since a string is a series of characters, and each character is number, we can convert a string to anumber as well
  • We looked at an example of converting strings to numbers as well

Exercise 6.2

In this exercise we convert strings to character and characters to numbers.

Specifications

  1. Copy the following program into a text editor, save it as stringdigits.cpp, and then compile and run the starter program to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    int main() {
        // Enter your code here
    
        return 0;
    }
    
  2. Add code to get user input into an string variable named str. When you run the program after adding this code, the output should look like:
    Enter an integer number: 12345
    

    Note that the underlined numbers above shows what the user enters. Also, we do NOT want to allow spaces in user input. For more information see section 3.2.2: String Variables and Simple I/O.

  3. After the input statement, add another line of code that displays the length of the string variable str. When you run the program after adding this code, the output should look like:
    Enter an integer number: 12345
    The number of characters is 5.
    

    Note that the number 5 in the above example may change depending on the number entered. For more information see section 6.2.3: String Functions.

  4. After the other statements, add the following code to convert the first character of the string to a number:
    char ch = str[0];
    int digit = ch - 48;
    cout << "Digit: " << digit << endl;
    
  5. Enclose the above code that converts a character to a string inside a loop that iterates through each character, as explained in section 6.2.4: Iterating Strings. IMPORTANT: change the number 0 in square brackets to the index variable of the counting loop. When finished, your code should look like:

    Looping through a string

  6. In this step, we add the code to display the sum of the digits as follows:
    1. Before the loop, declare a variable named sum and initialize the variable to 0.
      int sum = 0;
    2. At the end of the loop, before the closing curly brace (}), add the statement:
      sum = sum + digit;
    3. After the closing curly brace of the loop, add a statement to display the sum of the digits.
  7. Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
    Enter an integer number: 12345
    The number of characters is 5.
    Digit: 1
    Digit: 2
    Digit: 3
    Digit: 4
    Digit: 5
    The sum of the digits is: 15
    

    Debug any problems you see and ask your neighbor or the instructor for help as needed.

  8. In this step, we add the code to convert the digits into a single number as follows:
    1. At the top of the file, include the cmath library:
      #include <cmath>
    2. Before the loop, declare a variable named num and initialize the variable to 0:
      int num = 0;
    3. At the end of the loop, before the closing curly brace (}), add the statements:
      int exp = str.length() - (int) i - 1;
      num = num + (int) (digit * pow(10.0, exp));
      
    4. After the closing curly brace of the loop, add a statement to display the sum of the digits.
  9. Compile and run your modified program to make sure you made the changes correctly. When you run the program, the output should look like:
    Enter an integer number: 12345
    The number of characters is 5.
    Digit: 1
    Digit: 2
    Digit: 3
    Digit: 4
    Digit: 5
    The sum of the digits is: 15
    The number is: 12345
    

    Debug any problems you see and ask your neighbor or the instructor for help as needed.

  10. Submit your program source code to Blackboard as part of assignment 6.

Program that Processes Strings with Loops

Code to process strings in a loop

Check Yourself

As time permits, be prepared to answer these questions. You can find more information by following the links after the question.

  1. String are enclosed in double quotes. What type of quote marks enclose characters? (6.2.1)
  2. The characters of a string variable can be accessed using what brackets? (6.2.2)
  3. The leftmost character of a string is accessed using which index number? (6.2.2)
  4. For a string variable named str, what code do you write to determine the number of characters in the string? (6.2.3)
  5. What function do you use to find a substring in a string variable? (6.2.3)
  6. To print the following string vertically down the page, what code do you write? (6.2.4)
    string str = "Hi mom!";
  7. To convert the following char variable to a number, what code do you write? (6.2.5)
    char ch = '7';
  8. What is the value of the expression: 'd' - 'a' + 'A'? (6.2.5)
  9. To convert the following string variable to a number, what code do you write? (6.2.6)
    string str = "7";

6.3: More About Functions

Learner Outcomes

At the end of the lesson the student will be able to:

  • Return a value from a function
  • Document functions
  • Trace the control-flow of function calls

6.3.1: Variable Scope and Global Constants

  • Recall our drawSquare() function with multiple parameters (shown below)
  • What would happen without the parameters for turtle and size?

Example Program with Multiple Function Parameters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "turtlelib.cpp"

void drawSquare(Turtle& turtle, double size) {
    const double ANGLE = 90;

    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
}

int ccc_win_main() {
    Turtle myrtle;
    myrtle.right(90);

    drawSquare(myrtle, 3);
    myrtle.moveTo(-6, -6);
    drawSquare(myrtle, 5);

    return 0;
}

Variable Scope

  • Variables and parameters declared in a function can only be used within that function
  • This is known as a variables scope
  • This lets us use variables with the same name in different functions
  • For instance, we could define two functions using the same variables and parameters:
    void drawSquare(Turtle turtle, double size) {
        const double ANGLE = 90;
        // statements to draw a square
    }
    
    void drawTriangle(Turtle turtle, double size) {
        const double ANGLE = 120;
        // statements to draw a triangle
    }
    
  • Variables defined inside a function are known as local variables
  • When the function finishes executing, local variables disappear
  • Trying to use a local variable outside a function causes a compile error

Global Variables and Constants

  • C++ lets you define variables and constants with global scope
  • Global variables and constants are declared outside of any function and can be accessed in any function
  • Because they have the same value everywhere, global constants are considered good programming practice
  • Unlike global constants, global variables are considered poor programming practice
  • Global variables make programs more difficult to understand and maintain
  • Do not use global variables in your programs for this course
  • However, do use global constants for read-only values used in many functions
  • The following example shows a global constant named FULL_CIRCUIT

Program Using Both Global and Local Constants

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "turtlelib.cpp"

const double DEGREES_IN_CIRCLE = 360;

void drawTriangle(Turtle& turtle, double size) {
    const int SIDES = 3;
    double angle = DEGREES_IN_CIRCLE / SIDES;

    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
}

void drawSquare(Turtle& turtle, double size) {
    const int SIDES = 4;
    double angle = DEGREES_IN_CIRCLE / SIDES;

    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
}

int ccc_win_main() {
    Turtle myrtle;
    myrtle.right(90);
    drawTriangle(myrtle, 3);
    myrtle.moveTo(-1, -1);
    drawSquare(myrtle, 5);
    myrtle.moveTo(-2, -2);
    drawTriangle(myrtle, 7);
    myrtle.moveTo(-3, -3);
    drawSquare(myrtle, 9);

    return 0;
}

About Global Variables

  • Global variables are variables that are defined outside functions
  • They are declared just like a global constant but without the const keyword
  • Unlike global constants, global variables are considered poor programming practice
  • Global variables make programs more difficult to understand and maintain
  • Do not use them in your programs for this course

6.3.2: Returning a Value

  • Recall that functions can return values
  • Every function is declared with a return type so they can return values
    returnType functionName(parameter1, ..., parametern) {
        statements
    }
    
  • Until now we have used void for all our function return types:
    void drawSquare(Turtle turtle, double size) {
        // Statements to draw a square
    }
    
  • We use the keyword void when we want to return nothing
  • However, we can declare a function that gives back a specific value to the caller as shown below

Program with a Function that Returns a Value

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;

double square(double number2) {
    double result = number2 * number2;
    return result;
}

int main() {
    double number;
    cout << "Enter number to square: ";
    cin >> number;

    double result = square(number);
    cout << result << endl;

    return 0;
}

Return Statement

  • The way we return a value is to use a return statement
    return result;
  • If we declare that a function will return a value, we must return a value of the correct type
  • The compiler will check and make sure we do not try to return the wrong data type
  • Whenever the return statement is reached in the program flow, the function exits immediately
  • Note that we can use return in a void function as well:
    return;
  • When we use return from a void function, we do not specify a value in the return statement
  • If we do not code a return statement for a void function, the function automatically returns when the control reaches the end

Exercise 6.3

In this exercise we define a function that returns a value. In addition, we trace the flow of control in our program.

Specifications

  1. Copy the following program into a text editor, save it as triangle2.cpp, and then compile and run the program to make sure you copied it correctly.
    #include "turtlelib.cpp"
    
    void drawTriangle(Turtle& boggy, double size) {
        double angle = 120;
    
        boggy.forward(size);
        boggy.left(angle);
        boggy.forward(size);
        boggy.left(angle);
        boggy.forward(size);
        boggy.left(angle);
    }
    
    int ccc_win_main() {
        Turtle boggy;
        boggy.right(90);
        drawTriangle(boggy, 5);
        boggy.moveTo(-4, 0);
        drawTriangle(boggy, 3);
    
        return 0;
    }
    
  2. Add a global constant right after the #include "turtlelib.cpp":
    const double DEGREES_IN_CIRCLE = 360;
    

    The global constant is accessible to any function in your program. For more information see section: 6.3.1: Variable Scope and Global Constants.

  3. Add the following function definition before all the other functions but after the global constant:
    double calcAngle(int sides) {
        double angle = DEGREES_IN_CIRCLE / sides;
        return angle;
    }
    

    This function calculates the angle of the adjacent sides of a regular polygon. Once the calculation is complete, the function returns the value using a return statement. For more information see section: 6.3.2: Returning a Value.

  4. The function is ignored until called. Change the first line of the drawTriangle() function from double angle = 120; to:
    double angle = calcAngle(3);
    

    Notice that we are calling a function from another function. For more information see section 6.3.3: Functions Calling Functions.

  5. Now we explore the use of function prototypes. Move both the calcAngle() and drawTriangle() functions to a line after the closing curly brace of the main() function. Make sure the calcAngle() function still precedes the drawTriangle() function. Try to compile the code after you move the functions and you should see a compiler error message with the following:
    traingle2.cpp:8: error: `drawTriangle' undeclared
    

    The error is because the C++ compiler requires a declaration of functions before they are called. For more information see section 6.3.4: Function Prototypes Functions.

  6. To correct the error, place the following function prototypes right after the #include "turtlelib.cpp" and before main():
    double calcAngle(int sides);
    
    void drawTriangle(Turtle& boggy, double size);
    

    Notice the function prototypes are declaring the function name and the parameter types. For more information see section 6.3.4: Function Prototypes Functions. At this time, your program should look like the following:

    Revised program to draw a triangle

  7. Review section 6.3.5: Programming Style Requirements for Functions and add block comments. In addition, make sure your functions meet all the other programming style requirements including indentation.
  8. Run Doxygen, which is available in the Tools menu of TextPad on the computers in our classroom. After running Doxygen, look in the html directory where you saved your source code. Double-click on the file named index.html and examine in a Web browser the documentation that Doxygen generated from your source code. For more information on running Doxygen, see section 6.3.5: Programming Style Requirements for Functions.
  9. Submit your final program source code to Blackboard as part of assignment 6. Notice that you do not need to submit any files from running Doxygen.
  10. In addition to completing the programming code, prepare a second file named trace.txt.
  11. In the trace.txt file, list the line numbers of each statement for the version of the program shown above in the order the lines are executed. For example, the following are the first few line numbers of the program flow (assuming main() starts on line 9):
    9, 10, 11, 12, 24, 25, ...
    
  12. Do not bother to list blank lines or lines containing only the closing curly brace (}) of a function definition. For more information on tracing, see section 6.3.4: Tracing Code.

  13. Also submit the trace.txt file to Blackboard as part of assignment 6.

Check Yourself

As time permits, be prepared to answer these questions. You can find more information by following the links after the question.

  1. What is meant by the term scope? (6.3.1)
  2. What is a block of code? (6.3.1)
  3. What is a global variable? (6.3.1)
  4. Why should you avoid using global variables in your programs? (6.3.1)
  5. What is a global constant? (6.3.1)
  6. Why might you want to use a global constant in your programs? (6.3.1)
  7. What makes a global constant acceptable whereas a global variable should be avoided? (6.3.1)
  8. What statement is used to return values from functions? (6.3.2)
  9. When do you use the void return type in a function definition? (6.3.2)
  10. Are you required to have a return statement in a void function definition? (6.3.2)
  11. What effect would removing the return statement from the following function have on compiling or executing the program? (6.3.2)
  12. void showResults(double fDegrees, double cDegrees) {
        cout << fDegrees
             << " degrees Fahrenheit is equivalent to "
             << cDegrees << " degrees Celsius." << endl;
        return;
    }
    
  13. Assuming that showResults() is a void function, what is wrong with: (6.3.2)
  14. cout << showResults(32.5, 0.3); // not allowed
    
  15. How many times can functions call other functions? (6.3.3)
  16. What are the four pieces of a block comment for functions? (6.3.5)
  17. What is meant by the term, "tracing code"? (6.3.6)

6.3.3: Functions Calling Functions

  • Functions may call other functions
  • Within the body of one function, we can call another function call
  • Functions can call other functions as often as needed
  • We are already doing this when main() calls a function
  • The following program writes program status to the console as the program runs
  • Writing values like this is known as data logging
  • Using log statements is a good debugging technique

Example of Functions Calling Functions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
using namespace std;

void log(string funName, double value) {
    cout << "In " << funName << " the value is "
         << value << endl;
}

double square(double number) {
    log("square() before", number);
    double result = number * number;
    log("square() after", result);
    return result;
}

int main() {
    double number = 5;
    log("main() before", number);
    double result = square(5);
    log("main() after", result);

    return 0;
}

6.3.4: Function Prototypes

  • C++ allows you to declare functions without defining them
  • Function declarations (prototypes) have the function heading without the function body
  • The general syntax for declaring a function is:
    returnType functionName(parameter1, ..., parametern);
    
  • Where:
    • returnType: the type of the value returned
    • functionName: the name you make up for the function
    • parameterx: the input values, if any
  • As an example, we can declare our function to draw a square like this:
    void drawSquare(Turtle turtle, double size);
  • By declaring a function, the compiler can resolve a function call made inside main()
  • Thus, we can reorganize our programs to place function definitions after main()
  • Note that if you use function prototypes, you place the block comments before the prototypes and not the definitions
  • You can see this new function organization in the following example

Example Program with a Function Prototype

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include "turtlelib.cpp"

void drawSquare(Turtle& turtle, double size);

int ccc_win_main() {
    Turtle myrtle;
    myrtle.right(90);

    drawSquare(myrtle, 3);
    myrtle.moveTo(-6, -6);
    drawSquare(myrtle, 5);

    return 0;
}

void drawSquare(Turtle& turtle, double size) {
    const double ANGLE = 90;

    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
}

6.3.5: Programming Style Requirements for Functions

  • Let us look more closely at the layout of the function shown below
  • Note the placement of the curly braces
  • There are two common styles of curly brace placement for functions:
    1. Place the opening brace on the same line as the function heading:
      void myFunction() {
          // statements of the function
      }
      
    2. Place the opening brace under and lined up with the first letter of the return type:
      void myFunction()
      {
          // statements of the function
      }
      
  • You can use either style as long as you are consistent
  • Also notice the indentation of the statements inside the function
  • As before, you always indent 3-4 more spaces after an opening curly brace
  • After the closing curly brace, you no longer indent the extra 3-4 spaces
  • Indenting makes it easier to see the block of code

Example Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "turtlelib.cpp"

void drawSquare(Turtle& turtle, double size) {
    const double ANGLE = 90;

    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
    turtle.forward(size);
    turtle.left(ANGLE);
}

int ccc_win_main() {
    Turtle myrtle;
    myrtle.right(90);

    drawSquare(myrtle, 3);
    myrtle.moveTo(-6, -6);
    drawSquare(myrtle, 5);

    return 0;
}

Naming Functions

  • When making up a name for a function, use verbs since functions perform an action
  • There are two common naming styles you may use:
    1. Start with a lower-case letter and use uppercase letters as separators. Do not use underbars ('_').
    2. int myFunction()
    3. Use all lower case letters and use underbars ('_') as separators.
    4. int my_function()

Commenting Functions

  • For your homework, every function must have a block comment before the function name
  • Comments are for human readers, not compilers
  • There is no universal standard for comment layout, but we use a style commonly used with many programming languages:
    1. Block comments start with /** and ends with */
    2. The first line explains the idea of the function, not the implementation
    3. An @param entry explains each parameter
    4. An @return entry describes the return value
  • The following example has a fully commented function
  • Notice that the example does NOT include the program file block comment required for homework

Example Program with Fully Commented Function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include "turtlelib.cpp"

/**
    Draws a square with sides of length size using the
    Turtle.

    @param turtle The turtle to use for drawing
    @param size The length of each side
*/
void drawSquare(Turtle& turtle, double size) {
    const double angle = 90;

    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
}

int ccc_win_main() {
    Turtle myrtle;
    myrtle.right(90);

    drawSquare(myrtle, 3);
    myrtle.moveTo(-6, -6);
    drawSquare(myrtle, 5);

    return 0;
}

Using Doxygen

  • The purpose of the comment layout is to produce hyperlinked web pages describing your program
  • The program we use to produce the web pages is called Doxygen
  • We can run Dyoxygen from TextPad in the classroom and CTC
  • You can install Doxygen at home by following my instructions
  • Running Doxygen produces a folder named "html"
  • Inside the folder, we open the index.html file in a Web browser

Further Information

6.3.6: Tracing Code

  • One critical programming skill is tracing the code, often statement by statement
  • In a sense, you have to "be the computer"

    Be the computer

  • To trace the code, you follow the flow of execution
  • Every program starts with the first line of the main() function and continues sequentially statement by statement from there
  • A function call transfers the flow to the first statement of the called function
  • When the function returns, the flow transfers back to the point from which the call was made
  • Thus, every time the flow of control reaches a function call, the program:
    1. Temporarily stops executing in the current function
    2. Jumps to the called function and executes the statements of that function
    3. Returns to the point in the code from which it jumped
  • Let us trace the flow in the following code by line number:

Example Program for Tracing the Flow

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "turtlelib.cpp"

const double DEGREES_IN_CIRCLE = 360;

void drawTriangle(Turtle& turtle, double size) {
    const int SIDES = 3;
    double angle = DEGREES_IN_CIRCLE / SIDES;

    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
}

void drawSquare(Turtle& turtle, double size) {
    const int SIDES = 4;
    double angle = DEGREES_IN_CIRCLE / SIDES;

    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
    turtle.forward(size);
    turtle.left(angle);
}

int ccc_win_main() {
    Turtle myrtle;
    myrtle.right(90);
    drawTriangle(myrtle, 3);
    myrtle.moveTo(-1, -1);
    drawSquare(myrtle, 5);
    myrtle.moveTo(-2, -2);
    drawTriangle(myrtle, 7);
    myrtle.moveTo(-3, -3);
    drawSquare(myrtle, 9);

    return 0;
}

6.3.7: Summary

  • Scope is the term used to define where you can access a variable
  • A variable inside a pair of curly braces is local to that block of code
  • Blocks begin at an opening brace ({) and end at a closing brace (})
  • This includes functions and other statements that use curly braces
  • Thus, variables declared in one function are not available in any other function
  • When the function finishes executing, local variables disappear
  • Trying to use a local variable outside a function cause a compile error
  • Global variables are variables declared outside of any function
    • Do NOT use global variables in your programs for this course
  • Global constants, on the other hand, are the preferred way to declare constants
  • Recall that we define a function using the following syntax:
    returnType functionName(parameter1, ..., parametern) {
        statements
    }
    
  • If the function does not return a value, we use the return type: void
  • Otherwise, we specify the type of data we want to return
  • To return a value, we use a return statement like:
    return 39;
  • Functions have style requirements you must follow
  • For instance, you must have a block comment before the name

Wrap Up

    Reminders

    Due Next: A5-Five Easy Functions (3/19/09)
    A6-Postal Bar Codes (3/26/09)

  • When class is over, please shut down your computer
  • You may complete unfinished exercises at the end of the class or at any time before the next class.
Home | Blackboard | Announcements | Day Schedule | Eve Schedule
Course info | Help | FAQ's | HowTo's | Links
Last Updated: May 05 2009 @21:10:06