6: Getting Functional

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

  1. Can you suggest a different algorithm than shown in exercise P4.6?

6.1: 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.1.1: Strings Versus 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 Table
  • 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

Check Yourself

  1. True or false: "A" and 'A' are the same.
  2. The following code is wrong because ________.
    cout << "3.14159" * 2;
    
    1. you cannot double PI
    2. "3.14159" is not exact enough for PI
    3. you cannot multiply a string
    4. "3.14159" is not a string
  3. True or false: strings are a sequence of characters.

6.1.2: Indexing a String

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

    String character positions

  • We 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 number of the character position
  • For example:
    string str = "abcdef";
    char firstLetter = str[0];
    cout << firstLetter << str[1] << endl;
    
  • The above code displays:
    ab

Check Yourself

For the following string declaration, answer the questions below:

string str = "C++ Rules!";
  1. The value of str[0] is: ________
  2. The value of str[2] is: ________
  3. The value of str[4] is: ________
  4. The value of str[str.length() - 1] is: ________

6.1.3: 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:
    cout << "Enter a message: ";
    string msg;
    cin >> msg;
    for (unsigned i = 0; i < msg.length(); i++) {
        cout << "Char[" << i << "]: " << msg[i] << endl;
    }
    

Using unsigned

  • Note the use of unsigned i in the for loop
  • Recall from lesson 4.1.7 that unsigned ranges from 0 to 4294967295 rather than -2147483647 to 2147483647 for int
  • The length() function returns an unsigned number because the length of a string is never less than zero
  • If you compare a signed number with an unsigned number, the compiler may issue a warning:

    warning: comparison between signed and unsigned integer expressions

  • By using unsigned as the counting variable type in the for loop you avoid the warning

Check Yourself

  1. True or false: the length() function of a string returns an unsigned integer.
  2. For the following code, the output the second time through the loop is ________
    string msg = "aeiou";
    for (unsigned i = 0; i < msg.length(); i++) {
        cout << "Char[" << i << "]: " << msg[i] << endl;
    }
  3. True or false: the compiler may give a warning if you compare an unisgned int with a signed int.

6.1.4: 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 the algorithm for converting a string to a number is repetitious, we can use a loop
  • We will explore converting strings to numbers in the next exercise

Check Yourself

  1. The ASCII value for the character '0' is ________.
  2. True or false: The ASCII value for the character '5' is 53.
  3. 53 - 5 = ________.

Exercise 6.1

In this exercise we convert strings to characters 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.1.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.1.3: 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, like:
      cout << "The sum of the digits is: "
           << sum << endl;
      
  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 entire number :
      cout << "The number is: " << num << endl;
      
  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

As time permits, read the following sections and be prepared to answer the Check Yourself questions in the section: 6.1.7: Summary.

6.1.5: String Input With Spaces

  • We have been using the >> operator to enter data into a string variable:
    string something;
    cout << "Enter something: ";
    cin >> something;
    cout << "You entered: " << something << endl;
    
  • However, there are some complications
  • >> skips whitespace and stops on encountering more whitespace
  • Thus, we only get a single word for each input variable
  • If a user types in "Hello Mom!", we would only read "Hello" and not " Mom!"
  • This is because cin >> s1 works as follows:
    1. Skips whitespace
    2. Reads non-whitespace characters into the variable
    3. Stops reading when whitespace is found

Input Using getline()

  • To read an entire line we use function getline()
  • Syntax:
    getline(cin, stringVariable);
    
  • Where:
    • stringVariable: the name of the string variable
  • For example:
    string line;
    cout << "Enter a line of input:\n";
    getline(cin, line);
    cout << line << "END OF OUTPUT\n";
    
  • Note that getline() stops reading when it encounters a '\n'

The Problem with Newlines

  • When you press the Enter key, a newline character ('\n') is inserted as part of the input
  • The newline character can cause problems when you mix cin >> with getline()
  • Recall that cin >> s1:
    1. Skips whitespace
    2. Reads non-whitespace characters into the variable
    3. Stops reading when whitespace is found
  • Since whitespace includes newline characters, using cin >> will leave a newline character in the input stream
  • However, getline() just stops reading when it first finds a newline character
  • This can lead to mysterious results in code like the following:
    cout << "Enter your age: ";
    int age;
    cin >> age;
    cout << "Enter your full name: ";
    string name;
    getline(cin, name);
    cout << "Your age: " << age << endl
         << "Your full name: " << name << endl;
    
  • To get around this problem you can use cin >> ws just before getline()
    cin >> ws; // clear whitespace from buffer
    
  • You can see how to use this fix in the following example

