Welcome to Lesson 19!


Learning Objectives

By the end of today's class, you should know...

  • How do you write a void function?
  • How do you call a void function?
    • What is different about the way you call a void function vs a non void function?
  • What is the difference between pass by reference and pass by value?
  • How do you indicate a reference parameter?

Announcements

  • Midterm 2 Results:
    • As: 17 (6 100% scores!)
    • Bs: 9
    • Cs: 7
    • Ds: 3
    • Fs: 7
    • No Shows: 1
  • Hand back midterms in last 5 minutes of class
  • Quiz 7 on Thursday - functions, functions, functions
    • Writing functions - non void and void
    • Calling functions - non void and void
    • Write a prototype and comment given a function
    • Pass by reference vs Pass by value
  • Last Women in Computer Science Club meeting of the quarter
    • Tomorrow (Wednesday) 12:30-1:30pm
    • Location: ATC 202
    • Intel Speaker!
    • All are welcome to join
  • Lab 10 due Friday

Review Activity

With a partner, answer the following questions:


1. Write the below function:

Name: notString
  • It takes in one string parameter
  • It returns a new string where "not " has been added to the front.
  • However, if the string already begins with "not", it return the string unchanged.

2. Now, call the function, passing it the following values:


string result;

//call function below passing in "x"


cout << "Result of function call 1: " << result << endl;

//call function below passing in "not x"


cout << "Result of function call 2: " << result << endl;


3. Write the comment and prototype for the below function:

double mpg(double miles, double gallons)
{
    return miles / gallons;
}

4. What is the difference between cout and return?

Void Functions

  • Previously we looked at functions that returned one value
  • Functions returning a value use a return statement
    return result;
  • A function that returns no value is called a void function
  • In C++, void functions are defined like functions that return a value
  • However, the keyword void replaces the return type
  • For example, what do you notice that is different about the following?
    void displayDegrees(double degreeFarenheit) {
        double degreeCelsius = 5.0 / 9 * (degreeFarenheit - 32);
        cout << degreeFarenheit
             << " degrees Fahrenheit is equivalent to "
             << degreeCelsius << " degrees Celsius." << endl;
        return;
    }
    
  • There are only two differences between definitions for void functions and other functions:
    • void return type
    • return statement is optional and does not specify a value if used
  • If no return type is specified, the function returns after executing the last statement
  • Here is an example program using the void function shown above

Example Program With a void Function

#include <iostream>
using namespace std;

void displayDegrees(double degreeFarenheit);

int main() {
    double fTemperature;

    cout << "Enter a temperature in Fahrenheit: ";
    cin >> fTemperature;
    displayDegrees(fTemperature); //Notice function call without assigning result to variable

    return 0;
}

void displayDegrees(double degreeFarenheit) { double degreeCelsius = 5.0 / 9 * (degreeFarenheit - 32); cout << degreeFarenheit << " degrees Fahrenheit is equivalent to " << degreeCelsius << " degrees Celsius." << endl; return; }

When to Write void Functions

  • When we use a non-void function, we are asking a question
  • The function returns a value in response to our question
    cout << sqrt(9.0);
    
  • When we use a void function, we are giving the computer a command
    displayDegrees(212);
  • We do not expect or receive an answer


Common Errors With void Functions

  • Note that we cannot call a void function from a cout statement
  • For example, the following causes a compile error:
    cout << displayDegrees(fTemperature); // NO!
  • The reason is that a void functions does not return a value and cout has nothing to print
  • Similarly, we cannot call a void function in an assignment statement:
    double temp = displayDegrees(fTemperature); // NO!
  • There is nothing to assign to the variable temp

Activity 19.1: Printing Squares (10 pts)

  • Remember our programs that used nested for loops to print out shapes.
  • Let's write a similar program with a function that prints squares of different sizes for our user.
  • Open up Eclipse and create a new C++ file called squares.cpp.
  • Then, copy and paste the starter code into your file, save it and run it to make sure everything is working properly.
#include <iostream>
using namespace std;

//Your function goes here

int main() {
    int length;

    while (length != -1) {
        cout << "I will print squares for you!\n";
        cout << "Please enter the length of one side of the square or -1 to quit: ";
        cin >> length;
        //code to call function

    }
    cout << "Thanks for \"square\" dancing with me!" << endl;

    return 0;
}
  • Now, write a function that prints squares called printSquares(). Your function should take in an integer argument for the length of one side of the square and should return nothing.
  • Call your function inside the while loop so that it will print out a square given the user input for the length of a side.
  • Run the program again. Does it print out a square?
  • When you are finished, upload your squares.cpp file to Canvas.
  • The output of your program should look identical to the sample output below (except user input will vary).

Activity 19.2: Into the Void (10 pts)

  • Void functions are useful for printing out information in a particular format.
  • Let's consider dates and times.
  • In America, we use the 12 hour clock, but in Europe, the 24 hour clock is used. For example, in America, 8:30 at night is represented as 8:30pm, while in Europe, it is represented as 20:30.
  • In America, we write dates in this format MM-DD-YYYY. In Europe, dates are often written as DD.MM.YYYY
  • Let's write a program that uses void functions to format dates and times.
  • We will print each date and time in both the American and European formats for our user.
  • Open up Eclipse and create a new C++ file named dateTime.cpp.
  • Copy and paste the starter code below into your file:
