==================================== Predefined Functions - Section 3.1 ==================================== Functions are small program parts that can be created separately from the rest of the program. Functions can be assembled to form large programs. Large programs are complicated projects that have to be "engineered." The engineering of software is, perhaps surprisingly, similar to the engineering of concrete objects, like large buildings or ships. Pieces of various kinds have to be constructed separately and then fit together precisely. Programs are designed to accept input and produce corresponding output. Functions are like small programs. They too are designed to accept input and produce corresponding output. The output of one function can be used as input by another function. Data can pass through a chain of "function calls". Each function contributes something further to the processing required. This is the idea of how functions "fit together" to make programs. C++ programmers often write functions. However many functions are available in predefined form in system libraries. For example the directive: #include <cmath> makes the following functions available to a C++ program: double sqrt(double) double pow (double base, double exponent) double fabs (double) double ceil (double) double floor (double) There are other examples listed on page 94 of Savitch As Savitch explains in section 3.1, we can "call" these functions to perform computations. EXAMPLES: theRoot = sqrt(9.0) ; /* illustrates that a function call can be embedded in an expression */ root_1 = (-b + sqrt( (b*b) - (4*a*c) ) ) / (2*a) ; lengthSide = sqrt (area) ; roundValue = floor(value + 0.5) ; fifthPower = pow (2.0, 5.0) ; The inputs to the functions are called arguments (some authors call these actual parameters). The value that the function returns becomes a part of the expression on the right hand side of the assignment statement. It contributes to the value that is placed into the variable whose name appears on the left side of the assignment statement. Expressions like floor(value + 0.5) or pow(2.0, 5.0) are called function calls or function invocations. They illustrate the syntax the programmer uses to command the function to return a value. A function call consists of the name of the function, followed by a parenthesized list of arguments - zero or more arguments. (Some functions don't require any arguments, like int rand(), which returns a 'random' number.) Multiple arguments have to be separated by commas, as in pow(2.0, 5.0) The concept of a function that returns a value is a lot like the concept of a mathematical function. However, C++ allows the concept of a function that does not return a value. These so-called void functions are really what are called procedures in other programming languages. A void function is basically just a sub-program that performs a sequence of actions. The exit function on page 94 is an example. It just causes the program to stop. It doesn't return a value. To make a call to a void function, you don't try to use it in an expression. You just write the call as a "free-standing" statement like this: exit(0) ; ============================================ Programmer-Defined Functions - Section 3.2 ============================================ Study example 3.5 (page 103) and make sure you know how everything works there. Remember: * the return statement causes the function call to terminate. * functions can have "side effects" - actions they take in addition to returning a value. * There is a rule that a function prototype or definition must appear in a program before any calls to the function. This is much like the rule that a variable must be declared before it is used. ============================================ Suggested Exercises ============================================ Exercise #14 on page 109: Write a boolean-valued function isDigit that inputs a character and returns true if the character is a digit, and false if not. Also: write a function upcase that inputs a character. If the input is a lowercase letter, the function returns the uppercase version of the letter. Otherwise it just returns the input. Change the program so it loops, processing characters until the user wants to stop. Write a program with a sorting function. The program inputs three integers and outputs them in sorted order. ============================================ ============================================ C++ allows "void functions" - they don't return a value, so their "side effects" are their only outputs - all that they produce. Example: /* This is a program that uses a void function to render some art */ #include <iostream> using namespace std; void makeBees (int howMany) ; int main (void) { makeBees(3) ; return 0 ; } void makeBees (int howMany) { cout << endl << endl ; int N ; for (N=0; N<howMany; N++) { cout << " \\ / " << endl ; cout << " \\ o ^ o / " << endl ; cout << " \\ ( ) / " << endl ; cout << " ____________(%%%%%%%)____________ " << endl ; cout << "( / / )%%%%%%%( \\ \\ )" << endl ; cout << "(___/___/__/ \\__\\___\\___)" << endl ; cout << " ( / /(%%%%%%%)\\ \\ ) " << endl ; cout << " (__/___/ (%%%%%%%) \\___\\__) " << endl ; cout << " /( )\\ " << endl ; cout << " / (%%%%%) \\ " << endl ; cout << " (%%%) " << endl ; cout << " ! " << endl ; cout << endl << endl ; } } ============================================ Remember: * It's OK to define a function without any arguments, for example: void askAgain() { cout << "Your input was not understood. Please try again: " ; } ============================================ Each function should have a function declaration comment that explains what the function does. Often a good way to do this is to give preconditions and postconditions. If done correctly, the reader will know how to use the function (correctly) just by reading the prototype and the function declaration - with no need to see the code for the function. ============================================ Example: write a prototype and function declaration comment for the predefined function "pow" ============================================ Scope Rules - Section 3.3 ============================================ Will this program compile? If so, what does it write on the screen? #include <iostream> using namespace std ; void my_test_function(void) ; int main () { int my_test_number = 0 ; cout << my_test_number << endl ; my_test_function() ; cout << my_test_number << endl ; return 0 ; } void my_test_function(void) { int my_test_number = 1; cout << my_test_number << endl; } Answer: It compiles OK. A variable declared inside a function is local to the function. Here there are two variables named "my_test_number." The scope of each variable is limited to the body of the function in which it is declared. The scope of each variable starts where it is declared and ends at the closing brace of the function body. Therefore the two variables have the same name but they are different variables. They are just as separate and different as they would be if they had different names. The output of the program is: 0 1 0 Each function outputs the value of its local variable. --------- Procedural Abstraction: Most of us know how to make a telephone call, but we don't understand how our phone works. It would be very inconvenient if we had to understand everything we use. This is the idea of procedural abstraction. --------- --------- Will *this* program compile? If so, what does it write on the screen? #include <iostream> using namespace std ; void my_test_function(void) ; /* global variable (not usually a good idea) */ int my_test_number = 0 ; int main () { cout << my_test_number << endl ; my_test_function() ; cout << my_test_number << endl ; return 0 ; } void my_test_function(void) { int my_test_number = 1; cout << my_test_number << endl; } Answer: 0 1 0 It compiles OK. The global variable my_test_number is in the scope of the main function. It would be in the scope of my_test_function(). However, because there is a local variable with the same name declared there, that local variable masks the global variable. Within my_test_function() a reference to my_test_number gives access to the local variable. --------- Scope Rules: * A global variable is one that is declared outside of any function body. (Remember that main() is a function too.) * The scope of a global variable starts at the point in the file where it is declared and extends to the end of the file. * The scope of a local variable starts where it is declared and extends to the end of the innermost block containing the declaration. * There is an exception to the previous two rules: The scope of a variable local to a block masks any variable with the same name that is declared outside the block. --------- Will *this* program compile? If so, what does it write on the screen? #include <iostream> using namespace std ; void my_test_function(void) ; /* global variable (not usually a good idea) */ int my_test_number = 0 ; int main () { int my_test_number = 1; cout << my_test_number << endl ; my_test_function() ; cout << my_test_number << endl ; return 0 ; } void my_test_function(void) { cout << my_test_number << endl; } Answer: 1 0 1 It compiles OK. Here the local declaration in main masks the global variable. The reference to my_test_number in my_test_function() accesses the global variable. --------- --------- Will *this* program compile? If so, what does it write on the screen? #include <iostream> using namespace std ; void my_test_function(void) ; int main () { int my_test_number = 1; cout << my_test_number << endl ; my_test_function() ; cout << my_test_number << endl ; return 0 ; } void my_test_function(void) { cout << my_test_number << endl; } Answer: This one does not compile. You get this error message: scope04.cpp:17: error: 'my_test_number' was not declared in this scope Line 17 is the second-to-last line of the program. The problem is that the scope of my_test_number is the body of the main function. There's no variable of that name in the scope of the body of my_test_function(). --------- ---------