Example Using cin >> ws

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

int main() {
    cout << "Enter your age: ";
    int age;
    cin >> age;
    cout << "Enter your full name: ";
    string name;
    cin >> ws; // clear whitespace from buffer
    getline(cin, name);
    cout << "Your age: " << age << endl
         << "Your full name: " << name << endl;
}

Check Yourself

  1. True or false: Using the >> operator with string variables only reads one word at a time.
  2. To read strings containing multiple words use the ________ function.
  3. True or false: before you switch from using the >> operator to using getline(), you must clear the next newline character from the input buffer.
  4. To clear whitespace from the input buffer use: ________.

6.1.6: Processing Text Input

  • Sometimes we need to read input as words and sometimes as lines
  • To input a sequence of words, use the loop:
    string word;
    while (cin >> word) {
       // process word
       cout << word << endl;
    }
    
  • cin >> word is the same test as cin.good() (see lesson 5.3.6)
  • To process input one line at a time, use the getline() function
    string line;
    while (getline(cin, line)) {
       // process line
       cout << line << endl;
    }
    
  • getline(cin, line) returns true as long as there is input remaining
  • The following example processes text input by counting words
  • When reading input in the while test, you need to close the stream using:
    • Ctrl + Z in Windows
    • Ctrl + D in UNIX or Max OS X
  • Closing the stream acts as a sentinel value for the loop
  • When the stream fails the loop exits

Example Program that Reverses a Sentence

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

using namespace std;

int main() {
    cout << "Enter a phrase followed by the Enter"
         << " key and Ctrl-Z/D.\n";
    string reversed;
    string word;
    while (cin >> word) {
        reversed = word + " " + reversed;
    }
    cout << reversed << endl;

    return 0;
}

Redirection of Input and Output

  • We could use the above program by typing words at the command line
  • However, that quickly gets tedious
  • A better way is to use redirection of input
  • The command line interfaces of most operating systems have a way to link a file to the input of a program
  • The content of the file gets fed into the program as if all the characters had been typed by a user
  • For example, after compiling the above program we type something like the following at the command line:
    ./words < input.txt
    
  • Where input.txt is the text file on which we want to count words
  • You can redirect program output to a file as well using something like:
    ./words > output.txt
    
  • You can combine input and output redirection in one command:
    ./words < input.txt > output.txt
    

Check Yourself

  1. True or false: the following code reads input one word at a time.
    string str;
    while (cin >> str) {
       cout << str << endl;
    }
    
  2. True or false: the following code reads input one line at a time.
    string str;
    while (getline(cin, str)) {
       cout << str << endl;
    }
    
  3. To close the cin input stream use the Ctrl key plus the ________ key.
  4. True or false: most operating systems let you redirect input and output at the command line.

6.1.7: 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)

    String character position

  • 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 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
  • To read an entire line, you need to use the getline() function:
    getline(cin, line);
  • Sometimes cin >> can leave a '\n' character in the input stream
  • To get around this problem you can use cin >> ws before getline()
    cin >> ws; // clear whitespace from buffer
    

Check Yourself

Answer these questions to check your understanding. 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.1.1)
  2. The characters of a string variable can be accessed using what brackets? (6.1.2)
  3. The leftmost character of a string is accessed using which index number? (6.1.2)
  4. To print the following string vertically down the page, what code do you write? (6.1.3)
    string str = "Hi mom!";
  5. To convert the following char variable to a number, what code do you write? (6.1.4)
    char ch = '7';
  6. What is the value of the expression: 'd' - 'a' + 'A'? (6.1.4)
  7. To convert the following string variable to a number, what code do you write? (6.1.4)
    string str = "7";
  8. How many words can you enter with the following code? (6.1.5)
    string something;
    cout << "Enter something: ";
    cin >> something;
    cout << "You entered: " << something << endl;
    
  9. How can you change the previous code to read a string that includes spaces? (6.1.5)
  10. What code can you use to clear newlines and other whitespace from the input stream? (6.1.5)

6.2: Predefined Functions

Objectives

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

  • Create code that calls predefined functions
  • Describe the flow of control of a function call
  • Write code that generates random numbers

6.2.1: About Functions

