9. Functions continued

Review Topics


General Information

Housekeeping

  • Make sure you follow along with this page linked in Canvas
  • Please keep your microphone off unless you are asking a question
  • Please turn on camera if you can (optional)
  • Use chat if you would like to comment or ask questions

Announcements

See Announcements link in Canvas to keep up with what is going on. Here are a few other items:

  • Complete vaccinations required to visit campus or sign up for future terms (instructions)
  • Remember that PAs and the Individual Readiness Assurance Quiz are due before class on Tuesday.
  • Remember to post in the Pair programming partners discussion group if you need a partner
  • Remember that CAs and the exercises from this page are due Sunday at 9:00pm.
  • Remember that CAs, Labs, and Class Exercises may be completed up to two days late but with a 10%/day penalty.
  • Remember that some lab solutions are posted in Canvas Modules
  • Food & Housing Resources: free food, meals, temporary and permanent housing
  • COVID-19 Resources and Information: Includes loaner-laptop information
  • Campus WiFi Access
  • Extra credit bonus points for the first student to report a problem

Homework Help

9.1: Readiness Assessment Quizzes

  • Reading and participation activities are due before the first class meeting of the week
  • Quizzes assess the comprehension of the reading and participation activities

Quiz Part 1: Individual Readiness Assessment

  • Complete this quiz solo to assess your reading comprehension and readiness
  • Must take this quiz before the first class meeting of the week to ensure you are ready for the team quiz
  • Cannot take the quiz late
  • Quiz is open book and notes but timed
  • Highest score is counted so take the quiz multiple times

Quiz Part 2: Team Readiness Assessment (20m)

  • Must attend the class meeting to take this quiz
  • Login to Canvas and enter the access code
  • Will move to breakout rooms with your team
  • Make sure you have the access code for the exam
  • Openly discuss what you believe to be the best answers for the questions
  • Decide how to agree on the answers
    • Strive to reach a consensus on quiz answers
    • If no consensus, work it out as you and others in your group see fit
  • Turn in the quiz as a group
  • Each group member will receive the same score
  • Return to the main meeting room when finished

Quiz Appeals

  • After completing the team quiz, team members may appeal an answer
  • Appeals can be based on two criteria:
    1. Question is factually wrong

      Appeal must included citations to sources of information that document or support an alternative answer. Team may access reference materials during the appeal.

    2. Question is confusing based on it's wording

      Appeal must include an appropriate rewrite of questions or answers that you interpret as ambiguous or confusing.

  • Work with teammates to develop and write any appeals
  • Team has up to 24 hours after the quiz to email appeal to instructor
  • If appeal is granted, only the teams that submitted appeal gets credit

9.2: Pass by Reference

We look more closely at how values are passed to functions.

9.2.1: Reviewing Pass by Reference

  • C++ supports two ways to pass arguments to parameters:
  • Value parameters are copied and thus independent from variables of the calling function
  • Modification of value parameters does not affect the corresponding argument
  • The following example program uses value parameters
  • What does this program output? (Replit)

Example of Value Parameters

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

int mystery(int param) {
    cout << "param=" << param << endl;
    param = param * 2;
    return 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;
}

Implementing Pass by Reference

  • Remember that variables are names for memory addresses in a computer

    Memory variables and addresses

  • Pass by reference sends to the function the memory address of the variable instead of the value of the variable
  • 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
#include <iostream>
using namespace std;

int mystery(int& param) {
    cout << "param=" << param << endl;
    param = param * 2;
    return 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;
}
  • Call-by-references works differently than call-by-value
  • A reference parameter does not create a new variable, but uses the caller's argument variable instead
  • Any value change in a reference parameter is actually a change in the argument variable to which it refers
  • Because a reference parameter relies on the argument variable, the function call must provide a variable
  • The call-by-reference function call cannot use not literal values or other constants

Comparing Call-by-Reference vs Call-by-Value

  • Call-by-value is like calling on a phone to get something done
  • Call-by-reference is like going somewhere to get something done
  • When you return from somewhere you can bring something back like a cup of coffee
  • The following animation shows the effect of call-by-reference versus call-by-value
  • Think of the coffee in the cup as the data in a variable
  • Call-by-reference goes to the function with the cup and brings back the cup of coffee
  • Call-by-value is like making a phone call asking someone to fill a cup with coffee
  • As the coffee cup gets filled in fillCup(), the contents of the cup in the calling function is different
call-by-reference vs. call-by-value
Image source: penjee.com

