Functions

Alright, let's start with the standard. Here are a few reasons why we care about functions.

  1. Functions allow you to organize your code by breaking large chunks into smaller pieces. This can really help with readability.
  2. Functions can prevent a lot of copy-pasting. For example, it's nice to be able to write fmax(a,b) instead of putting a few lines of if statements every time.
  3. Functions are portable. Often the same function is useful in many different problems. If you code it well once, it's easy to reuse the work.
  4. I always talk about solve long problems by breaking them up into small pieces. Functions are a great way to do this. See example 1 below.

Example 1:

Last time we wrote a program that finds the smallest number that is divisible by everything between 1 and 20. Below is an edited version of this program that performs the exact same steps, but the code is more organized.

#include<iostream>
using namespace std;

// This program finds the smallest number that is divisible by everything
// between 1 and divMax by testing each number, one at a time.
// It then outputs the result to the screen.

bool testDivide(int x, int divMax);

int main() {

    const int divMax = 20;
    
    int num = 0;
    bool isDivisible = false;
    
    do {
        num++;
        // Note the change here. We test if num is divisible using
        // the testDivide function.
        // The code is all the same, just reorganized.
        isDivisible = testDivide(num,divMax);
    } while( !isDivisible );

    cout << num << " is the smallest number that's divisible by everything between "
         << "1 and " << divMax << "." << endl;

    return 0;
}

// This function tests if x is divisible by everything between 1 and 20
// It will return either true or false
bool testDivide(int x, int divMax) {
    bool isDivisible = true;
    for(int i=2; i<=divMax; i++) {
        if( x % i != 0) {
            isDivisible = false;
            break;
        }
    }
    return isDivisible;
}

Example 2:

Here's another example where we use functions to increase readability, and to split up our code into smaller chunks. The dist function below has 4 integers as parameters, representing two points in 2D, and returns the distance between them.

/* This program inputs two points on the xy-plane (four integers), and outputs the distance between those points.
   You could change it to four doubles pretty easily if you'd like.
*/

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

/* This is the prototype of the function dist. It says that dist is a function that inputs four ints and returns a double.
We haven't yet defined what the dist function does. That occurs below.*/
double dist(int x1, int y1, int x2, int y2);

int main() {
    cout << "This program inputs two points in the xy-plane, and outputs the distance\n"
        << "between those points.\n\n"
        << "Please input four integers:\n";
    int a, b, c, d;
    cin >> a >> b >> c >> d;

    cout << "The distance between (" << a << ',' << b << ")"
        << " and (" << c << ',' << d << ") is " 
        << dist(a, b, c, d) << endl;
    // The code-segment "dist(a,b,c,d)" tells the program to run the dist function with x1=a, y1=b, x2=c, y2=d.
    
    return 0;
}

/* This is the definition of the function dist. Here we describe what the dist function actually does.
This particular function calculates distance by using the Pythagorean theorem*/
double dist(int x1, int y1, int x2, int y2) {
    return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
}

Parameter and return types

When you write your function, you decide what types of variable(s) it will input, and what type it will return. You can input any number of variables, with any arrangement of types. You can only output one thing, but it can be any type. See the following code-segments for examples:

// This function inputs a bool (and we call it x) and returns a bool.
bool notTrue(bool x) {
    return !x;
}

// This function doesn't input anything, and returns an int.
int alwaysReturnsThree() {
    return 3;
}

// This function inputs an int, and doesn't return anything   (this is what 'void' means)
void printNumber(int r) {
    cout << r;
}

// This function inputs one double and one int, and returns an int
int divide(double x, int y) {
    return (int)(x/y);
}

Practice Problems

Each problem below gives a skeleton of a program. The program will have a finished main routine, but one or more functions will not be implemented. Without changing the code in the main routine, edit the functions so that the program will run as intended.

I think you should be able to solve all these problems without #include-ing any more libraries, but if you feel like you need to include something then go ahead.

Example Problem:

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

// INSERT PROTOTYPE FOR THE dist FUNCTION HERE.

int main() {
    cout << "This program inputs two points in the xy-plane, and outputs the distance\n"
        << "between those points.\n\n"
        << "Please input four integers:\n";
    int a, b, c, d;
    cin >> a >> b >> c >> d;

    cout << "The distance between (" << a << ',' << b << ")"
        << " and (" << c << ',' << d << ") is " 
        << dist(a, b, c, d) << endl;
    return 0;
}

//INSERT DEFINITION FOR THE dist FUNCTION HERE.


My answer to this problem is shown above. I would put:

//Prototype
double dist(double x1, double y1, double x2, double y2);

//Definition
double dist(double x1, double y1, double x2, double y2) {
    return sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2));
}

As always, there are many possible correct answers for each problem.

Problem 1:


/* This program should input a string, and print to the console the first half of the 
string. If the string contains an odd number of characters, then round down. */
#include<iostream>
#include<string>
using namespace std;

// INSERT PROTOTYPE FOR getHalf HERE

int main() {
    cout << "Please input a string:\n";
    string input;
    getline(cin,input);

    string output = getHalf(input);
    cout << output << '\n';

    return 0;
}

// INSERT DEFINITION FOR getHalf HERE

Problem 2:

/* This program should input 3 integers and check if they are in ascending order. If they are
    output "In order!". If not, output "Not in order!"
   Ex: 2,5,6 is in order. 3,3,4 is in order. 9,5,20 is not in order.
*/
#include<iostream>
using namespace std;

// INSERT PROTOTYPE FOR inOrder HERE

int main() {
    cout << "Please input 3 integers:\n";
    int a, b, c;
    cin >> a >> b >> c;
    if (inOrder(a, b, c))
        cout << "In order!\n";
    else
        cout << "Not in order!\n";
    return 0;
}

// INSERT DEFINITION FOR inOrder HERE

Problem 3:

// This program should input 3 integers and print their product to the console.

#include<iostream>
using namespace std;

// INSERT PROTOTYPE FOR printProd HERE

int main()
{
    int a, b, c;
    cout << "a = ";
    cin >> a;
    cout << "b = ";
    cin >> b;
    cout << "c = ";
    cin >> c;
    printProd(a, b, c);
    cout << endl;
}

// INSERT DEFINITION FOR printProd HERE

Scopes (again)

Similar to if statments and loops, when we work with functions we need to worry about the scopes of variables. The good news is there are no new rules. You can still figure out the scope of a variable by looking at the curly braces '{' and '}'.

#include <iostream>
using namespace std;

void example();

int main() {

    int a;

    if(true) {
        int b;
        // both a and b are in scope here, c is not
    }

    // a is in scope here, b and c are not
    
    return 0;
}

void example() {
    int c;
    // c is in scope here, a and b are not
}

As before, it is possible to use the same variable name in two different scopes. C++ will create two different variables. In the below example, there are two variables called a, but only one of them is in scope at a time (there is an a in the main method, and an a in the example function).

#include <iostream>
using namespace std;

void example();

int main () {

    int a = 4;
    example();

    cout << "a is " << a << endl;
    return 0;
}

void example() {
    int a = 7;
    cout << "a is " << a << endl;
}

More function problems

In the above problems I gave you guys most of the code and asked you to complete some bits. For these problems I'm asking you to write the entire program from scratch.

Problem 4:

Write a prototype and definition for a function called excite. This function should take one parameter of type string. It should add "!!!" to the end of the string and print the result to the console.

Problem 5:

Write a prototype and definition for a function that takes one input of type double. The function returns the character value 'P' if its input is positive and returns 'N' if its input is zero or negative. Also write a main method that will run a simple test of your function.