Function -- a subprogram (method, procedure or subroutine) that executes a block of code when called.

  • Most popular programs are large, containing thousands to millions of lines of code
  • When programs are this large, the best way to develop and maintain them is to construct them from smaller pieces or modules
  • In C++, these smaller pieces are called functions
  • Later on we will look at another way to create larger modules called Classes
  • You may have noticed that we have been using functions already
  • For instance, main() is a function that we use in every program
    1
    2
    3
    4
    5
    6
    7
    
    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Hello, World!\n";
        return 0;
    }
    
  • Function are often collected into libraries so they can be reused by many different programs
  • C++ comes with many common libraries such as <cmath> which contains functions like sqrt()
  • We have used many of these library functions and will use more as the course progresses
  • Functions such as these are known as predefined functions
  • A predefined functions is simply a function that someone else wrote
  • Our use of predefined functions shows one of the benefits of functions: reusable code
  • Later on we will learn to define our own functions so that we can create reusable code as well
  • For now, we are going to focus on how to use functions

Check Yourself

  1. ________ are a named block of code that executes when called.
  2. Many predefined ________ are available in program libraries.
  3. When a function was written by someone else they are known as ________ functions.

6.2.2: Calling a Function

  • When a function is defined or included in a program, C++ ignores the statements at first
  • In order to run the statements, you must call the function
  • Function call: an instruction that passes control to a function; after completing the function, control returns to the next instruction in the calling function.
  • Calling a function is like a boss asking a worker to do something
  • The "boss" (calling function) asks the "worker" (called function) to complete a task

Flow of Control for a Function Call

  • To understand how a function works, you need to trace its flow of control
  • The programs we write in this course have a single flow of control
  • All the statements in our programs execute in sequence, which can be modified by conditional statements or loops
  • A function call is another way to change the flow of control
  • When we call the function, the caller function stops and waits for the called function to finish
  • You can see this flow in the following diagram:

    Function call flow of control

Arguments and Returned Values

  • When we call a function we can send the function data called arguments
  • For example, to calculate the square root of a number, we call the sqrt() function with a particular value:
    sqrt(9.0);
  • In this case the argument is the numerical value 9.0
  • When the called function finishes executing, it may return a value
  • In this case our function returns the value 3.0

Example Program with a Function Call

1
2
3
4
5
6
7
8
9
10
#include <cmath>
#include <iostream>
using namespace std;

int main() {
    double result = 1 + sqrt(9.0);
    cout << result << endl;

    return 0;
}

Check Yourself

  1. True or false: functions are executed as soon as the compiler reaches the function code.
  2. To execute the code inside of a function we must write a function ________.
  3. True or false: standard function calls always include parenthesis.
  4. After a function ends, control returns to the ________ code.
  5. A(n) ________ is data passed to a function.

6.2.3: Generating Random Numbers

  • Random numbers are a series of numbers whose order cannot be predicted
  • The C++ library has a random number generator, which produces numbers that appear to be random
  • Many computational problems need to use random numbers
  • rand() is a library function that produces a series of psuedorandom numbers:
    • Range is 0 up to and including RAND_MAX
    • Returns an "random" int value
  • Random numbers actual come from a a very long sequence of numbers computed from fairly simple formulas; they just behave like random numbers
  • For that reason they are often called psuedorandom numbers
  • The following program uses rand() to produce the same output every time it runs
  • The reason that the numbers are the same is because the numbers are generated with formulas

Example Program Using rand()

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

int main() {
    int i;
    for (i = 0; i < 10; i++) {
        int num = rand();
        cout << num << "\n";
    }

    return 0;
}

Check Yourself

  1. A ________ number is one that cannot be predicted ahead of time.
  2. The problem with this random number generator from xkcd is that you can ________.
  3. The function rand() returns a number between ________ and including ________.

6.2.4: Seeding the Random Generator

  • When running programs we do not always want the same sequence of numbers every time
  • For instance, if we run a dice simulation for a game we want different numbers every time the program runs
  • To get a different number, we must seed the random number generator
  • We set the seed with the srand() function
  • If we change the seed value, we will get different numbers every time
  • One common strategy for changing the seed value is to use time
  • Since the time changes every second, we get a new random number sequence every time we run our program
  • To generate a number from time, we can use the time() function from the C time library:
    srand(time(0));
  • The expression time(0) returns the number of seconds since January 1, 1970
  • Only call srand(time(0)) once in a program or you may get repeated numbers

Check Yourself

  1. The function ________ sets the starting location, or seed, for rand().
  2. To produce a new random number sequence every time a program starts use the code: ________.
  3. True or false: you must reseed the random number generator every time before calling rand().

Exercise 6.2

In this exercise we look at how to call functions and learn how to generate random numbers.

