CSC 306 Introduction to Programming with C++

Programmer Defined Functions

Chapter 3.3, 3.5


Objectives

Important Definitions


Creating New C++ Functions

So far we have used functions such as sin() and cos() that are built into C++, but it is also possible to create your own functions. Actually, we have all already created a C++ function definition, namely main(). The main() function is special because it indicates where the program execution begins, but the syntax used in the creation of main() is the same as for any other C++ function definition:
  returnType functionName ( listOfParameters ) {
    Statement 1;
    Statement 2;
    ...
    Statement Last;
  }
Here are the parts in more detail:
functionName You can make up any name you want for your function, as long as you follow the C++ identifier rules. Of course, you cannot call it main or any other C++ reserved word.
listOfParameters The list of parameters specifies what information, if any, you have to provide in order to call, which means use, the new function. When there are no parameters, this space is blank, such as is the case so far with the main() function. The first couple of functions we will write also have no parameters, so the syntax will be similar.
returnType Functions can return a value when they complete, and common data types of these values are int and double. The functions we will define initially will only perform actions and not return values, but you cannot simply ignore this part. These functions return a void type, which tells the compiler that nothing is returned.

Suppose we want to create a new function called newLine() that outputs a newline character into the output stream like the following:
void newLine() {
    cout << endl;
}
This function has no parameters so it does not take any arguments, and it does not return anything, so the return type is declared as void. It contains only a single statement that outputs the newline character.

In main, we can call this new function using syntax that is similar to the way we call the built-in C++ commands:
void main() {
    cout << "First Line." << endl;
    newLine();
    cout << "Second Line." << endl;
}
The output of this program is:
First line.

Second line.
Notice the extra space between the two lines. If we wanted more space between the lines, there are many options:

  1. We could call the same function repeatedly, in this case using a loop:
    void main() {
        int i = 0;
        cout << "First Line." << endl;
        while( i < 3 ) {
    	newLine();
    	i++;
        }
        cout << "Second Line." << endl;
    }
    
  2. We could create a second new function, named threeLine(), that prints three new lines calling the newLine() function. The main function then calls threeLine once instead of newLine() three times:
    // This function calls newLine() three times.
    void threeLine() {
        newLine();
        newLine();
        newLine();
    }
    
    void main() {
        cout << "First Line." << endl;
        threeLine();
        cout << "Second Line." << endl;
    }
    

Common Advantages of Defining Your Own Functions

There are many advantages of creating a function that is used in various points of your program:
  1. You can improve your code's readability by giving a name to a group of statements servicing a specific purpose.
  2. The program can be simpler by hiding a complex computation behind a single command, and by using an understandable function name in place of hard-to-read code. In this case, the name of the function, "newLine();", gives the intuitive idea of creating a newline, versus the statement "cout << endl;"?
  3. The program source code can be shorter by eliminating repetitive code. For example, a short way to print nine consecutive new lines is to call threeLine() 3 times.
  4. Once a function has been debugged and works correctly, one does not need to check it again when debugging the entire program.

Definitions and uses

Pulling together all the code fragments from the previous section, the entire program looks like this:
#include 
using namespace std;

void newLine() {
  cout << endl;
}

void threeLine() {
  newLine();
  newLine();
  newLine();
}

void main() {
  cout << "First Line." << endl;
  threeLine();
  cout << "Second Line." << endl;
}
This program contains three function definitions: newLine, threeLine, and main. The function definition describes what happens when the function is called and includes all of its statements to be executed. In the example above, the main() function performs a cout calls threeLine() and outputs more stuff before it ends. Similarly, threeLine() calls newLine() three times.