Another Call-by-Reference versus Call-by-Value Analogy

  • Here is a URL to a web page: www.edparrish.net
  • If I tell you the URL, I'm passing by reference
  • You can use that URL to see the same web page I can see
  • If that page is changed, we both see the changes
  • If you delete the URL, you are destroying your reference to that page and not the actual page itself
  • If I take a picture and send the image to you, I'm passing by value
  • Your image is a disconnected copy of the original
  • You will not see any subsequent changes made
  • Also, any changes you make, like marking on the image, will not show up on the original page
  • If you delete the image, you destroy your copy of the object
  • The original web page remains intact

Mixed Parameter Lists

  • We can mix value and reference parameters in a function, like:
    void mixedCall(int& par1, int par2, double& par3);
    

When to Use Reference Parameters

  • Pass by reference parameters should be used sparingly
  • We typically use reference parameters when:
    • We pass a large object like a long string or vector to a function
    • We need to return more than one value

Exercise 9.2: Coding Pass by Reference (5m)

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

For this exercise we break into teams. Within the team, work with each other to develop a solution. When the team has finished, choose one member to show your solution to the class by sharing your screen. The instructor will ask one team to share their solution.

Specifications

  1. Start Replit and copy the following code into the code editor.
    #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 your code to make sure you added the code correctly.

    When you run the program, the output should look like:

    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 has no effect on num1 and num2. For more information, see section: 8.3.1: Parameter Passing and Value Parameters.

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

    Program using pass by reference

    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. For more information, see section: 8.3.2: Using Reference Parameters.

  5. Once satisfied with your code, copy it into a text editor, save the file as "swap.cpp", and submit the file to Canvas with the rest of the exercise files for the week.

When finished developing your code click hereClick to show answer to verify. Code need not look exactly the same. After you have completed your own program, reviewing another is often helpful in learning how to improve your programming skills.

9.3: Functions with Vector Parameters

We may write functions to work with vector parameters.

9.3.1: Reviewing Functions with Vector Parameters

  • By writing a function we gain the benefits of a modular design including:
    • Making main() easier to read and understand
    • Modular development to allow reuse of functions
    • Incremental development where the functions can be written and tested separately from the rest of the program
    • Avoiding redundant code
  • One such function is displaying the elements of a vector to the screen
  • The following example shows a print() function with a vector parameter

Example Code

#include <iostream>
#include <vector>
using namespace std;

/**
   Prints all the elements in a vector to the console.

   @param data the vector to print.
*/
void print(vector<int> data) {
    for (unsigned i = 0; i < data.size(); i++) {
        cout << data.at(i) << " ";
    }
    cout << endl;
}

int main() {
    const int SIZE = 20;
    const int MAX_NUM = 100;

    srand(time(0));
    vector<int> test(SIZE);
    for (unsigned i = 0; i < test.size(); i++) {
        test.at(i) = 1 + rand() % MAX_NUM;
    }
    print(test);

    return 0;
}

Linear Search

  • One useful function is to look for a particular value in a vector
  • An easy and straightforward approach is linear search (a.k.a. sequential search)
  • In linear search we:
    1. Start at the beginning of the list
    2. Compare each value in the list looking for matches:
      1. If the value is found, then return the index where the element was found
    3. If the search reaches the end of the list, return "not found"
Linear search animation
Image source: learndsa.com
  • Linear search is easy to implement using a loop and an if statement:
    int find(const vector<int>& data, int item) {
        for (unsigned i = 0; i < data.size(); i++) {
            if (item == data.at(i)) {
                return i;
            }
        }
        return -1; // Not found
    }
    

Removing an Element

  • Often, functions modify the vector contents such as removing an element from a list
  • If order does not matter then we can:
    1. Overwrite the element to be removed with the last element of the vector
    2. Shrink the size of the vector
  • However, if order matters then we must:
    1. Move all elements, after the one to remove, up towards 0 by one slot
    2. Shrink the size of the vector
  • The following diagram from the textbook shows this operation

    Move items down and reduce list size
  • We implement this operation using a loop:
    void erase(vector<int>& data, int pos) {
        for (unsigned i = pos; i < data.size() - 1; i++) {
            data.at(i) = data.at(i+1);
        }
        data.pop_back();
    }
    