Specifications

  1. Copy the following program into a text editor, save it as dice.cpp, and then compile the starter code to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    int main() {
        // Enter your code here
    
        return 0;
    }
    
  2. Random numbers are generated by using the rand() function. Declare two integer variables, die1 and die2, and assign them values returned by the rand() function using code like the following:
    int die1 = rand();
    int die2 = rand();
    cout << "You rolled a " << die1
         << " and a " << die2 << endl;
    

    For more information, see section: 6.2.3: Generating Random Numbers.

  3. Compile and run your program and make sure your output looks like the following. Note that the actual numbers may be different.
    You rolled a 0 and a 1481765933
    

    Notice the size of the numbers displayed. We want to limit the size of the random numbers generated by rand() to only six numbers. We limit the range by using the modulus (%) operator.

  4. Change the two assignment statements with the following code:
    int die1 = rand() % 6;
    int die2 = rand() % 6;
    

    The number 6 in the above code is known as the scaling factor since it limits the scale of the numbers produced by the rand() function.

  5. Compile and run your program and make sure your output looks like the following. Note that the actual numbers may be different.
    You rolled a 0 and a 5
    
  6. Seeing just one roll of the dice is not very useful. Add a counting loop to roll and display the dice 10 times. For more information, see section: 5.1.1: Using Loops to Count. You may want to use a for loop for counting as described in section 5.1.2: for Statements.
  7. Compile and run your program and make sure your output looks like the following. Note that the actual numbers may be different.
    You rolled a 0 and a 5
    You rolled a 3 and a 2
    You rolled a 5 and a 0
    You rolled a 0 and a 4
    You rolled a 0 and a 2
    You rolled a 1 and a 3
    You rolled a 5 and a 3
    You rolled a 5 and a 0
    You rolled a 5 and a 0
    You rolled a 0 and a 5
    

    Notice that we get numbers in the range of 0 to 5 when we want 1 to 6. To correct this problem, we must add one to each of the statements generating the random numbers. Go ahead and make this change now. For more information, see section: 6.2.5: Simulating Dice.

  8. Rerun your code two or more times and check the numbers rolled. Do you see any patterns? To correct the problem we must "seed" the random number generator. Add the following code after the start of main and before your counting coop:
    srand(time(0));
    

    For more information, see section: 6.2.4: Seeding the Random Generator.

  9. Compile and run your program and make sure your output looks like the following. Note that the actual numbers may be different.
    You rolled a 1 and a 1
    You rolled a 4 and a 5
    You rolled a 5 and a 6
    You rolled a 3 and a 6
    You rolled a 2 and a 4
    You rolled a 4 and a 6
    You rolled a 3 and a 4
    You rolled a 1 and a 5
    You rolled a 4 and a 5
    You rolled a 4 and a 6
    
  10. Submit your final program source code to Blackboard as part of assignment 6.

As time permits, read the following sections and be prepared to answer the Check Yourself questions in the section: 6.2.7: Summary.

6.2.5: Simulating Dice

  • A simulation is an imitation of some real thing or process
  • We create a simulation in a computer program by generating random events and evaluating their outcome
  • One simple simulation we can do is a pair of dice
  • We need a number between 1 and 6, but rand() returns a number between 0 and RAND_MAX
  • We need only random numbers for a die and so we scale the range of RAND_MAX using the % operator
  • Now we can generate random integer numbers between 0 and 5
  • To get a number between 1 and 6, we shift the numbers by adding 1
  • Our code to simulate a single die with random numbers is now:
    int die = 1 + rand() % 6;
    cout << die << endl;
    
  • We can generalize our formula for producing integer random numbers to:
    rand() % SCALING_FACTOR + SHIFTING_VALUE;
    
  • The following program implements our dice rolling simulation
  • Note how the program simulates rolling 2 dice using 1 die at a time
  • You would get a different result if you just generated a random number between 2 and 12
  • To repeat the dice rolling, we use a loop

Example Program Simulating the Rolling of a Pair of Dice

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

int main() {
    srand(time(0));

    for (int i = 0; i < 10; i++) {
        int die1 = rand() % 6 + 1;
        int die2 = rand() % 6 + 1;
        cout << "You rolled a " << die1
             << " and a " << die2 << endl;
    }

    return 0;
}

Check Yourself

What code do you write to get the following result, including the end points?

  1. A random number between 1 and 6. answer
  2. A random number between 0 and 10. answer
  3. A random number between 1 and 10. answer
  4. A random number between -10 and 10. answer

