7: Getting Functional

What We Will Cover


Continuations

NASA Swarmathon

  • Cabrillo Robotics Club participating
  • You can join the Robotics Club
  • Opportunity to improve your programming skills

Questions from last class?

Homework Questions?

Learning from the Midterm

Learner Outcomes

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

  • Know what was missed on the midterm
  • Decide on what you need to do to improve your performance, if anything
  • Write code to respond to mouse clicks

7.1.1: Post Midterm Review

  • Everyone who did all the homework and completed the midterm study preparations fully passed the midterm
  • For difficult topics I suggest reviewing the notes and homeworks and getting help understanding -- and then practice until perfect!
  • If you believe a question was graded incorrectly, please email me an explanation
  • We will have another midterm before the final
  • Grading policies are listed in the syllabus

7.1.2: Post Midterm Survey

  • Please complete the following survey to help future students and the instructor
  • Post Midterm Survey

7.1.3: Making the Grade

  • Oftentimes students who get less than an "A" on the midterm wonder if they can still get an "A" in the course
  • Since this is the first midterm, the answer is "Yes" unless:
    • You have not completed most of the homework
    • AND you failed the midterm with < 50%
  • Even with the above, you can still pass the course and even get a "B"
  • However, you will need to start doing your homework fully and study more for the tests

Suggestions for Improving your Grade

  • Start planning and studying for the next midterm now
  • Take notes and rewrite them the day after a class meeting
  • Review your notes every week and identify possible exam problems
  • Analyze your homework and get help on items with which you have problems
  • Study with others by reviewing homework problems and practicing with possible exam questions
  • Use your instructors' office hours to ask questions about material you don't understand

Exercise 7.1: Midterm Self-Reflection

In this exercise we reflect on our progress in this course.

You Can Learn Anything: from the Khan Academy (1:30)

  • Brain research shows that we can grow our brain interconnections
  • Like a muscle, the more we work with our brain the more it grows
  • When things are easy our brain may grow a little
  • However, the most growth occurs when we struggle with things
  • Research shows that our brain grows the most when we get a question wrong
  • So if we did not do well on the midterm, we have an opportunity to grow our brain
  • When we review and understand why we got something wrong, that is when our brain grows the most
  • If we keep improving when we get something wrong, we are on our way to a more capable brain

Reflection (3m)

  1. Please take out a piece of paper and something to write with.

    There is no need to tear the paper out of a notebook. If you need paper or a writing tool, ask a classmate or the instructor for one.

  2. Reflect on the following questions and write down an answer for yourself:
    1. Are you achieving your goals for this course?
    2. What ways can you think of to improve your progress towards goals?
    3. What actions are you going to take to better meet your goals?

More Information

7.2: Array Basics

Learner Outcomes

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

  • Declare and allocate memory for arrays
  • Generate code to initialize arrays
  • Access array elements
  • Use arrays with functions

7.2.1: Introduction to Arrays

  • Recall that a string is a series of characters enclosed in double quotes

    String character position

  • We can access individual characters of a string using []
    string s = "abcdef";
    char c = s[2]; // character 'c'
    
  • With the [] we can iterate through a string with a loop like:
    string s = "abcdef";
    for (unsigned i = 0; i < s.length(); i++) {
        cout << "Char[" << i << "]: " << s[i] << endl;
    }
    
  • It turns out we can make lists of numbers or other data that we can also access using []
  • These lists of data are called arrays

Array Definition

Array: an ordered arrangement of identically-typed data values

  • An array is used to process a collection of data of the same type
  • Often times we need to process a group of the same types of data, like:
    • Bank account transactions
    • Salaries for employees in a company
    • Prices for products
    • Temperature data over some period of time
    • Test scores for a group of students
  • Consider how we might process the following student test scores:
    90
    95
    87
    89
    98
    96
    85
    79
    95
    100
  • With this data, we can calculate statistics like:
    • Highest score
    • Lowest score
    • Average (mean) score
    • Difference (deviation) of each score from the average

Array Example

  • For the above example, we can define an array like:
    int score[] = { 90, 95, 97, 89, 98, 96, 85, 79, 95, 100 };
    
  • An array is like single row or column of data in spreadsheet or table
  • In C++, the slots of arrays are numbered starting at 0, as shown below:

    scores = 
    90[0]
    95[1]
    87[2]
    89[3]
    98[4]
    96[5]
    85[6]
    79[7]
    95[8]
    100[9]

  • Our array holds 10 values and all the values are of the same type: int
  • Each of the items inside an array slot is known as an element
  • The number inside of the square brackets is known as an index
  • Notice that the first index is 0 (zero)

