Functions What is a function –“sub” program, with an isolated set of statements –Accepts parameters, returns a result (perhaps) –Think of it as its own little machine which is created and operated whenever it is requested Why we need functions? –Compartmentalize a long program into manageable parts: Better organization of code, encapsulation Use same code repeatedly, rather than repeating the same code –Each function acts as a building block
Functions How to declare a function return_type function_name(parameter_list) { Declarations; Statements; } Parameter-list format type1 variable_name1, type2 variable_name2,… typeN variable_nameN
Example Function Declaration Example: int main() { …;} double calcMax(double a,double b) {…;} Special cases –Use void for return_type if no value is to be returned. –Use void for parameter_list if no parameters are to be passed to the function
Using Functions How to return a value in a function –return; // for void return type –return ; // to return the value of // to the caller –In both cases, the next instruction executed is the instruction following the invocation of the function in the calling program/function How to call (invoke) a function –function_name(…); // as its own statement Or –function_name(…) may appear in an expression, where its value will be the value returned.
Example: Area Calculation double calcArea(double height, double width) { return height * width; } int main() { double h, w, area; printf(“Please input height and width\n”); scanf(“%f, %f”, &h, &w); area = calcArea(h, w); printf(“The area is %f”, area); return 0; }
Example – I Compute the square root of x Pseudo-code (Babylonian Method) 1.Set the value of guess to 1 2.If |guess 2 - x| <, proceed to step 4 3.Set a new value of guess to (guess + x/guess)/2 and repeat step 2 4.Return guess as the result
Example I – code float fabs(float x) {// this is really a if (x < 0.0) return -x;// standard library return x;// function in } float squareRoot(float x) { const float epsilon = ; // desired precision float guess = 1.0; while ( fabs(guess*guess - x) >= epsilon) { guess = (guess + x/guess) / 2.0; } return guess; }
Example – II Compute factorials double factorial(int n) { double result = 1; int i; for( i = 2; i <= n; i++) { result = result * i; } return result ; }
Example: factorials 5! = 5 * 4 * 3 * 2 * 1 –Notice that 5! = 5 * 4! 4! = 4 * 3!... –Can define factorials recursively –Solve base case (1! = 0! = 1) then plug in 2! = 2 * 1! = 2 * 1 = 2; 3! = 3 * 2! = 3 * 2 = 6; factorial(5) = 5 * factorial(4);
Example: factorials factorial(n) = n * factorial(n-1); double factorial(int n) { if ( n <= 1 ) return 1; // base case return n * factorial(n – 1); } Does this code work?
Local Variables – I What are local variables (also called automatic variables) –Variables declared within a function –Function parameters are also “local” Example: double calcMax(double a[10]) { int i; double maxValue; …; } int main() { int i; double a[10] double maxValue; maxValue = CalcMax(a) ; } Local variables
Local Variables – II Why use local variables? –To store temporary information –Values are private to current function –Can't be accessed by other functions Parameters are local variables! Every invocation of a function creates its own private set of local variables!
Recursive Function Call double factorial(int n) { if (n <= 1) return 1; return n*factorial(n–1); } double factorial(int n) { if (n <= 1) return 1; return n*factorial(n–1); } double factorial(int n) { if (n <= 1) return 1; return n*factorial(n–1); } double factorial(int n) { if (n <= 1) return 1; return n*factorial(n–1); } n=4n=3 n=2 n=1 return (4 * factorial(4 – 1));factorial( 3)); return (3 * factorial(3 – 1)); factorial( 2)); return (2 * factorial(2 – 1));factorial( 1)); return 1; 1); 2); 6);
Recursion Recursive functions –Functions that invoke themselves –Use when the solution can be defined in terms of itself –Three requirements for successful use of recursion: There must be an identifiable base case –Such as: factorial(1) == 1 There must be a recursive case –Such as: factorial(n) == n * factorial(n-1) There must be progress towards the base case –Such as: factorial(n) depends on factorial(n-1), with n-1 closer to the base case of 1, than n.
Example Implement function power(base, exponent) which returns base exponent –Recursive definition: base exponent = base * base exponent-1 –Base case: base 1 = base;
Code double power(double base, int exponent) { if (exponent == 1) return base; else return base * power(base, exponent-1); }
Possible Improvement double power(double base, int exponent) { if (exponent == 0) return 1; else if (exponent == 1) return base; else if (exponent % 2 != 0) return(base * power(base, exponent-1)); else { double temp; temp = power(base,exponent/2) return temp * temp; }
Fibonacci series Fibonacci series: 0, 1, 1, 2, 3, 5, 8... –Each number is the sum of the previous two –Can be defined and solved recursively: fib( n ) = fib( n - 1 ) + fib( n - 2 ) –Code for the fibonacci function int fib( int n ) { if (n == 0 || n == 1) // base case return n; else return(fib(n - 1) + fib(n - 2)); }
Arrays as parameters Pass entire array to a function –Example: int minimum(int values[ ], int numberOfElements) Only the location of array is passed to the function –Not the value of all elements in the array –Without a separate parameter, the function has no way of knowing the size of the array
Pass by Value Passing a copy of the value as an argument –Parameters receive a distinct copy of the caller's arguments, as if the parameters were assigned the values of the actual arguments –Changes made to the parameters have no effect on the caller’s arguments (because they are copies) Examples: h = 3; w = 4; area = calcArea(h, w); double CalcArea(double height, double width) { …; } height = 3, width = 4
Except Arrays Arrays are NOT passed by value! Arrays are passed by “reference” The location of the array is passed to a function –Code within the function may “refer” to the elements of the array (with an index) –Changes made to array elements change the original array!
Calculate the minimum value In a recursive way: –Base case: If only one number is in the array, the number is the minumum –Recursive Calculate the minimum value for the first half of the array Calculate the minimum value for the second half of the array smaller value of these two values is the minimum min
Code int minimum(int values[], int first, int last) { int middle; int v1, v2; if (first == last) return values[first]; else { middle = (first + last) / 2; v1 = minimum(values, first, middle); v2 = minimum(values, middle+1, last); if (v1 < v2) return v1; else return v2; }
Iterative Solution int minimum(int values[], int first, int last) { int i; int min; min = values[first]; for (i = first + 1; i <= last; i++) { if (values[i] < min) min = values[i]; } return min; }
Global Variables What is a global variable –A variable defined outside of any function –A global variables can be accessed by any function in a program Why use a global variable –avoid passing frequently-used variables continuously among many functions, How to define a global variable –Same as other variable declaration, except it is declared outside a function
Example int x; /* Global variable */ int y = 10; /* Initialized global variable */ int foo(int z) { int w; /* local variable */ x = 42; /* assign to a global variable */ w = 10; /* assign to a local variable */ return (x % y + z / w); }
Global Variables are Discouraged! Global variables are generally regarded as poor programming practice Why? –Destroys encapsulation and structure of programs –Harder to debug –Harder to reliably enhance –Someone looking at code which uses a global variable cannot be sure of all the other places the variable may be used or modified, requiring them to understand all the code in order to understand any part of it -- recipe for problems!