6.2.6: Flotaing-Point Random Numbers

  • Sometimes we want random numbers that are of data type double
  • For example, we may want a random number for simulations
  • However, the rand() function returns an int and we need to convert the int to a double
  • For this we can use the formula:
    double r = rand() / (RAND_MAX + 1.0);
    
  • This produces a number between 0 (inclusive) and 1 (exclusive), often written as [0, 1)
  • One we have this random double, we multiply it by the scaling factor
  • Also, we can shift the range using addition or subtraction
    double num = r * SCALING_FACTOR + SHIFTING_VALUE;
    
  • For example, we can get a random floating-point number between -10 and +10 (not including +10) using:
    double r = rand() / (RAND_MAX + 1.0);
    double y = r * 20 - 10;
    
  • If we want to include +10 then we use the simpler:
    double r = rand() / RAND_MAX;
    double y = r * 20 - 10;
    

6.2.7: Summary

  • A function is a block of code get executed when called
  • During a function call, control is passed to the called function
  • When the called function finishes executing, control returns to the calling function and statement
  • C++ has many predefined functions in several libraries
  • Libraries must be "included" in a program:
    #include <cmath>
  • Newer standard libraries, such as cmath, also require the directive:
    using namespace std;
  • One of the library functions generate "random" numbers: rand()
  • To seed the random number generator, you use the srand() function
  • We can use these functions to simulate the rolling of a die:
    srand(time(0));
    
    int die = 1 + rand() % 6;
    cout << die << endl;
    
  • You can use random numbers for other computations as well, such as x and y coordinates:
    double r = (double) rand() / ((double) RAND_MAX + 1.0);
    double y = r * 20 - 10;
    

Check Yourself

Answer these questions to check your understanding. You can find more information by following the links after the question.

  1. What is a function? (6.2.1)
  2. Why do we use functions? (6.2.2)
  3. Where does the control flow during a function call? (6.2.2)
  4. What is an argument? (6.2.2)
  5. What is a returned value? (6.2.2)
  6. What is a random number? (6.2.3)
  7. What is the value of RAND_MAX on our classroom computers? (6.2.3)
  8. How do you make the rand() function return a different random sequence when you run your program again? (6.2.4)
  9. How do you code a random number that simulates rolling a die? (6.2.5)
  10. What statement do we use to limit the range of the values returned by the rand() function to the values 1 through 10? (6.2.5)

6.3: Coding Functions

Learner Outcomes

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

  • Define functions with and without parameters
  • Pass arguments to functions

6.3.1: Repeated Code

  • As developers, we need to know how to create and call functions

    Function: a named block of statements that can receive input, perform an action, and optionally return a value

  • Once we define a function, we can execute the statements by calling the function
  • Functions help us organize our code into modules and reduce errors
  • The following example shows one use for functions

Example Application for a Function

  • Recall our test code to validate user input:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;

int main() {
    double input = 0.0;
    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');
            input = -1; // set loop test to fail
        } else if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input <= 0.0);
    cout << "You entered: " << input << endl;

    return 0;
}
  • What if we need to enter two validated numbers into a program?
  • We want to process the first number after input and then input the second number
  • Doing so, we would end up with code 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
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
using namespace std;

int main() {
    double input = 0.0;
    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');
            input = -1; // set loop test to fail
        } else if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input <= 0.0);

    // Process the input
    cout << "You entered: " << input << endl;

    double input2 = 0.0;
    do {
        cout << "Enter a positive number: ";
        cin >> input2;
        if (cin.fail()) {
            cout << "You must enter digits, not words\n";
            cin.clear();
            cin.ignore(INT_MAX, '\n');
            input2 = -1; // set loop test to fail
        } else if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input <= 0.0);

    // Process the second input
    cout << "You entered: " << input2 << endl;

    return 0;
}
  • Our program would be easier to write if we could get the second input without repeating the code
  • With functions, we give the list of commands a name and then run the list using the name

Programming Style: Avoid Duplicating Code

  • Duplicate code is the mark of a poor or lazy programming style
  • It can lead to problems such as:
    • Long repeated sections that are more difficult to understand than shorter sequences
    • Repetition of largely identical code within which it is difficult to see the different purposes of each section
    • Update anomalies where you make changes in some sections but overlook making changes in other sections
  • If you find yourself writing similar code of three or more lines multiple times, then consider writing a function

Check Yourself

  1. A function is a __________ block of statements that can receive __________, and optionally __________ a value.
  2. True or false: functions can reduce the amount of repeated code, making programs shorter.
  3. True or false: people write functions to organize code into small understandable pieces.

