Activity 3-3 - Functions that return a value
                       Procedural Abstraction



We can write our own functions to perform some computations.  These type of functions are referred to as programmer-defined functions.  A programmer-defined function may have three parts: 1) Function definition, 2) Function Call, and/or 3) Function declaration.

The following program, which computes the total cost of purchases made in a store uses a function to compute the cost plus 5% sales tax of  purchases made.

// P33_1.cpp This program computes the total cost of purchases made,
//including 5% sales tax, on number_par items at a cost of price_par each.
#include <iostream>
using namespace std;

double total_cost(int number_par, double price_par); // (1) Function declaration

int main( )
{
        double price, bill;
        int number;

        cout << "Enter the number of items purchased: ";
        cin >> number;
        cout << "Enter the price per item $";
        cin >> price;

        bill = total_cost(number, price); // (2) Function call

        // The following three lines are used for formatting purposes.  Since a precision of 2
       //  is set, then all numbers will be displayed with two decimal points.  We work with $
       //  this seems to be the most appropriate way to display the numbers..
        cout.setf(ios::fixed);
        cout.setf(ios::showpoint);
        cout.precision(2);

        cout << number << " items at "
                 << "$" << price << " each.\n"
                 << "Final bill, including tax, is $" << bill
                 << endl;

        return 0;
}

// (3) Function definition
double total_cost(int number_par, double price_par)  // Function heading
{ // Function body begins here
        const double TAX_RATE = 0.05; //5% sales tax, const is to make sure this value stays unchanged
        double subtotal;

        subtotal = price_par * number_par;
        return (subtotal + subtotal*TAX_RATE);
}// Function body ends here

As you can see, we have used a function called total_cost to compute the cost + 5% tax.  Note that this function has computed the total cost and has returned a single value at return (subtotal + subtotal*TAX_RATE); The returned value is of type double.

Remarks
When you work with functions, there are at least 4 things that you must remember .

    1) A function must have a name, in the above program the function name was total_cost.
    2) A function must have a type, the type for the above function is double.
    3) A function must have correct argument definitions.  This means that the arguments, if any, must have type consistency and correct ordering at the:
                    a) function declaration, b) function call, and c) function definition.
    4) A function must have the correct return type. In our example, the function was of type double and it returns a value of type double.

Violation of any of these will result in syntax or logical errors.

Procedural Abstraction and Parameter Ordering
A function must be written like a black box.  The user does not need to have any knowledge of the details in the body of the function.  He/she should be able to determine what the function will do by looking at the function prototype and providing the correct input values with correct types to obtain the correct result from a function.

A function may have several arguments of different types.  It is critical that the parameters passed to a function have the same order at a) the function prototype, b) the function call, and c) the function definition.  Violation of the correct ordering may result in a) syntax error or b) logical error.  It is very hard to find the error when the ordering is incorrect.  So if you get an error when you are using a function, the first thing you may want to check is the type and ordering constancy in all instances of the function.

Scope of a variable
The scope of a variable declared inside a function is the body of that function.  For example, in the above program variable bill isdeclared inside the body of the main function.  Thus, bill is unknown in the total_cost function.  If we attempt to use bill without declaring it in the function total_cost, we will get a syntax error that bill is undeclared.  Similarly, variable subtotal is unknown to the main function, because it is a variable defined in the total_cost function and its scope is the body of the total_cost function only.  These types of variables are referred to as local variables.  They are local to the function in which they are declared.  There is, however, a method to define a variable such that it is known to all functions.  These types of variables are defined at the top of the program right after the include directives.  Any variable defined this way is known as global variable.

The parameters passed to a function are also local to the function within which they are defined.  Thus, a parameter that may go through changes inside a function that is called by another, will assume its original value upon the completion of the called function. This is referred to as call_by_value. The following example will help you understand all these definitions.

// P33_2.cpp This program illustrates the local and global variables and call-by-value.
// This program computes the side area and the cross section area of a cylinder
#include<iostream>
#include<cmath>
using namespace std;

double PI = 3.14159;  // This variable is defined globally, known to all functions in this program as PI

double cross_area(double r);  // Function prototype for function cross_area
double side_area(double r, double h);  // Function prototype for function Side_area

int main(void)
{
     double h, r;  //variables local to the main function

      cout << "Enter the radius and the height of the cylinder in Cm <Enter> ";
      cin >> r >> h;
      cout << endl;
      cout << "Before I do any computation or call any function, I want to let you know that \n";
      cout << "you have entered r = " << r << " and h = " << h << "." << endl;
      cout << "I am planning to use inch, thus in the first function, I will convert r, and " << endl;
      cout << "in the second one I will convert h \n";

      cout << "The cross section area of the cylinder is " << cross_area(r) << "  inch-sqr endl;
      cout << "The side area of the cylinder is " << side_area(r,h) << " inch-sqr \n\n";

      return 0;
}

double cross_area(double r)
{
     //Cross secion area includes the disks at the bottom and the top
      r = r * 0.3937;  // converting r to inch
      return 2*PI*pow(r,2);
}

double side_area(double r, double h)
{
      double area; //variable local to Side_area function
      h = h * 0.3937;  // converting h to inch
      area = 2*PI*r*h;
      return area;
}

In the above program, r and h are declared in the main function and are local to that function.  These two have been passed to the function side_area with the same names but they are still local to both functions regardless of their names. But, PI is defined globally and will be known to all the functions as PI.  If by any chance the value for PI changes in one of these functions, every function which is using PI will use it with its new value. That is why it is a good practice to define a variable that should remain unchanged througout the program as a global variable using a constant modifier,  const.

For example, in the above program, PI should be defined as:  const double PI = 3.14159;

Exercise 3.6
Copy or cut and paste program P33_2.cpp to a new program called ex36.cpp.  Compile and run the program for the following values:
r = 2 Cm, h = 10 Cm

The answer should be:
      The cross section area of the cylinder is 3.8955634 c
      The side area of the cylinder is 19.474819  inch-sqr

Did you get the same answer?  Explain the reason for such an error and fix the problem.

Exercise 3.7
Modify the ex36.cpp to include a new function called total_area, that computes the total suface area of a cylinder.  The total surface area is the sum of side area and cross section area.  Call your new program ex37.cpp.

For the above test values the total area must be:  23.370382 inch-sqr