Inserting an Element

  • In addition to removing items from a list, we often need to insert elements
  • We can either add elements to the end of a list or in the middle
  • If we add items to the end, we may just call the push_back() function of the vector:
    data.push_back(item);
  • However, if we want to insert an item in the middle of a list we must:
    1. Add a new element at the end of the vector
    2. Copy elements down towards the end by one index from the end of the list to the insertion index
    3. Assign the new value at the insertion index
  • The following diagram from the textbook shows this operation

    Add new element and move items up
  • We implement this operation using a loop:
    void insert(vector<int>& data, int pos, int value) {
        int last = data.size() - 1;        // last element value
        data.push_back(data.at(last));     // Make space at end
        for (int i = last; i > pos; i--) { // loop from end to pos - 1
            data.at(i) = data.at(i - 1);   // copy toward end
        }
        data.at(pos) = value; // Element to be inserted
    }
    

Exercise 9.3: Coding Functions with Vector Parameters (20m)

In this exercise we explore how to code vector algorithms.

Remember to verify your code by compiling after each step.

For this exercise we break into teams. Within the team, work with each other to develop a solution. When the team has finished, choose one member to show your solution to the class by sharing your screen. The instructor will ask one team to share their solution.

Specifications

  1. Download the starter code and save it to a convenient location like the Desktop.

    algorithms.cpp

  2. Open your code in a text editor and copy it to the code editor of Replit
  3. Compile and run your program to make sure you do not have any errors so far. When run you should see output like:
    Vector Algorithms
    
    Vector data:
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 0
    
    Goodbye!
    

    Notice the menu provided and how the menu is implemented in code with a loop and if-statements. When entering a 0, as shown in aqua italics above (for emphasis), the program should exit.

  4. Add the following print() function to the starter code after main().
    void print(vector<int> data) {
        for (unsigned i = 0; i < data.size(); i++) {
            cout << data.at(i) << " ";
        }
        cout << endl;
    }
    
  5. Uncomment the call to print() in the main() function and then compile and run your program to test the changes you made. When run you should see output like:
    Vector Algorithms
    
    Vector data: 5 7 4 2 8 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 0
    
    Goodbye!
    

    Notice the list of numbers printed, which are the numbers stored in the vector.

  6. Add the find() function to the starter code:
    int find(const vector<int>& data, int item) {
        for (unsigned i = 0; i < data.size(); i++) {
            if (item == data.at(i)) {
                return i;
            }
        }
        return -1;
    }
    
  7. Uncomment the call to find() in the main() function and then compile and run your program to test the changes you made. When run you should see output like:
    Vector Algorithms
    
    Vector data: 5 7 4 2 8 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 1
    Enter the number to find: 8
    Found 8 at position 4.
    
    Vector data: 5 7 4 2 8 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 0
    
    Goodbye!
    

    Notice the position number (index) returned by the find() function.

  8. Add the following erase() function which deletes an element while maintaining order.
    void erase(vector<int>& data, int pos) {
        for (unsigned i = pos; i < data.size() - 1; i++) {
            data.at(i) = data.at(i + 1);
        }
        data.pop_back();
    }
    
  9. Uncomment the call to erase() in the main() function and then compile and run your program to test the changes you made. When run you should see output like:
    Vector Algorithms
    
    Vector data: 5 7 4 2 8 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 2
    Position to remove value: 2
    
    Vector data: 5 7 2 8 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 0
    
    Goodbye!
    

    Notice the number for the position (index) is now gone. In our example, the number 4 is gone from position 2.

  10. Add the following insert() function which inserts an element into the vector while maintaining order.
    void insert(vector<int>& data, int pos, int value) {
        int last = data.size() - 1;
        data.push_back(data.at(last));
        for (int i = last; i > pos; i--) {
            data.at(i) = data.at(i - 1);
        }
        data.at(pos) = value;
    }
    
  11. Uncomment the call to insert() in the main() function and then compile and run your program to test the changes you made. When run you should see output like:
    Vector Algorithms
    
    Vector data: 5 7 4 2 8 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 3
    Value to insert: 42
    Position to insert the value: 5
    
    Vector data: 5 7 4 2 8 42 6 1 9 0 3
    
    0. Exit program
    1. Find item
    2. Remove item
    3. Insert new item
    Choice (0-3): 0
    
    Goodbye!
    

    Notice the element for the position (index) is now gone.

  12. Once satisfied with your code, copy your code into a text editor, save the file as "algorithms.cpp", and submit the file to Canvas with the rest of the exercise files for the week.

When finished developing your code click hereClick to show answer to verify. Code need not look exactly the same. After you have completed your own program, reviewing another is often helpful in learning how to improve your programming skills.