Check Yourself

  1. To store lists of data we can code a(n) ________.
  2. True or false: we use arrays because they are more convenient than strings.
  3. True or false: arrays values must all be of the same type.
  4. To access an element of an array we use an ________.

7.2.2: Arrays and Elements

  • One way to define an array is to declare an array variable and provide a list of values
    dataType variableName[] = { list };
    
  • Where:
    • dataType: the data type of all the array items
    • variableName: the name you make up for the array
    • list: the list of values separated by commas
  • From our previous example:
    int scores[] = { 90, 95, 97, 89, 98, 96, 85, 79, 95, 100 };
    
  • This definition is known as static initialization because the values are assigned by the compiler
  • C++ has other ways to declare lists of data which we will explore later in the course

Accessing an Element

  • Once we have the array in place, we can access the elements using the index
  • The index is the position number of the element
  • For example, the integer 95 is at position 0, 97 at position 1, and so on
  • We use the variable name with the index inside square brackets to access an element
  • As an example, we would access the element with the value 98 as follows:
    score[3]
  • Once we access an element, we use it like a regular variable such as
    cout << score[3] << endl; // prints element #3
    
  • We can assign a new value to an element as well, like:
    scores[4] = 98;
    
  • Note that we should not go beyond the last index as the value is undefined and may cause errors
    cout << score[10] << endl; // element not defined
    

Try It: Create an Array (3m)

  1. Copy the following program into a text editor, save it as myarrays.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. Inside main(), add a statement to define an array of double named temp along with a list of five (5) randomly chosen values.
  3. Compile your code to make sure it has correct syntax.

    If you have problems, ask a classmate or the instructor for help as needed.

  4. Print element #0 like:
    cout << temp[0] << endl;
    
  5. Compile your code to make sure it has correct syntax.

    If you have problems, ask a classmate or the instructor for help as needed.

  6. Verify your code agains the following example. Your array values will vary.

Example Array of Type double

example array

Creating Arrays with No Values

  • We can declare an array with no values in each element using the following syntax
    dataType variableName[size];
    
  • Where:
    • dataType: the data type of all the array items
    • variableName: the name you make up for the array
    • size: the number of data items the array can hold
  • For example, the following is the declaration of an array named scores that holds 10 values of type int:
    const int SIZE = 10;
    int scores[SIZE];
    
  • Notice the use of the constant SIZE to record the number of elements
  • To make use of such an array, we would need to assign a value to each element like:
    scores[0] = 95;
    scores[1] = 97;
    // and so on
    

Check Yourself

  1. The number inside of the square brackets of an array is called an ________.
  2. Like a string, the first element in any array has an index value of ________.
    1. -1
    2. 0
    3. 1
    4. it depends on the declaration
  3. If you declare an array with 10 elements, the index number of the last element is ________.
  4. For the following array declaration, answer the questions below:

    double num = { 1.2, 2.3, 3.4, 4.5, 5.6 };

    1. The number of elements is ________
    2. The value of num[0] is: ________
    3. The value of num[2] is: ________
    4. The value of num[4] is: ________

7.2.3: Arrays and Loops

  • We can use a loop as a way to access each array element
  • Notice that the index of an array is an integer number
  • The index can be a counter variable, like those used in counter-controlled loops
  • Thus we can use arrays with a loop like:
    const int SIZE = 5;
    int nums[SIZE] = { 1, 2, 3, 4, 5 };
    int total = 0;
    for (int i = 0; i < SIZE; i++) {
        cout << nums[i] << endl;
        total = total + nums[i];
    }
    cout << total << endl;
    
  • The first time through the loop, when i = 0, the value of nums[i] is 1
  • The value of total starts at 0 but becomes 1 during the first iteration

Activity

  1. Take out a piece of paper and put your name on it.
  2. Create a table with columns for total, i and nums[i] like:
    total | i | nums[i]
    -------------------
          |   |
          |   |
    
  3. Trace the values of total, i and nums[i] for each iteration of the following loop: (3m)
    const int SIZE = 5;
    int nums[SIZE] = { 1, 2, 3, 4, 5 };
    int total = 0;
    for (int i = 0; i < SIZE; i++) {
        cout << nums[i] << endl;
        total = total + nums[i];
    }
    
  4. When finished, verify your array-and-loop trace with another classmate. (1m)