/*
* Name(s)
* Section info
*/
#include<iostream>
using namespace std;


//write prototypes here

int main() {
    int year;
    int day;
    int month;
    int hour;
    int minutes;
    string dayEve;

    cout << "Welcome! This program will print dates and times in both the American and European styles!\n\n";

    cout <<"First, let's print a formatted date.\n\n";
   
    cout << "Please enter the current year: ";
    cin >> year;
    cout << "Please enter the current month: ";
    cin >> month;
    cout << "Please enter the current day: ";
    cin >> day;
    cout << endl;
  
    //call to the formatDateAmerican function here
    //call to the formatDateEuropean function here
   
    cout << "\nNow, let's print a formatted time.\n\n";
   
    cout << "Please enter the current hour: ";
    cin >> hour;
    cout << "Please enter the current minutes: ";
    cin >> minutes;
    cout << "Please enter whether it is \"morning\" or \"evening\": ";
    cin >> dayEve;
    cout << endl;

   
    //call to the formatTimeAmerican function here
    //call to the formatTimeEuropean function here

    cout << "\nBye! See you another day!" << endl;

    return 0;
}
//write functions here


  • Now, you need to write four functions as follows:
formatDateAmerican
takes as input three integer parameter, one for the year, one for the month and one for the day
prints a formatted version of the date to the console, using the format m/d/yyyy
returns nothing
formatDateEuropean
takes as input three integer parameters, one for the year, one for the month and one for the day
prints a formatted version of the date to the console, using the format d.m.yyyy
returns nothing
formatTimeAmerican
takes as input two integer parameters, one for the hour, one for the minutes, and a string parameter that contains either "morning" or "evening"
prints a formatted version of the time to the console, using the format H:MMam or H:MMpm
returns nothing
formatTimeEuropean
takes as input two integer parameters, one for the hour, one for the minutes, and a string parameter that contains either "morning" or "evening"
prints a formatted version of the time to the console, using the 24 hour clock. Note that there is no am or pm in this format.
returns nothing

  • Upload your dateTime.cpp file to Canvas.

Your output should look identical the output below when you are finished:

Functions Calling Functions

  • Functions may call other functions
  • Within the body of one function, we can call another function call
  • Functions can call other functions as often as needed
  • We are already doing this when main() calls a function
  • The following program calls a "helper" function to help calculate the BMI.
  • Because calculating the BMI is a somewhat complicated process, it is helpful to create a second function to do part of the work for us.
  • The heightToSquareInches function handles turning the height from feet and inches (such as 5'8") into inches squared (such as 68"2).

Example of Functions Calling Functions


#include <iostream>
using namespace std;

double calculateBMI(int feet, int inches, double weight);
//Calculates a user's Body Mass Index

int convertFeetInches(int feet, int inches);
//Converts height in feet and inches to height in inches

int squareInches(int inches);
//Squares the height in inches

int main() {
    const double WEIGHT = 135.5;
    const int HEIGHT_FEET = 5;
    const int HEIGHT_INCHES = 8;
    double bmi = calculateBMI(HEIGHT_FEET, HEIGHT_INCHES, WEIGHT);
    cout << "Your BMI is: " << bmi << endl;

    return 0;
}

double calculateBMI(int feet, int inches, double weight) {
    int heightInches = convertFeetInches(feet,inches);
    int heightInches2 = squareInches(heightInches);
    double bmi = 703 * weight / heightInches2;
    return bmi;
}

int convertFeetInches(int feet, int inches) {
    return 12 * feet + inches;
}


int squareInches(int inches) {
    return inches * inches;
}


  • Functions may call other functions
  • Within the body of one function, we can call another function call
  • Functions can call other functions as often as needed
  • We are already doing this when main() calls a function
  • The following program calls a "helper" function to help calculate the BMI.
  • Because calculating the BMI is a somewhat complicated process, it is helpful to create a second function to do part of the work for us.
  • The heightToSquareInches function handles turning the height from feet and inches (such as 5'8") into inches squared (such as 68"2).

Example of Functions Calling Functions


#include <iostream>
using namespace std;

double calculateBMI(int feet, int inches, double weight);
//Calculates a user's Body Mass Index

int convertFeetInches(int feet, int inches);
//Converts height in feet and inches to height in inches

int squareInches(int inches);
//Squares the height in inches

int main() {
    const double WEIGHT = 135.5;
    const int HEIGHT_FEET = 5;
    const int HEIGHT_INCHES = 8;
    double bmi = calculateBMI(HEIGHT_FEET, HEIGHT_INCHES, WEIGHT);
    cout << "Your BMI is: " << bmi << endl;

    return 0;
}

double calculateBMI(int feet, int inches, double weight) {
    int heightInches = convertFeetInches(feet,inches);
    int heightInches2 = squareInches(heightInches);
    double bmi = 703 * weight / heightInches2;
    return bmi;
}

int convertFeetInches(int feet, int inches) {
    return 12 * feet + inches;
}


int squareInches(int inches) {
    return inches * inches;
}


Value Parameters

  • There are two ways to pass arguments to parameters
  • All our functions so far have used value parameters
  • Value parameters are separate variables from the ones in main() (or another calling function)
  • Modification of value parameters does not affect the original caller's value when the function returns

How Value Parameters Work

  • During the function call, your program copies the argument's value into the parameter variable
  • The scope of value parameters is the same as the scope for a local variable
  • If the parameter is assigned a new value, only the local copy changes
  • When the function returns, your program discards any value assigned to a parameter variable
  • The following example program uses value parameters
  • What does this program output?

Example of Value Parameters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#include <iostream>
using namespace std;
int mystery(int param);
int main() { int num = 2; cout << "At first, num=" << num << endl; int result = mystery(num); cout << "After calling, num=" << num << endl; cout << "And result=" << result << endl; return 0; }

int mystery(int param) {
    cout << "param=" << param << endl;
    param = param * 2;
    return param;
}


Reference Parameters

  • C++ has another parameter-passing mechanism known as call-by-reference
  • A reference parameter does not create a new variable, but refers to an existing variable instead
  • Any change in a reference parameter is actually a change in the variable to which it refers
  • We create a reference parameter by using an ampersand (&) between the parameter's type and name
    parameterType& parameterName
    
  • The following program shows an example of reference parameters
  • What is different?
  • What does this program output?

Example of Reference Parameters

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

#include <iostream>
using namespace std;

int mystery(int& param);
int main() { int num = 2; cout << "At first, num=" << num << endl; int result = mystery(num); cout << "After calling, num=" << num << endl; cout << "And result=" << result << endl; return 0; }
int mystery(int& param) {
    cout << "param=" << param << endl;
    param = param * 2;
    return param;
}
 

Call-By-Reference Details

  • What's really passed to the reference parameter?
  • A reference to the caller's original argument!
  • Essentially a reference parameter is another name for the original argument
  • With a reference parameter the code uses the original argument variable in calculations
  • Any change made to a reference parameter changes the original argument
  • Because C++ is passing variables, arguments for reference parameters must be variables and not constants



Mixed Parameter Lists

  • Parameter lists can include both value and reference parameters
  • As usual, the order of arguments in the list is critical
  • The following is a function signature with mixed parameter types:
    void mixedCall(int& par1, int par2, double& par3)
    
  • To call the function:
    int arg1 = 0, arg2 = 1;
    double arg3 = 2.2;
    mixedCall(arg1, arg2, arg3);
    
  • arg1 must be an integer type and is passed by reference
  • arg2 must be an integer type and is passed by value
  • arg3 must be a double type and is passed by reference

When to Use Reference Parameters

  • Reference parameters are usually more efficient than value parameters because they do not make copies of the parameters:
    • A program simply passes the memory address to the function
    • No new memory space is allocated and deallocated
  • Therefore, function calls using reference parameters usually operate faster
  • However, reference parameters restrict the arguments we can use for a function
  • Specifically, we must use a variable argument and not a literal or constant value
  • Usually, the best practice is to pass an object, like a String, by reference
  • Also, we should use value parameters unless a function needs to modify a parameter
  • The performance advantage of reference parameters for primitive types tends to be negligible
  • Thus, it is not worth restricting the call pattern of a function

Reference vs Value Video


Activity 19.3: Exploring Call by Reference (10 pts)

In this exercise we explore how call-by-reference parameters differ from call-by-value parameters.

Specifications

  1. Copy the following program into Eclipse and save it as swap.cpp:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    
    #include <iostream>
    using namespace std;
    
    void swap(int var1, int var2);
    
    int main() {
        int num1 = 0, num2 = 0;
        cout << "Enter two integers: ";
        cin >> num1 >> num2;
    
        swap(num1, num2);
    
        cout << "After calling function:  "
             << num1 << " " << num2 << endl;
        return 0;
    }
    
    void swap(int var1, int var2) {
        int temp = var1;
        var1 = var2;
        var2 = temp;
    }
    
  2. Compile and run the starter program to make sure you entered it correctly. When you run the program, the output should look like this:
    Enter two integers: 1 2
    After calling function: 1 2
    

    Notice that num1 and num2 have the same values before and after calling the function swap(). Any value assigned to var1 and var2 have no effect on num1 and num2.

  3. Change your program by adding the four ampersands (&) circled below:

    The ampersands tell C++ to use call-by-reference when passing parameter values.

  4. Compile and run the modified program to make sure you made the changes correctly. When you run the program, the output should look like this:
    Enter two integers: 1 2
    After calling function: 2 1
    

    Notice that num1 and num2 have different values before and after calling the function swap(). Any value assigned to var1 and var2 change num1 and num2 respectively.

  5. Submit your final program source code to Canvas.



Wrap Up

  • With your partner, answer the questions from today's learning objectives

Upcoming Assignments


~See You Thursday!~