9.4: Overloaded Functions

Sometimes the same word in a language can have multiple meanings--the word is overloaded by having multiple uses. An example might be washing items: "wash the clothes, wash the car". People understand the washing process from context. We do not say, "clothes_wash the clothes, car_wash the car". Similarly, C++ allows us to overload function names.

9.4.1: Reviewing Default Parameter Values

One way to overload a function names is default parameters.

  • Sometimes a function's last parameter (or last few) should be optional
  • A function call could then omit the last argument
  • Instead the function parameter can get a default value
  • Examples shown in ZyBook 9.6 Default parameter values
  • One important point is that function prototypes (declarations) contain default values
  • However, function definitions do not have default values if using a prototype
  • For example, the following will not compile
#include <iostream>
using namespace std;

// Prints a string and a number
void print(string str, double num = 0);

int main() {
    print("Hello", 42.0);
    print("Hello");

    return 0;
}

void print(string str, double num = 0) { // will not compile
   cout << "string: " << str << ", number: " << num << endl;
}
  • To make the code compile we remove the = 0 in the function definition
#include <iostream>
using namespace std;

// Prints a string and a number
void print(string str, double num = 0);

int main() {
    print("Hello", 42.0);
    print("Hello");

    return 0;
}

void print(string str, double num) { // will compile
   cout << "string: " << str << ", number: " << num << endl;
}

9.4.2: Reviewing Overloaded Functions

Another way to overload is have two or more functions with the same name. This is known as function name overloading, which is often shortened to function overloading.

  • Function overloading allows us to have more than one function with the same name
  • However, the parameter list must be different in the data type and sequence of parameters
  • For example, the following function declarations all have the same name but have different parameter lists:
    void print(int num);
    void print(double num);
    void print(string str);
    
  • The compiler decides which function to call based on the argument types
  • Assuming our program has the three print() functions above, the compiler calls the functions as follows:
    int main() {
        print(42);    // first
        print(42.0);  // second
        print('a');   // Which function does this call?
        print("abc"); // third
    
        return 0;
    }
    
  • Remember that the parameter list must be different for each function
  • For example:
    int print(int num);
    double print(int num);
    
  • These two functions are not allowed in the same scope as the parameter list is the same
  • Even though they have different return types, the two functions are not valid together
  • We can see and verify the call choices in the following example code

Example Code

#include <iostream>
using namespace std;

void print(int num);
void print(double num);
void print(string str);

int main() {
    print(42);    // first
    print(42.0);  // second
    print('a');   // Which function does this call? Why?
    print("abc"); // third

    return 0;
}

void print(int num) {
   cout << "int: " << num << endl;
}

void print(double num) {
   cout << "double: " << num << endl;
}

void print(string str) {
   cout << "string: " << str << endl;
}

Exercise 9.4: Coding Overloaded Functions (10m)

In this exercise we code overloaded functions.

For this exercise we break into teams. Within the team, work with each other to develop a solution. When the team has finished, choose one member to show your solution to the class by sharing your screen. The instructor will ask one team to share their solution.

Specifications

  1. Start Replit and copy the following code into the code editor.
    #include <iostream>
    using namespace std;
    
    // Prints a number and a string
    void print(double num, string str);
    
    // Prints a string and optional number
    void print(string str, double num = 0);
    
    int main() {
        // Enter your function calls here
    
        return 0;
    }
    
    // Define your functions here
    
  2. Add a function definition for each of the function prototypes.

    You may choose how to define your functions as long as each one prints both parameter values.

  3. Inside main(), add a statement to call each of the functions you defined, using any number or string you prefer.
  4. Compile your code to make sure it has correct syntax and expected output, which should look like:
    number: 42, string: Hello
    string: Hello, number: 42
    string: Hello, number: 0
    
  5. Once satisfied with your code, copy your code into a text editor, save the file as "overload.cpp", and submit the file to Canvas with the rest of the exercise files for the week.

When finished developing your code click hereClick to show answer to verify. Code need not look exactly the same. After you have completed your own program, reviewing another is often helpful in learning how to improve your programming skills.

9.5: Preprocessor, include and separate files

The preprocessor is a tool used during compiling to scan for lines starting with #, known as a number sign, hash symbol, or pound sign. These lines are not program statements but instead directs the preprocessor to modify the file in some way before compiling continues. One of the modifications is to include the contents of another file.