6.3.2: Defining a Function

  • A function is like a little program within a bigger program
  • What a function does depends on what statements you put inside it
  • For instance, a function might display a line of text
  • Another function might calculate a number and return the result of the calculation
  • We have used functions already, such as:
    • sqrt(x) -- computes the square root of a floating point number
    • pow(x, y) -- computes the power of xy
  • Many functions have input values (a.k.a. arguments or parameters) that are transferred or passed into the function
  • For example:
    • The x in: y = sqrt(x);
    • Both the x and the y in: z = pow(x, y);
    • An expression as in: sqrt(b * b - 4 * a * c);
  • Many functions have output or return values
  • For example the y in: y = sqrt(x);
  • Both parameters and return values are a particular type
  • For instance:
    • You cannot compute: sqrt("Ed Parrish");
    • You cannot assign: string thing = sqrt(5.5);

Function Syntax

  • The general syntax for defining a function is:
    returnType functionName(parameter1, ..., parametern) {
        statements
    }
    
  • Where:
    • returnType: the data type of the value returned
    • functionName: the name you make up for the function
    • parameterx: the input values, if any
    • statements: the statements to execute when the function is called
  • As an example, we can define our function to read a positive number like this:
    double readPosNum(String prompt) {
        // Statements to read and validate the input
    }
    
  • Lets look more details of the syntax in order from left to right

Return Type

  • Sometimes you will want a function to return a value
  • If you do, then you need to specify the type of data it will return
  • If you do not want a function to return a value, then you use the keyword void
  • In our example the return type is a double

Function Name

  • Technically, you can use any valid identifier for a function name
  • However, you should use a name that suggests the action the function performs
  • For instance, readPosNum suggests that the function will get a positive number from the user

Parameter List

  • You must have parenthesis after the function name
  • Inside the parenthesis, you define a list of zero or more parameters
  • Parameters are like variables except they are declared inside the function parenthesis
  • Each parameter must have both a type and a name, just like a variable
  • If you have more than one parameter, you separate each one with commas
  • Any parameter that you declare must be given a value when you call the function

Code Block

  • After the parenthesis, you define the block of code that you want to execute
  • The block starts with an opening curly brace: {
  • The block ends with a closing curly brace: }
  • Between the curly braces, you place all the statements you want the function to execute
  • For readability, you indent the statements within the curly braces

Check Yourself

  1. The statements inside a function are surrounded by ________.
    1. Curly brackets -- { }
    2. Parenthesis -- ( )
    3. Square brackets -- [ ]
    4. Colons -- : :
  2. True or false: function names are case sensitive.
  3. Of the following, ________ would be a valid function definition?
    1. fun() { /* C++ statements */ }
    2. int fun;
    3. int fun() { /* C++ statements */ }
    4. int fun();
  4. __________ are used to allow a function to get input of one or more values from somewhere outside the function.
  5. Parameters are set on the first line inside a set of __________
    1. Curly brackets -- { }
    2. Parenthesis -- ( )
    3. Square brackets -- [ ]
    4. Colons -- : :

6.3.3: Example Function Definition

  • Let us define a function for reading positive numbers
  • We are taking our previous repeated code and packaging it inside a function
  • You can see the entire function in the following program

Example Program with a Function for Reading Input

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 <iostream>
using namespace std;

double readPosNum(string prompt) {
    double input = 0.0;
    do {
        cout << prompt;
        cin >> input;
        if (cin.fail()) {
            cout << "You must enter digits, not words\n";
            cin.clear();
            cin.ignore(INT_MAX, '\n');
            input = -1; // set loop test to fail
        } else if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input <= 0.0);

    return input;
}

int main() {
    double input = readPosNum("Enter a positive number: ");
    // Process the input
    cout << "You entered: " << input << endl;

    double input2 = readPosNum("Enter another number: ");
    // Process the second input
    cout << "You entered: " << input2 << endl;

    return 0;
}
  • Note that the function readPosNum() comes before main()
  • In C++, the compiler requires us to declare a function before we call the function
  • Since we call function readPosNum() from main(), we must put the function before main()
  • Also notice that the function readPosNum() is outside of main()
  • You cannot nest functions
  • Instead, each function is separate from every other function

Variable Scope, Parameters and Return Statements

  • A variable declared inside a function can only be used within that function

    Local variable: a variable that can only be accessed within a function or block.

  • For example, we declared input inside the readPosNum() function:
    double input = 0.0;
  • In addition, we declared another variable named input inside main():
    double input = readPosNum("Enter a positive number: ");
    
  • These are not the same variable even though the have the same name
  • The area of code that a variable can operate within is known as it's scope

    Scope: the enclosing area within which a variable exists

  • To send information to a function we must use a parameter:
    double readPosNum(string prompt)
  • Within main() we send the information to the parameter as part of the function call:
    readPosNum("Enter a positive number: ")
  • The string, "Enter a positive number: ", is passed to the parameter variable: prompt
  • To return information from a function, we use a return statement:
    return input;
  • We must save the returned information if we want to it for processing:
    double input = readPosNum("Enter a positive number: ");
    
  • This is the same process we used for calling sqrt():
    y = sqrt(x);