Check Yourself

For the following code:

const int SIZE = 5;
int nums[] = { 1, 2, 3, 4, 5 };
int total = 0;
for (int i = 0; i < SIZE; i++) {
    cout << nums[i] << endl;
    total = total + nums[i];
}
cout << total << endl;
  1. For the second time through the loop:
    1. The value of the index variable i is ________
    2. The value of nums[i] is ________
  2. After executing the above code snippet, the value stored in total is ________?
    1. 0
    2. 1
    3. 2
    4. 15

7.2.4: Finding Elements in an Array

  • Suppose you want to find a particular value in an array
  • This is known as searching a list
  • An easy and straightforward algorithm is linear search (a.k.a. sequential search)
  • In linear search you:
    • Start at the beginning of the list
    • Compare each value in the list looking for matches:
      • If the value is found, then return the position (index)
      • If you reach the end of the list, return "not found"
  • Since an index must be >= 0, then we can use -1 as the "not found" value

Group Activity: Finding an Element in a List

  1. Select one volunteer to be the finder.
  2. All other students line up and each choose a number between 1-20.
  3. The finder writes the number he or she is looking for on the board.
  4. The finder starts at one end of the line and asks each student if he or she has the number sought, keeping track of the current student index number.
  5. When a student with the sought after number is found, write the index number of the found student on the board, or -1 if the number is not found.

Solo Activity: Writing the Algorithm

  1. At the top of your myarrays.cpp file from the last exercise, add a block comment like
    /*
    Linear Search Algorithm
    ... write the algorithm here
    */
    
  2. In the block comment write the algorithm for finding an element in an array using psuedocode. (3m)
  3. Review your algorithm with another student. (2m)

Check Yourself Click to show message

  1. True or false: to find a value in an array, start at one end and check each element until you find the value or reach the end.
  2. The above technique for searching a vector is known as sequential or ________ search.
  3. True or false: when searching an array you must always start at index 0 and proceed to the end.

Exercise 7.2: Simple Arrays (5m)

In this exercise we explore processing arrays as lists.

Specifications

  1. If you have not already created the myarrays.cpp file, complete the exercise Try It: Create an Array.
  2. Add a for-loop that accesses every index of the temp array and prints every value to the screen like:

    array loop

  3. Compile your code to make sure it has correct syntax.

    If you have problems, ask a classmate or the instructor for help as needed.

  4. Declare a summing variable named total before the loop and initialize the variable to zero (0).
  5. Inside the loop, add the indexed temp[i] value to total every time the loop iterates.
  6. Compile your code to make sure it has correct syntax.

    If you have problems, ask a classmate or the instructor for help as needed.

  7. After the loop completes, print the value of total.
  8. Compile your code to make sure it has correct syntax.

    If you have problems, ask a classmate or the instructor for help as needed.

  9. Save your program source code to submit to Canvas as part of assignment 7.

When finished, please help those around you.

7.2.5: Summary

  • In this section we looked at how to use arrays for lists of numbers
  • An array is a list of data elements each identified by an index

    array

  • Arrays are used to keep a list of data that is easily accessed
  • Any type of data may be stored in an array, but all elements must be of the same type
  • For example, we may have a list of student test scores to process:
    909587899896857995100
  • With this data, we can calculate statistics like:
    • Highest score
    • Lowest score
    • Average (mean) score
    • Difference (deviation) of each score from the average

Creating an Array

  • One way to define an array is to declare an array name and provide a list of values
    dataType variableName[] = { list };
    
  • Where:
    • dataType: the data type of all the array items
    • variableName: the name you make up for the array
    • list: the list of values separated by commas
  • For example:
    int scores[] = { 95, 97, 89, 98, 96, 85, 79, 95, 100 };
    
  • We can declare an array with no values using the following syntax:
    dataType variableName[size];
    
  • Where:
    • dataType: the data type of all the array items
    • variableName: the name you make up for the array
    • size: the number of data items the array can hold
  • For example, the following is the declaration of an array named scores that holds 10 values of type int:
    const int SIZE = 10;
    int scores[SIZE];
    
  • Arrays like this can never change size and the array size must be set when the program is compiled
  • To make use of such an array, we would need to assign a value to each element like:
    scores[0] = 95;
    scores[1] = 97;
    // and so on
    