9.5.1: Reviewing preprocessor and include

  • When C++ source code gets translated into machine code, several steps occur before compiling
  • One of those steps runs a tool known as the preprocessor
  • The preprocessor scans the file from top to bottom looking for lines that begin with # (hash symbol) and end with a newline
  • Each such line is known as a preprocessor directive
  • Preprocessor directives are not program statements, but tell the preprocessor to modify the file in some way before compilation
  • The most commonly-used preprocessor directive is #include, known as an include directive
  • The #include tells the preprocessor to replace that line by the contents of a given filename
  • We have been using the #include directive since we started:
    #include <iostream>
  • It turns out we can include our own files into program files
  • Syntax:
    #include "myfile.h"
  • By convention, we use a .h suffix for any file that will be included in another file
  • The h is short for header, to indicate that the file is intended to be included at the top (or header) of other files

9.5.2: Separating files

  • In C++, each program must have exactly one main() function
  • To prevent the main file from becoming too large, we often separate code into various functions
  • We may go one step further and separate the functions into other files
  • The function headers (declarations) are placed in a header file with a .h extension
  • The function definitions are placed in an implementation file with a .cpp extension
  • Then any functions needed by main are added using the #include preprocessor directive
  • To demonstrate, we remove the main() function from last weeks example squarelog program as shown below
  • Notice that the two files are reconnected by the preprocessor directive
    #include "squarelog.h"
    
  • We can still compile using the same process we have been using

Multiple Files in Replit

  • To work with multiple files in Replit we need to sign up
  • If you do not want to sign up, then you need to install a compiler on your own computer

squarelog.h

#ifndef SQUARELOG_H
#define SQUARELOG_H

#include <iostream>
using namespace std;

const int ANSWER = 42;

// Returns the square of a number
double square(double number);

// Displays a message to the console
void log(string funName, double value);

#endif

squarelog.cpp

#include "squarelog.h"

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

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

main.cpp

#include <iostream>
using namespace std;
#include "squarelog.h"

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

    return 0;
}

#include Guards

  • Notice the use of:
    #ifndef SQUARELOG_H
    #define SQUARELOG_H
    
    ... (function prototypes)
    
    #endif
    
  • These are know as #include guards
  • We use these constructs to avoid the problem of double inclusion
  • Once a header files is included, the preprocessor checks if a unique value is defined
  • If the value is not defined, then it defines it and continues with the file
  • If the value is already defined elsewhere, the first ifndef fails and results in a blank file being included
  • We typically use a naming scheme of the FILENAME_H to define the #include guards

More Information

Exercise 9.5: Coding with #include (10m)

In this exercise we explore the use of separate compilation using include directives.

For this exercise we break into teams. Within the team, work with each other to develop a solution. When the team has finished, choose one member to show your solution to the class by sharing your screen. The instructor will ask one team to share their solution.

Specifications

  1. Start Replit and copy the following code into the code editor.
    #include <iostream>
    using namespace std;
    
    void print(int num);
    void print(double num);
    void print(string str);
    
    int main() {
        print(42);
        print(42.0);
        print('a');
        print("abc");
    
        return 0;
    }
    
    void print(int num) {
       cout << "int: " << num << endl;
    }
    
    void print(double num) {
       cout << "double: " << num << endl;
    }
    
    void print(string str) {
       cout << "string: " << str << endl;
    }
    
  2. Compile your code to make sure you copied it correctly. Run the code and verify you see:
    int: 42
    double: 42
    int: 97
    string: abc
    
  3. In replit.com, add a second file named print.h.
    1. Next to Files, click the page icon with a '+' sign on it.
    2. Type the file name in the box that appears underneath "Add file".

    Add file menu in replit.com

  4. Copy the include directives and the using command into the new file, and then move the function prototypes to the new file.
  5. Add the #include guards to the print.h file:
    #ifndef PRINT_H
    #define PRINT_H
    
    ... (function prototypes)
    
    #endif
    
  6. Inside the main file, add an include directive for the file print.h.
  7. Compile your code to make sure it has correct syntax. Run the code and verify you still see:
    int: 42
    double: 42
    int: 97
    string: abc
    
  8. Next, move the function definitions into a file named print.cpp, and add the #include directives. The file looks like:
    #include <iostream>
    #include "print.h"
    using namespace std;
    
    void print(int num) {
       cout << "int: " << num << endl;
    }
    
    void print(double num) {
       cout << "double: " << num << endl;
    }
    
    void print(string str) {
       cout << "string: " << str << endl;
    }
    
  9. Compile your code to make sure it has correct syntax. Run the code and verify you still see:
    int: 42
    double: 42
    int: 97
    string: abc
    
  10. Once satisfied with your code, copy your code into three separate text files: print.h, print.cpp, and main.cpp. Submit all three files to Canvas with the rest of the exercise files for the week.