Flow of Control for a Function Call

  • To use functions well, you must understand their flow of control
  • In our example, the program starts executing in the main() function
  • When our program gets to the following statement, it stops executing in main() and jumps to our function:
    double input = readPosNum("Enter a positive number: ");
    
  • The program executes the statements in the function and then returns to the statement from which it jumped
  • After returning to the calling statement, the program completes processing the statement and then moves on to the next statement
  • In our example, the statement saves the returned value in the variable: input
  • 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

Check Yourself

  1. Of the following, __________ is a valid function call.
    1. int fun2(myArgument);
    2. fun2(myArgument);
    3. int fun() { /* C++ commands */ }
    4. fun2(myArgument) functionCall;
  2. A __________ variable can be used only within the function in which it was declared.
  3. True or false: after a function is called, it returns to the place in the code from which it was called.

Exercise 6.3

In this exercise we define our own function.

Specifications

  1. Copy the following program into a text editor, save it as absvalue.cpp, and then compile the starter code to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    int main() {
        // Enter your code here
    
        return 0;
    }
    
  2. Inside the main() function, enter these statements:
    cout << "This program calculates absolute values\n";
    cout << "Number to calculate: ";
    double num = 0.0;
    cin >> num;
    double absnum = calcAbs(num);
    cout << "Absolute value is: " << absnum << endl;
    

    The fifth line contains the function call. For more information on function calls, see section: 6.2.2: Calling a Function.

  3. Try to compile your code. You should see an error message like:
    absvalue.cpp:9: error: `calcAbs' undeclared
    

    The reason is that the we have not yet written the calcAbs() function. We must define a function before we can call the function.

  4. Before the main() function, define a function named calcAbs() as shown below:
    double calcAbs(double value) {
        // Insert statements here
    
        return value;
    }
    

    Your code should compile at this time. Even though the function is not complete, we have supplied enough information to the compiler to define the calcAbs() function.

  5. Inside the curly braces of the calcAbs() function, write the statements to calculate the absolute value using the following psuedocode:
    if value is less than zero return -1 * value
    return value
    
  6. Compile and run your modified program and verify the output looks like:
    This program calculates absolute values
    Number to calculate: -42
    Absolute value is: 42
    
    Also, verify that a positive number works correctly:
    This program calculates absolute values
    Number to calculate: 42
    Absolute value is: 42
    
  7. In addition to completing the programming code, prepare a second file named trace.txt.
  8. In the trace.txt file, list the line numbers of each statement of your program in the order the lines are executed. For example, if main() starts on line 11, statements are executed as follows:
    11, 12, 13, 14, ...
    

    Do not bother to list blank lines or lines containing only the closing curly brace (}) of a function definition.

  9. Review the hand trace with another student in the class. Then add a comment to the top of the file that contains the name of the person with whom you reviewed the code, like:
    Reviewed trace with Fred George.
  10. Submit both files absvalue.cpp and trace.txt to Blackboard as part of assignment 6.

Completed Program

When finished, your application should look like the following.

Completed exercise

As time permits, read the following sections and be prepared to answer the Check Yourself questions in the section: 6.3.7: Summary.

6.3.4: Passing Arguments to a Function

  • Let us look how parameters work in more detail
  • When a program makes a function call, it sends the data inside the parenthesis to the function:
    readPosNum("Enter a positive number: ");
  • The string, "Enter a positive number: ", is passed to the parameter variable: prompt:
    double readPosNum(string prompt)
  • The function call must include an argument for every parameter
  • In addition, the data type of each argument must be compatible with the data type of the parameter

Arguments and Parameters

  • Depending on your programming background, you might use the term arguments or parameters for the values passed into functions
  • The terminology is not that important
  • However, the way I will use the terms is:
    • A called function has parameters
      double readPosNum(string prompt) {
          // Commands to execute in the function
      }
      
    • A caller passes arguments
      readPosNum("Enter a positive number: ");
  • Arguments are values you pass into functions
  • When the argument drops into a function, it lands in a parameter
  • The parameter is just like a local variable in the function
    • Except that a parameter gets initialized by an argument
  • The important part is:

    If a function takes a parameter, you must pass it a value.

  • Also, the value must be the same type as the parameter

Check Yourself

  1. If you declare three parameters, you must include ________ arguments in a function call.
  2. Which of the following is a function definition and which is a function call?
    1. int drawSquare(int x, int y) { /* statements */ }
    2. drawSquare(4, 2);
  3. A ________ is defined in a function and an ________ is data passed to a function.
  4. ________ correctly calls a function named someFun() and sends it two string arguments.
    1. someFun();
    2. someFun("some", "words");
    3. someFun("some", "words);
    4. somefun();

6.3.5: Returning a Value

  • Functions that return a value must execute a return statement
    return result;
  • For instance, in our example, function readPosNum() had a return statement
double readPosNum(string prompt) {
    double input = 0.0;
    do {
        cout << prompt;
        cin >> input;
        if (cin.fail()) {
            cout << "You must enter digits, not words\n";
            cin.clear();
            cin.ignore(INT_MAX, '\n');
            input = -1; // set loop test to fail
        } else if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input <= 0.0);

    return input;
}
  • We must save the returned information if we want to it for processing:
    double input = readPosNum("Enter a positive number: ");
    

Returning Early

  • Sometimes you do not want to execute all the code in a function
  • You can use a return statement to stop execution and return from anywhere
  • Control returns immediately from a function whenever a return is reached

Check yourself

  1. To return a value from a function use a __________ statement.
  2. True or false: a value returned from a function must be of the same type as the function return type.
  3. Of the following, __________ correctly assigns the result of a function named getSomething() to a variable named shopping
    1. shopping = getSomething();
    2. shopping = getSomething;
    3. shopping(getSomething);
    4. shopping() = getSomething();

6.3.6: Some Style Requirements for Functions

  • Consider again our 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
26
27
28
29
30
31
32
#include <iostream>
using namespace std;

double readPosNum(string prompt) {
    double input = 0.0;
    do {
        cout << prompt;
        cin >> input;
        if (cin.fail()) {
            cout << "You must enter digits, not words\n";
            cin.clear();
            cin.ignore(INT_MAX, '\n');
            input = -1; // set loop test to fail
        } else if (input <= 0.0) {
            cout << "You must enter a positive number\n";
        }
    } while (input <= 0.0);

    return input;
}

int main() {
    double input = readPosNum("Enter a positive number: ");
    // Process the input
    cout << "You entered: " << input << endl;

    double input2 = readPosNum("Enter another number: ");
    // Process the second input
    cout << "You entered: " << input2 << endl;

    return 0;
}
  • 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:
      int myFunction() {
          // statements of the function
      }
      
    2. Place the opening brace under and lined up with the first letter of the return type:
      int 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

Check Yourself

  1. True or false: You should indent code within a function.
  2. You should always indent ________ spaces inside a function.

6.3.7: Summary

  • When we reuse a block of code in various parts of a program, we should put the code into a function
  • To define a function, we use the following syntax:
    returnType functionName(parameter1, ..., parametern) {
        statements
    }
    
  • When we define a function, we want it to be reusable
  • To make a function more reusable, we avoid hard-wiring important values
  • Instead, we pass the key values by defining parameters
  • When we call the function, we supply an argument for each parameter

Check Yourself

Answer these questions to check your understanding. You can find more information by following the links after the question.

  1. Why do programmers write functions? (6.3.1)
  2. What is a function? (6.3.2)
  3. What are the four main parts of a function? (6.3.2)
  4. How can you tell the difference between a function name and a variable name? (6.3.2)
  5. How many parameters can you declare for a function? (6.3.2)
  6. How is a variable declaration different than a parameter? (6.3.2)
  7. If you declare a variable inside main() can you access that variable inside another function? (6.3.3)
  8. Why do functions need parameters? (6.3.3)
  9. If you call a function in main(), do you place the function definition before or after main()? (6.3.3)
  10. What happens to the flow of control when a function call is reached? (6.3.3)
  11. If you declare three parameters, how many arguments must you include in a function call? (6.3.4)
  12. Which of the following is a function definition and which is a function call? (6.3.4)
    1. int drawSquare(int x, int y) { }
    2. drawSquare(4, 2);
  13. What is the difference between an argument and a parameter? (6.3.4)
  14. What statement is used to return values from functions? (6.3.5)
  15. True or false? You should indent code within a function. (6.3.6)

Wrap Up

Due Next:
A5-Loopy Programs (3/15/12)
A6-Programs With Functions (3/22/12)
  • 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 | Day Schedule | Eve Schedule
Syllabus | Help | FAQ's | HowTo's | Links
Last Updated: March 18 2012 @22:55:55