Accessing Array Elements

  • We specify which slot of an array to access with the [] operator:
    cout << score[3] << endl; // prints element #3
    
  • The indexes of arrays are numbered starting at index 0
  • We can assign a value to an array element any time after it is declared:
    const int SIZE = 10;
    int scores[SIZE];
    scores[0] = 90;
    scores[1] = 95;
    scores[2] = 87;
    scores[3] = 89;
    scores[4] = 98;
    
  • In addition, we can read the value of an element using square brackets like:
    cout << scores[4] << endl;
    

Arrays and Loops

  • Because array indices are integers, we often use counting loops to access array elements like
    int scores[] = { 90, 95, 87, 89, 98, 96, 85, 79, 95, 100 };
    for (int i = 0; i < 10; i++) {
        cout << scores[i] << endl;
    }
    

Linear Search

  • One of the algorithms we discussed was linear search
  • We use linear search to find a specific element of an array
  • Linear search is easy to implement using a simple loop:
    int found = -1;
    for (unsigned i = 0; i < NUM_ELEMENTS and found == -1; i++) {
        if (item == arr[i]) {
            found = i;
        }
    }
    

Array Parameters

  • When writing a function with an array parameter, we place an empty [] after the parameter name:
    void print(int values[], int size);
    
  • We need to pass the size of the array into the function, because the function has no other way of knowing the size of the array
  • Sometimes we must pass both the capacity and size of an array to a function:
    void read(int data[], int capacity, int& size);
    
  • The capacity parameter tells the function the maximum array size
  • The size parameter records how many items the user entered into the array
  • Also note that functions cannot return arrays

7.3: 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

7.3.1: Introducing 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
  • The name function comes from mathematics where we write generalized formulas like:

    f(x) = 2x + 3

  • With the above formula, we can plug in a value for x and get a final value
  • In C++ we would write code like the following for the above math function:
    int f(int x)
    {
        return 2 * x + 3;
    }
    
  • Notice that we have been writing functions named main() for every program:
    #include <iostream>
    using namespace std;
    
    int main() {
        cout << "Hello, World!\n";
        return 0;
    }
    

Function Libraries

  • Function are often collected into libraries so they can be reused by many different programs
  • C++ comes with many common libraries of functions such as <cmath> which contains 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

Library Functions

  • Here are some library functions we have used so far:
    exp(exponent);
    pow(base, exponent);
    sqrt(number);
    length();
    substr(index, numChars);
    getline(cin, stringVariable);
    
  • Any others?
  • What do they all have in common? Notice any similarities?

Check Yourself

  1. A named block of code that executes its statements when called is known as a(n) ________.
  2. Many predefined functions are available in program ________.
  3. Function that are previously written and included in the C++ libraries are known as ________ functions.

7.3.2: Calling a Function

  • When a function is defined or included in a program, C++ ignores the statements at first
  • In order to execute the statements, we must call the function

    Function call: a request by a program to execute a function.

  • A function call passes control to the called function
  • After completing the function, control returns to the calling function (like main())
  • 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, we 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 calling function stops and waits for the called function to finish
  • We 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 argument like 9.0:
    sqrt(9.0);
  • In this case the argument is the numerical value 9.0
  • When the called function finishes executing, it returns to where it was called from
  • When the function returns, it may return a value
  • In the following example, our function call returns the value 3.0
  • We combine the returned value with an arithmetic expression and then save the expression in a variable

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: function calls always include parenthesis.
  4. After a function ends, control returns to the ________ statement.
  5. data passed to a function is known as an ________.

7.3.3: Generating Random Numbers

  • As an example of predefined functions, let us look at random numbers
  • Random numbers are a series of numbers whose future values cannot be predicted
  • Many computational problems need to use random numbers like:
    • Cryptography in many areas including generating passwords
    • Simulation of unpredictable real phenomena
    • Random numbers in games of chance like dice rolling
    • Random shuffling of the audio files in an audio player
  • The C++ library has a random number generator, rand(), that produces a series of psuedorandom numbers:
    • Range is 0 up to and including RAND_MAX
    • Returns an "random" int value
  • To make use of the rand() function we may need to include the library:
    #include <cstdlib>
    
  • The syntax for calling the function is:
    rand()
    
  • For example:
    int randNumber = rand(); // returns number between 0 and RAND_MAX
    