When finished developing your code click hereClick to show answer to verify. Code need not look exactly the same. After you have completed your own program, reviewing another is often helpful in learning how to improve your programming skills.

9.6: Programming Style Requirements for Functions

Professional programmers have style requirements for functions.

9.6.1: Curly brace placement

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

Camel Case

9.6.2: Naming functions

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

9.6.3: Commenting functions

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

Example Code with Fully Commented Functions

#include <iostream>
using namespace std;

/**
    Returns the square of a number

    @param number The number to square
    @return the square of number
*/
double square(double number);

/**
    Displays a message to the console

    @param funName The name of the function
    @param value The value to display
*/
void log(string funName, double value);

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

    return 0;
}

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

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

Using Doxygen

More Information

Exercise 9.6: Styling code (10m)

In this exercise we format your code to an acceptable style.

For this exercise we break into teams. Within the team, work with each other to develop a solution. When the team has finished, choose one member to show your solution to the class by sharing your screen. The instructor will ask one team to share their solution.

Specifications

  1. Open the C++ online code formatter and copy the following code into the editor window:
    
    /**
        CS-11 Asn 6: Calculates the area of a circle and the volume of a sphere.
        @file sphere.cpp
        @author Ed Parrish
        @version 1.1 3/17/20
    */
    
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    const double PI = 3.14159;
    
    /**
        Returns the area of a circle with the specified radius.
        @param radius The radius of the circle.
        @return The area of the circle.
    */
    double area(double radius);
    
    /**
        Returns the volume of a sphere with the specified radius.
        @param radius The radius of the circle.
        @return The volume of the sphere.
    */
    double volume(double radius);
    
    // Controls operation of the program.
    int main(void) {
    double radius_of_both, area_of_circle, volume_of_sphere;
    
    cout << "Enter a radius to use for both a circle\n"
      << "and a sphere (in inches): ";
    cin >> radius_of_both;
    
    area_of_circle = area(radius_of_both);
    volume_of_sphere = volume(radius_of_both);
    
    cout << "Radius = " << radius_of_both << " inches\n"
      << "Area of circle = " << area_of_circle
      << " square inches\n"
      << "Volume of sphere = " << volume_of_sphere
      << " cubic inches\n";
    
    return 0;
    }
    
    // Returns the area of a circle with the specified radius.
    double area(double radius) {
    return (PI*pow(radius, 2));
    }
    
    // Returns the volume of a sphere with the specified radius.
    double volume(double radius) {
    return ((4.0/3.0)*PI *pow(radius,3));
    }
    
  2. Use Code Beautify C++ Formatter
  3. Once satisfied with your code, copy your code into a text editor, save the file as "formatted.cpp", and submit the file to Canvas with the rest of the exercise files for the week.

When finished developing your code click hereClick to show answer to verify. Code should quite similar to the example below, within the approved options.

Deliverables

For this week's exercises we are turning in these files:

Remember that when submitting multiple files to Canvas, you must submit all files in the same session. For instructions on submitting multiple files for an assignment see the Canvas guide on How do I upload a file as an assignment submission in Canvas? section: Submit Assignment.

Lab and Exam 2 Introductions

Here are a few tips on how to get started on the labs.

  • LAB 9a: Swapping variables
  • Lab 9b: Vector printing
  • LAB 9c: Ice Cream Menu
  • Exam Preparation
    • Exam 2 is Thursday 10/28 at start of class
    • The exam has multiple choice and short answer (~44%)
    • Majority of exam points based on three programming problems (~56%)
    • ZyLab 10 published to help prepare for the programming problems (45 pts)
      • Nine (9) problems at 5 points each
    • Practice exam also available to help prepare for all types of exam problems
    • Extra credit available for completing the practice exam perfectly including the code problems
    • No credit unless all questions are completed perfectly in one exam attempt
    • To claim the extra credit, you must verify the practice exam is 100% correct, including code, with the instructor during one of the following times:
      • Monday 10/25 @1:00pm Student hours (20 pts)
      • Tuesday 10/26 during class (15 pts)
      • Wednesday 10/27 @1:00pm Student hours (10 pts)
    • This extra credit is your best opportunity to catch up and recover points lost in prior assignments
Last Updated: November 01 2021 @02:27:23