Notice that the definition of each function appears before the place where it is used. This is important and is like someone talking about a person named "Bob" before "Bob" was introduced...confusion can result. In C++, the definition of a function (or at least it's declaration--see the text) must appear before the first use of the function. You might try compiling this program with the functions in a different order and see what error messages you get.

Program Execution and Functions in the Source Code

When you look at a program that contains several functions, it is tempting to assume that the program executes in the same order as the functions appear in the source code. However, that is likely to be confusing because that is not in fact the order of execution of the program. Execution always begins at the first statement of main, regardless of where the function is located in the source code. In fact, main is at the bottom (rather counterintuitive). Statements in main are executed one at a time, in order, until you reach a function call, say to a function called submain. When a function is called, there is a detour in the flow of execution from main to submain, where the program then executes the entire set of statements of submain. When submain is done, the execution flow returns to the function that called submain, namely main, and continues from where it departed.

That sounds simple enough in theory, but recall that one function can call another, and this chaining of function calls can be arbitrarily long. Thus, if the flow of execute is done by hand, it can quickly become very complicated. While we are in the middle of main, we might have to go off and execute the statements in threeLine(). But while we are executing threeLine(), we get interrupted three times to go off and execute newLine(). Fortunately, computers are very good at keeping track of where the execution point is, so all the statements will run in the order that they are written, function calls and all.

Parameters and arguments

Some of the built-in functions we have used have formal parameters, which are values that you provide to the function to let the function do its job. For example, if you want to find the sine of a number, you have to indicate what the number is, which is usually a decimal number. Thus, sin() needs an input parameter of type double.

Some functions take more than one parameter, like the built-in function pow(), which takes two doubles, the base and the exponent. So, r = xy can be computed in C++ with r = pow(x, y).

Notice that in each of these cases we have to specify not only how many parameters there are, but also what type they are. So it shouldn't surprise you that when you write a function the parameter list indicates the type of each parameter. For example:

void printTwice(char letter) {
    cout << letter << letter << endl;
}
This function takes a single parameter, named letter, that has type char. Whatever that the value of the parameter is (and at this point we have no idea what it is), it gets printed twice, followed by a newline. The name you give a parameter is up to you.
WARNING: One common error is to assume that just because you give a variable a descriptive name, it somehow inherently has that quality about it. Naming a parameter as letter is as meaningful as giving it the name j5644ld.
This function is expecting a char data type, so we must provide a char when calling it. For example, the main function could be written as:
void main() {
    printTwice('a');
}
The char value you provide is called an argument, and we say that the argument is passed to the function. In this case, the value 'a' is passed as an argument to printTwice(...) where it will get printed twice.

Alternatively, if we had a variable of data type char, we could use it as an argument instead, as this version of main demonstrates:
void main() {
    char arg = 'b'; // declare and initialize argument with character 'b'
    printTwice( arg );
}
Notice something very important here: although the argument and the corresponding parameter in the function call is of the same type, the name of the variable we pass as an argument (arg) has nothing to do with the name of the parameter (letter). Again, this is because the memory location referenced by the identifier arg is different from that referenced by letter. In fact, it may be helpful to think that the parameter (which is a fancy way of saying its a variable used by a function) is assigned the value of the argument before the function starts---when printTwice is called, the value located in memory referenced by arg is copied to the location referenced by letter. The rule that the types of arguments and parameters are the same is important, but it is sometimes confusing because C++ sometimes converts arguments from one type to another automatically. For now you should learn the general rule, and we will deal with exceptions later.

Local Parameters

Parameters only exist inside the function can defines them, so are local to the function. In the example above, there is no definition of the variable letter within the confines of main, so if you try to use it, the compiler will flag an error. Similarly, inside printTwice(...) there is no such thing as the variable called argument. Whenever a function is called, it creates a new instance of that function. Finally, each instance of a function contains the parameters for that function.

Functions with multiple parameters

The syntax for declaring and invoking functions with multiple parameters is a common source of errors:
  1. You have to declare the type of every parameter. For example, suppose you have the following function:
    void printTime(int hour, int minute) {
        cout << hour;
        cout << ":";
        cout << minute;
    }
    
    It might be tempting to declare the function as void printTime(int hour, minute) because both parameters are of type integer, but that format is only legal for variable declarations, not for parameters.

  2. Another common source of confusion is that you do not have to declare the types of arguments when calling a function. The following is wrong!

        int hour = 11;
        int minute = 59;
        printTime(int hour, int minute);   // WRONG!
    
    In this case, the compiler can tell the type of hour and minute by looking at their declarations. It is unnecessary and in fact illegal to include the type when you pass them as arguments. The correct syntax is printTime(hour, minute).

Functions that return results

You might have noticed by now that some of the functions we are using, like the math functions, return results. Other functions, like newLine, perform an action but do not return a value.

Here is an example of a function that returns a value:

#include<iostream>
using namespace std;
	
/* FUNCTION TO COMPUTE INTEGER AVERAGE OF 2 INTEGERS AND RETURNS THE VALUE 
   AS A DOUBLE DATA TYPE */
double average(int first_number, int second_number) {
    return ((first_number + second_number) / 2.0);
}  
/* END OF FUNCTION */

	
/* MAIN PROGRAM: */
int main() {
    int numberA = 4, numberB = 3;      

    cout << "The integer average of " << numberA << " and ";
    cout << numberB << " is ";
    cout << average(numberA, numberB) << ".\n";

    return 0;
}
/* END OF MAIN PROGRAM */
Notice how the function is called right inside of the cout statement, so the program produces the following output:

	The integer average of 4 and 3 is 3.5.

More on Creating New Functions

Here's an example of a program which includes a user defined function called "area(...)".

#include<iostream>
using namespace std;

/* This program computes the area of a rectangle of given the length and width, 
   given as integers. */
	
/* FUNCTION TO CALCULATE AREA: */
int area(int length, int width)	{
    int number;
    number = length * width;
    return (number);
}
/* END OF FUNCTION */
	
/* MAIN PROGRAM: */
int main() {
    int this_length, this_width;      
	
    cout << "Enter the length: ";             /* <--- line 9 */
    cin >> this_length;
    cout << "Enter the width: ";
    cin >> this_width;
    cout << "\n";                             /* <--- line 13 */
	
    cout << "The area of a " << this_length << "x" << this_width;
    cout << " rectangle is " << area(this_length, this_width);
	
    return 0;
}
/* END OF MAIN PROGRAM */
An alternative way to accomplish the same task is to include the function declaration before main, but the function definition is written afterward. Unlike the definition, a function declaration simply describes how the function will be called and consists of the function name, parameters and return value.

#include<iostream>
using namespace std;

/* This program computes the area of a rectangle of given the length and width, 
   given as integers. */
	
int area(int length, int width);	/* <---- function declaration */
	
/* MAIN PROGRAM: */
int main() {
    int this_length, this_width;      
	
    cout << "Enter the length: ";             /* <--- line 9 */
    cin >> this_length;
    cout << "Enter the width: ";
    cin >> this_width;
    cout << "\n";                             /* <--- line 13 */
	
    cout << "The area of a " << this_length << "x" << this_width;
    cout << " rectangle is " << area(this_length, this_width);
	
    return 0;
}
/* END OF MAIN PROGRAM */
	
/* FUNCTION TO CALCULATE AREA: */
int area(int length, int width)	{   	/* <---- start of function definition */
    int number;
    number = length * width;
    return number;
}                                       /* <---- end of function definition */
/* END OF FUNCTION */


Lab Specifics

This lab must be completed individually.

Write a program in a file named YourLastName_306L2.cpp that uses functions to provide information about the temperature. The program should allow users to enter the temperature in either Fahrenheit or Celsius and then output the same temperature in both Fahrenheit and Celsius as well as information on the wind-chill and the heat index when it is relevant. From the perspective of the user, your program should do the following:

  1. First, welcome the user to the program.
  2. Ask users what kind of temperature they will input, allowing them to enter either 'f' or 'F' for Fahrenheit and 'c' or 'C' for Celsius. If the user enters any other character, they should be given a chance to re-enter the type of temperature.
  3. Allow the user to enter any real number for the temperature.
  4. Your program will output the temperature in both Celsius and Fahrenheit in easily readable format with 2 decimal places of accuracy.
  5. When the temperature is 50 F or below, it will also output the wind-chill factor. If the temperature is greater than 70 F, your program will output the heat index instead and display the following warnings:
    TemperatureWarning
    80 F <= temperature <= 90 F Fatigue possible with prolonged exposure and physical activity.
    90 F < temperature <= 105 F Sunstroke, heat cramps and heat exhaustion possible.
    105 F < temperature <= 130 F Sunstroke, heat cramps, and heat exhaustion likely, and heat stroke possible.
    130 F or greater Heat stroke highly likely with continued exposure.
    If you are interested in more information, look at the page: USA Today on humidity and heat index.
With regards to implementation, here are some more details: Be sure to: When you have completed your program and have it working to your satisfaction, drop the source code and your Microsoft Word Lab write-up YourLastName_306L2.doc into the CSC306_L02 dropbox on the Academic server.
Back to Introduction to Computer Programming with C++ Homepage