Psuedorandom

  • The numbers produced by the library appear to be random but are not
  • We call these types of random numbers psuedorandom
  • Psuedorandom means that given an initial starting condition, the procedure always produces the same result
  • Random numbers actual come from a a very long sequence of numbers computed from fairly simple formulas; they just behave like random 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 the same computer commands every time it is called
  • When running the following program, remember the first few numbers and then start the program again
  • Notice that the same sequence of numbers is produced

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;
}

More information

Check Yourself

  1. A number whose value cannot be predicted ahead of time is known as a ________ number.
  2. The problem with this random number generator from xkcd is that ________.
    1. dice rolling is not a fair way to get random numbers
    2. it was not selected randomly
    3. you can predict the number ahead of time
    4. nothing is wrong
  3. The function rand() returns a number between ________ and including ________.

7.3.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 with the syntax:
    srand(seed)
    
  • Where:
    • seed: the initial number for the random sequence
  • For example:
    randomSeed(seed);
    
  • If we change the seed value, we will get different numbers every time

Changing the Starting Value

  • One common strategy for changing the seed value is to use the current 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 standard time library:
    srand(time(0));
  • The expression time(0) returns the number of seconds since January 1, 1970
  • To make use of the time() function we may need to include the library:
    #include <ctime>
    
  • We only call srand(time(0)) once in a program or we may get repeated numbers

Example Program Using srand()

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

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

    return 0;
}

Check Yourself

  1. The function that sets the starting location, or seed, for rand() is ________.
  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 7.3: Getting Random (8m)

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. Add the library cstdlib at the top of the file:
    #include <cstdlib>
    
  3. 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: 7.3.3: Generating Random Numbers.

  4. 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.

  5. 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.

  6. 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
    
  7. 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.
  8. 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: 7.3.5: Simulating Dice.

  9. 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: 7.3.4: Seeding the Random Generator.

  10. 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
    
  11. Save your final program source code to submit to Canvas as part of assignment 7.

Read the following section and be prepared to answer the Check Yourself questions.

7.3.5: Simulating Dice*

  • A simulation is an imitation of some real thing or process
  • We create a simulation of randomness in a computer program by generating random numbers
  • One simple random simulation we can do is a pair of dice

Setting the Range

  • 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
16
#include <iostream>
#include <cstdlib>
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 integer random numbers, including the end points?

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

7.3.6: Summary

  • A function is a block of code gets 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? (7.3.1)
  2. Why do we use functions? (7.3.2)
  3. Where does the control flow during a function call? (7.3.2)
  4. What is an argument? (7.3.2)
  5. What is a returned value? (7.3.2)
  6. What is a random number? (7.3.3)
  7. What is the value of RAND_MAX on our classroom computers? (7.3.3)
  8. How do you make the rand() function return a different random sequence when you run your program again? (7.3.4)
  9. How do you code a random number that simulates rolling a die? (7.3.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? (7.3.5)

7.4: Coding Functions

Learner Outcomes

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

  • Discuss the reason for writing functions
  • Define functions with and without parameters
  • Pass arguments to functions
  • Return values from functions
  • Trace the flow of a function call

7.4.1: Grouping Repeated Commands

  • Some of the main() functions in our programs have been getting lengthy and complicated
  • The biggest problem in developing software is managing the complexity of programs
  • We can improve our code by organizing it into smaller pieces known as functions
  • Functions are a key tool in creating easy-to-understand programs that can be changed easily

What is a Function?

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

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

  • Functions are like little programs in our larger program
  • We give each little function commands we want executed
  • We call the function whenever we want the commands executed
  • When the function has finished running, program execution returns to the point just after the code that called the function

Example Application for a Function

  • As an example, 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(1000, '\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 by calling the name
  • Using functions we keep all the code in one place and avoid duplication
  • Avoiding duplication reduces the complexity of our code and makes it easier to understand and change

Programming Style: Avoid Duplicating Code

  • Duplicate code 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 problems where we make changes in some sections but overlook making changes in other sections
  • If we find ourselves writing similar code of three or more lines multiple times, we should consider writing a function

Check Yourself

  1. True or false: people write functions to organize code into small understandable pieces.
  2. Which of the following are features of a function?
    1. Must have a name
    2. Can receive input
    3. Performs an action
    4. Must return a value
  3. True or false: when a function finishes executing, the program flow returns to the point just after the code that called the function.
  4. True or false: functions can reduce the amount of repeated code, making programs shorter.

7.4.2: Defining a Function

  • In this section we look at function definition syntax and examine a simple example function
  • After we understand the syntax we can write more complicated functions

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 list of statements to execute when the function is called
  • Can you identify each of these syntax items in the function we have always used?
    int main() {
        // program statements go here
    }
    

Example Program with a Second Function

  • As an example, the following program has a simple function to add two numbers
  • Notice that the code has two functions: add() and main()
  • The second function is placed before main() so the compiler knows about the function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
using namespace std;

int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    cout << "Enter two numbers to add: ";
    int num1, num2;
    cin >> num1 >> num2;
    int total = add(num1, num2);
    cout << "Sum=" << total << endl;

    return 0;
}

Function Name

  • Every function must have a name that identifies the function
  • Function names follow the same rules as variable names
  • Technically, we can use any valid identifier for a function name
  • However, we should use a name that suggests the action the function performs
  • In our example, add suggests that the function will return the sum of two numbers

Function Structure

  • The first line of a function is known as the function signature
    int add(int a, int b)
    
  • The curly braces {...} contain the function body
  • The function body is the list of statement the function executes when called
  • The function signature describes the name, inputs and output of a function
  • We will look at these features in more detail in the following sections

Check Yourself

  1. True or false: function names are case sensitive.
  2. Of the following, ________ would be a valid function definition.
    1. fun() { /* C++ statements */ }
    2. int fun;
    3. int fun() { /* C++ statements */ }
    4. int fun();
  3. The statements inside a function are surrounded by ________.
    1. Curly braces -- { }
    2. Parenthesis -- ( )
    3. Square brackets -- [ ]
    4. Colons -- : :
  4. 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);

7.4.3: Parameters

  • When defining a function, it is worth thinking about what helpful action it will perform
  • We can make the function more useful if we give it parameters
  • Recall the use of functions in mathematics like:

    f(x, y) = x + y

  • With the above formula, we can plug in a value for x and y to get a final value
  • Like in math, we need two parameters for an add function
  • Read through the following code to identify how the code makes use of the parameters

Example Code with Function Parameters

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

int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    cout << "Enter two numbers to add: ";
    int num1, num2;
    cin >> num1 >> num2;
    int total = add(num1, num2);
    cout << "Sum=" << total << endl;

    return 0;
}

Parameter List

  • We must have parenthesis after a function name
  • Inside the parenthesis, we define a list of zero or more parameters
  • Parameters are the inputs to a function
  • In our example, we have two parameters inside the parenthesis
    int add(int a, int b)
    
  • Parameters are the declaration of a new variable, even though they are declared inside parenthesis
  • Each parameter must have both a type and a name, just like a regular variable
  • If we have more than one parameter, we separate them with commas
  • Any parameter that we declare must be given an argument when we call the function
  • In the following image, the value of arguments num1 and num2 are copied to the parameters a and b

Passing Arguments to Function Parameters

Passing arguments in a function call

Arguments and Parameters

  • Depending on our background, we might use the term arguments or parameters for the values passed to functions
  • The terminology is not that important
  • However, the way I will use the terms is:
    • A function definition has parameters
      int add(int a, int b) { // a and b are parameters
          // ...
      }
      
    • A function call passes arguments
      add(num1, num2); // num1 and num2 are arguments
      
  • Arguments are values we pass into functions
  • When the argument drops into a function, it lands in a parameter
  • A parameter is just like other variables in the function
    • Except that a parameter gets initialized by an argument
  • The important part is:

    We must pass every function parameter an argument.

  • The arguments must be in the same order as the parameters
  • Also, the argument value must be compatible with the type of the parameter
  • For example, we cannot call add() with: add("Ed", "Parrish")

Check Yourself

  1. To received input, a function has __________.
  2. Parameters are set on the first line of a function inside a set of __________
    1. Curly braces -- { }
    2. Parenthesis -- ( )
    3. Square brackets -- [ ]
    4. Colons -- : :
  3. True or false: like any other variable, a function parameter has both a type and a name.
  4. If a function has three parameters, a function call must include ________ arguments.
  5. For the following function signature, the parameter names are __________
    int add(int a, int b)
    
    1. a
    2. b
    3. both a and b
    4. cannot tell from the function signature
  6. The following code snippet prints ________.
    int addTwo(int x) {
      return x + 2;
    }
    int main() {
      int x = addTwo(40);
      cout << x << endl;
      return 0;
    }
    

7.4.4: Variable and Parameter Scope

  • 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.

  • Parameters are a local variable and thus can only be used inside the function in which they are declared as well
  • As an example of a local variable, we declared sum inside the add() function:
    int sum = a + b;
    
  • In addition, we declared another variable named total inside main():
    int total = add(num1, num2);
    
  • These variables cannot be accessed outside the function they were declared within

Scope

  • 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

  • Because of scope, we can use variables with the same name in different functions
  • To send information to a function we must include a parameters:
    int add(int a, int b)
    
  • When the function call is made, we send the arguments to the parameters:
    add(num1, num2)
    
  • The values of num1 and num2 are copied to the parameter variables a and b

Example of Scope

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 display(int a) {
    cout << a << endl; // What will this print?
    int x = 42;
    cout << x << endl; // What will this print?

    return 0;
}

int main() {
    int x = 7;
    cout << x << endl; // prints 7
    x = 11;
    cout << x << endl; // prints 11
    display(x);
    cout << x << endl; // What will this print?

    return 0;
}

Check Yourself

  1. A variable that can be used only within the function in which it was declared is known as a __________ variable.
  2. True or false: parameters are local variables.
  3. The area of a program within which a variable exists is known as its ________.
  4. The following code snippet prints ________.
    int myFun(int a) {
      int x = 12;
      a = x;
      a = a + 3;
      return 0;
    }
    int main() {
      int x = 42;
      myFun(x);
      cout << x << endl;
    
      return 0;
    }
    
    1. 12
    2. 15
    3. 42
    4. 45

7.4.5: Returning a Value

  • The first word in the function signature is the return type
    int add(int a, int b)
    
  • The return type specifies the type of data the function outputs
  • In our example the return type is an int

Return Statement

  • Functions that return a value must execute a return statement
    return result;
    
  • For instance, our example function add() has a return statement
    int add(int a, int b) {
        int sum = a + b;
        return sum;
    }
    
  • Note that the type of the returned valued must be compatible with the function return type
  • The returned value is substituted for the function call in the calling code
    sum =>[replaces]=> add(num1, num2)
    
  • We must save the returned value if we want to process it later in the program
    int total = add(num1, num2);
    

Returning a Value from a Function

Returning values from a function call

Returning an Expression

  • The value after the word return can be an expression
  • It does not have to be just the name of a variable
  • We could rewrite our return statement to the following:
    return a + b;
    

Multiple return Statments

  • We can have more than one return stattement in a function
  • The first return statement reached is the one executed
  • We might have multiple returns if we have if-statments with alternate actions, like:
    if (x > 400) {
        return 1;
    } else {
        return 0;
    }
    
  • We do not have alternate actions in our simple add function and so have only one return statement

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 compatible with the function return type.
  3. To correctly assign the result of a function named getSomething() to a variable named shopping, use __________.
    1. shopping = getSomething();
    2. shopping = getSomething;
    3. shopping(getSomething);
    4. shopping() = getSomething();
  4. The following code snippet prints ________.
    int get42() {
      return 42;
    }
    
    int main() {
      int x = get42() + 2;
      cout << x << endl;
      return 0;
    }
    

Exercise 7.4a: Writing a Function (8m)

In this exercise we define our own function.

Specifications

  1. Copy the following program into a text editor, save it as sub.cpp, and then compile and run the starter program to make sure you copied it correctly.
    #include <iostream>
    using namespace std;
    
    // Define function here
    
    int main() {
    
        return 0;
    }
    
  2. Write the signature for a function named sub that receives two int numbers and returns an int value, like we did for the add() function
    returnType sub(two_int_parameters)
    
  3. Add the curly braces for the function body: { }.
  4. Inside the function body, subtract the second parameter from the first and return the value, like we did for the add() function.
        int sum = a + b; // from add() function, CHANGE THIS!
        return sum;
    
  5. Compile and run your code. What do you see when you compile? (click here) Click to show answer
  6. Inside the main() function, enter these statements:
        cout << "Enter two numbers to subtract: ";
        int num1, num2;
        cin >> num1 >> num2;
        int diff = sub(num1, num2);
        cout << "Difference=" << diff << endl;
    

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

  7. Compile and run your modified program and verify the output looks like:
    Enter two numbers to subtract: 3 1
    Difference=2
    
  8. Save your sub.cpp file to submit to Canvas as part of assignment 7.

Completed Program

When finished, your application should look like the following.

Completed exercise

When finished, please help those around you.

7.4.6: Flow of Control for a Function Call

  • To use functions well, we must understand the flow of a program when calling functions
  • Every program starts executing in the main() function
  • When a program gets to a statement like the following, it stops executing in main() and jumps to our function:
    int total = add(num1, num2);
    
  • The program executes the statements in the function and then returns to the point in the code right after where it jumped
  • When the function returns, the returned value replaces the function call
  • After returning, the program completes processing the calling statement and then moves on to the next statement
  • In our example, the statement saves the returned value in the variable: total
  • 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 just after where it jumped

Function Call Flow

Flow of control for a function call
  1. Every program starts executing at the start of the function main().
  2. When reaching a function call, arguments are copied to the parameters.
  3. Function code executes until reaching a return statement.
  4. Return statement returns a value to the function call.
  5. Calling function continues after the function returns.

Check Yourself

  1. Every program starts executing at the start of the function __________.
  2. True or false: when reaching a function call, the currently executing function stops and control jumps to the start of the called function.
  3. True or false: the main() function continues executing when a function call returns.
  4. True or false: after a called function returns, control returns to the point in the code just after where it was called.

Exercise 7.4b: Tracing a Function Call (5m)

In this exercise we trace the function we developed in the last exercise.

Specifications

  1. Create a text file named trace.txt.
  2. In the trace.txt file, list the line numbers of each statement of your program from the last exercise in the order the lines are executed. For example, if main() starts on line 9, statements are executed as follows:
    9, 10, 11, 12, ...
    

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

  3. 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.
  4. Save the trace.txt to submit to Canvas as part of assignment 7.

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

7.4.7: 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
#include <iostream>
using namespace std;

int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    cout << "Enter two numbers to add: ";
    int num1, num2;
    cin >> num1 >> num2;
    int total = add(num1, num2);
    cout << "Sum=" << total << 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
      }
      
  • We can use either style as long as we are consistent
  • Also notice the indentation of the statements inside the function
  • As before, we always indent 3-4 more spaces after an opening curly brace
  • After the closing curly brace, we no longer indent the extra 3-4 spaces
  • Indenting makes it easier to see the block of code
  • In addition, function names always start with a lower case letter like variables
  • We can tell the difference between function and variable name because functions have parenthesis

Check Yourself

  1. True or false: always indent code within a function's curly braces.
  2. The number of spaces to indent is ________.
  3. Function names always start with a(n) ________ letter.
    1. camel case
    2. lowercase
    3. mixed case
    4. uppercase

7.4.8: Summary

  • As we add more code to main(), it becomes too long to easily understand
  • The solution is to break up the long sequences of code into shorter sections using functions

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

  • Creating functions is like adding new commands to the programming language
  • Functions allow us to organize code into short reusable pieces
  • We then assemble the parts to create larger programs

Defining Functions

  • To define a function, we use the following syntax:
    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 list of statements to execute when the function is called
  • As an example, we wrote the function add() which is called from main():
    int add(int a, int b) {
        int sum = a + b;
        return sum;
    }
    int main() {
        //... other code omitted
        int total = add(num1, num2);
        //... other code omitted
    }
    

Parameters

  • In the parenthesis of the function are the parameters
  • Parameters are the inputs to a function
  • 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 as shown below

Passing Arguments to Function Parameters

Passing arguments in a function call

Returning Values

  • The first word in the function signature is the return type
    int add(int a, int b)
    
  • The return type specifies the type of data the function outputs
  • When we want the function to return a value we write a return statement
    return sum;
    
  • The returned value gets substituted for the function call in the calling code
  • The flow of a function call is shown below

Function Call Flow

Flow of control for a function call

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

Wrap Up

Due Next:
A6-Loopy Programs (10/12/17)
A7-Programs With Functions (10/19/17)
  • 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.
Last Updated: October 14 2017 @00:14:02