Functions Course Code: CSC1102&1103 Dept. of Computer Science Faculty of Science and Technology Course Title: Introduction to Programming Lecturer No: 9.2 Week No: 10 Semester: Spring 2024-2025 Course Instructor: Mashiour Rahman, Associate Professor, mashiour@aiub.edu
2.
Lectures 9: Outline Functions Functions and Arrays Pointers as parameter Return Pointer Function Pointer Inline Function Recursive Functions Function Overloading
3.
Passing arrays asparameters A whole array can be one parameter in a function In the function declaration, you can then omit the specification of the number of elements contained in the formal parameter array. The compiler actually ignores this part of the declaration anyway; all the compiler is concerned with is the fact that an array is expected as an argument to the function and not how many elements are in it. Example: a function that returns the minimum value from an array given as parameter int minimum (int values[10]); We must modify the function definition if a different array size is needed ! int minimum (int values[]); Syntactically OK, but how will the function know the actual size of the array ?! int minimum (int values[], int numberOfElements);
4.
// Function tofind the minimum value in an array #include <iostream> using namespace std; int minimum (int values[10], int numberOfElements){ int minValue, i; minValue = values[0]; for ( i = 1; i < numberOfElements; ++i ) if ( values[i] < minValue ) minValue = values[i]; return minValue; } int main (void){ int array1[5] = { 157, -28, -37, 26, 10 }; int array2[7] = { 12, 45, 1, 10, 5, 3, 22 }; cout<<"array1 minimum: "<< minimum(array1, 5)<<endl; cout<<"array2 minimum: "<< minimum(array2, 7)<<endl; return 0; } int numberOfElements = sizeof(values); cout<<"array1 minimum: "<< minimum(array1) <<endl; cout<<"array2 minimum: "<< minimum(array2) <<endl; int values[ ]){ Example: Passing arrays as parameters OUTPUT: array1 minimum: - 37 array2 minimum: 1
5.
Array parameters arepassed by reference ! Parameters of non-array type: passed by copying values Parameters of array type: passed by reference The entire contents of the array is not copied into the formal parameter array. The function gets passed information describing where in the computer’s memory the original array is located i.e. the starting location of the array. That is why we only give the array name in the actual parameter. int array1[5] = { 157, -28, -37, 26, 10 }; minimum(array1); So, any changes made to the formal parameter array by the function are actually made to the original array passed to the function, and not to a copy of the array. This change remains in effect even after the function has completed execution and has returned to the calling function.
6.
Example: Array parametersare passed by reference ! #include <iostream> using namespace std; void multiplyBy2(float array[], int n){ int i; for ( i = 0; i < n; ++i ) array[i] *= 2; } int main(void){ float floatVals[4] = { 1.2f, -3.7f, 6.2f, 8.55f }; int i; cout << "nBefore Function:n"; for ( i = 0; i < 4; ++i ) cout << floatVals[i] << "t"; cout << endl; multiplyBy2(floatVals, 4); cout << "nAfter Function:n"; for ( i = 0; i < 4; ++i ) cout << floatVals[i] << "t"; cout << endl; OUTPUT: Before Function: 1.2 -3.7 6.2 8.55 After Function: 2.4 -7.4 12.4 17.1
7.
Pointers and FunctionArguments Recall that the C language passes arguments to functions by value. On exception are the arrays where we only give the array name in the actual parameter. Also, recall that the name of the array is a constant pointer which enables the called function to change the values of the array of the calling function. So, if we want the called function to alter a value of a variable in the calling function, we can use pointer in the parameter which will pass the location of the variable. /* interchange value of 2 variable */ void swap(int *x, int *y){ int temp = *x; *x = *y; *y = temp; } int main(void){ int a=3, b=5; cout<<"before: a="<< a <<", b="<< b <<endl; swap(&a, &b); cout<<"before: a="<< a <<", b="<< b <<endl; return 0; OUTPUT: Before: a=3, b=5 After: a=5, b=3 Main Memory 1000 2000 x = &a= y = &b= &1000 &2000 temp=3 3 5 5 3 *x=a = *y=b = a= b=
8.
Example: Arrays &Pointers as parameters void print1(int tab[], int N){ for(int i=0; i<N; i++) cout<< tab[i] <<" "; cout<<endl; } void print2(int tab[],int N){ for(int *ptr=tab; ptr<tab+N; ptr++) cout<< *ptr <<" "; cout<<endl; } void print3(int *tab,int N){ for(int *ptr=tab; ptr<tab+N; ptr++) cout<< *ptr <<" "; cout<<endl; } void print4(int *tab,int N){ for(int i=0; i<N; i++, tab++) cout<< *tab <<" "; cout<<endl; int main(void) { int a[5]={1,2,3,4,5}; print1(a,5); print2(a,5); print3(a,5); print4(a,5); return 0; } • The formal parameter can be declared as array or pointer ! • In the body of the function, the array elements can be accessed through indexes or pointers ! OUTPUT: 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
9.
Example: Arrays &Pointers as parameters /* strLength: return length of string s */ int strLength(char *s){ int n; for (n = 0; *s != '0'; s++) n++; return n; } char array[100]="Hello, world"; char *ptr="Hello, world"; cout<< strLength("Hello, world"); /* string constant */ cout<< strLength(array); /* char array[100]; */ cout<< strLength(ptr); /* char *ptr; */ The actual parameter can be declared as array or pointer !
10.
Pointer as returntype A pointer can be returned from a function. Allows the calling function to access and manipulate data of the called function. Useful to return large data structures (ex: array) that cannot be returned by value. Must be very careful about what/whose location is being returned Do not return Pointers to Local Variables as they go out of scope once the function exits, leading to undefined behavior if their addresses are returned. Use Static or Dynamic Allocation: Use static variables or dynamically allocate memory to ensure the pointer remains valid after the function returns. Free Dynamically Allocated Memory: Always free dynamically allocated memory to avoid memory leaks. Function Declaration While Returning Pointer dataType* functionName(argument/parameter){ // function body return ptr; }
11.
Example: Pointer asreturn type int main(){ int *p; p = fun1(); ShowIncrease(p, "fun1"); p = fun2(); ShowIncrease(p, "fun2"); delete p; p = fun3(); ShowIncrease(p, "fun3"); delete [] p; p = fun4(); ShowIncrease(p, "fun4"); return 0; } int* fun1(){ static int A = 10; return &A; } int* fun2(){ int *B = new int(20); // *B = 20 return B; } int* fun3(){ int *C = new int[5]; //array *C = 30; // C[0] = 30 return C; } int *fun4(){ int D = 40; return &D; } void ShowIncrease(int *q, char *f){ cout << f << "->" << *q << endl; (*q)++; cout << f< < "->" << *q << OUTPUT: fun1->10 fun1->11 fun2->20 fun2->21 fun3->30 fun3->31 fun4-> error main *p= fun1 A=10 fun2 B= fun3 C= fun4 D=40 30 *B=20 ShowIncrease(q, f) *q=p *f="fun1" *f="fun2" *f="fun3" *f="fun4" A=11 *B=21 31
12.
Function Pointer Pointersthat point to location of functions instead of variables. They are used to store the address/location of a function definition and can be used to call the function or pass it as an argument to another function. In the declaration a function pointer, along with the pointer name, the return type and parameter types of the function it points to need to be specified. The syntax is as follows: Example: rType (*functionPointer)(argument/parameter); int subtract(int a, int b){ return a - b; } int add(int a, int b){ return a + b; } int multiply(int a, int b){ return a * b; } void Show1(char *s, int r){ cout << s << r << endl; } void Show2(char *s, int (*f) (int,int)){ cout << s << f(15, 2) << endl; } int main() { int (*funPtr) (int, int); // Declaration funPtr = add;// Reference int r = funPtr(15, 2);// r=add(15,2) //Dereference and call the function cout << "Addition: " << r << endl; funPtr = subtract; r = funPtr(15, 2);//r=subtract(15,2) Show1("Subtract: ", r); Show1("Subtract: ", funPtr(15,2)); Show1("Multiply: ", OUTPUT: Addition: 17 Subtract: 13 Subtract: 13 Multiply: 30 Multiply: 30 Addition: 17
13.
When thefunction is short and fast, and when we expect the function to be invoked very often, it’s better (and more time effective) to write the function code at each invocation. A function compiled like this is called an inline function by putting the keyword inline before function header. Asks the compiler to copy code into program instead of making function call Reduce function-call overhead Compiler can ignore inline Good for small, often-used functions Inline functions #include<iostream> using namespace std; inline int Fun(int p){ return (p * 2); } int main(void) { int e = 1; e = Fun( e ); // e = 2 e = Fun( e ); // e = 4 e = Fun( e ); // e = 8 cout << e <<endl; return 0; }
14.
14 Recursive & Recurrence An object is recursive if it contains itself as part of it, or it is defined in terms of itself. Recurrence relation Mathematical Functions that defined by itself with one or more base cases – Factorial numbers: F1 = 1 (base case) Fn = Fn-1 x n (recurrence relation) Examples: Fibonacci numbers: F0 = 0 (base case 1) F1 = 1 (base case 2) Fn = Fn-1 + Fn-2 (recurrence relation) Examples: F4 = F3 + F2 F4 = F3 + F2 = F2 + F1 + F1 + F0 = F4 = F3 + F2 = F2 + F1 + F1 + F0 = F1 + F0 + 1 + 1 + 0 = F4 = F3 + F2 = F2 + F1 + F1 + F0 = F1 + F0 + 1 + 1 + 0 = 1 + 0+ 1 + 1 + 0 = F4 = F3 x 3 F4 = F3 x 3 = F2 x 2 x 3 = F4 = F3 x 3 = F2 x 2 x 3 = F1 x 1 x 2 x 3 = F4 = F3 x 3 = F2 x 2 x 3 = F1 x 1 x 2 x 3 = 1 x 1 x 2 x 3 F4 = F3 x 3 = F2 x 2 x 3 = F1 x 1 x 2 x 3 = 1 x 1 x 2 x 3 = 6 F4 = F3 + F2 = F2 + F1 + F1 + F0 = F1 + F0 + 1 + 1 + 0 = 1 + 0+ 1 + 1 + 0 = 3
15.
15 Recursion Functions Recursivefunctions Functions that call themselves Can only solve a base case If not base case Break problem into smaller problem(s) Launch new copy of function to work on the smaller problem (recursive call/recursive step) Slowly converges towards base case Function makes call to itself inside the return statement Eventually base case gets solved Answer works way back up, solves entire problem
16.
int main(){ // factorial(i ) and display result. for ( int i = 0; i <= 3; i++ ){ unsigned long f = factorial( i ); cout << i <<"! = "<< f <<endl; } OUTPUT: 0! = 1 1! = 1 2! = 2 3! = 6 Recursion Functions – Example 1 // recursive definition of function factorial unsigned long factorial( unsigned long n ) { if ( n <= 1 ) // base case return 1; else // recursive step return n * factorial(n-1); } STACK i=0; f=factorial(0) i=1; f=factorial(1) i=2; f=factorial(2) i=3; f=factorial(3) i=3; f=6 main() i=0; f=1 factorial(1) 1 i=1; f=1 factorial(0) factorial(1) factorial(2) 2 factorial(2) n=2; 2*factorial(1) n=2; 2*1 factorial(0) 1 factorial(1) 1 factorial(1) i=2; f=2 factorial(3) 6 factorial(3) n=3; 3*factorial(2) n=2; 2*1 factorial(2) factorial(1) factorial(1) 1 n=2; 2*factorial(1) factorial(2) 2 n=3; 3*2 main() factorial(1) factorial(2) factorial(3) factorial(0) 2*factorial(1 ) 3*factorial(2 ) 2*1 3*2 2*factorial(1 ) 2*1 1 2 6
17.
// recursive definitionof function fibonacci long fibonacci( long n ){ if ( n == 0 || n == 1 ) // base case return n; else // recursive step return fibonacci(n-1) + fibonacci(n–2); } int main(){ // fibonacci( i ) and display result. for ( int i = 0; i <= 5; i++ ) cout<<"Fibonacci("<<i<<") = "<<fibonacci(i)<<endl; return 0; } OUTPUT: Fibonacci(0) = 0 Fibonacci(1) = 1 Fibonacci(2) = 1 Fibonacci(3) = 2 Fibonacci(4) = 3 Fibonacci(5) = 5 Recursion Functions – Example 2
18.
// recursive definitionof function gcd int gcd( int u, int v ){ if ( v == 0 ) // base case return u; else // recursive step return gcd(v, (u%v)); } int main(){ cout<<"gcd(150, 35) = “ <<gcd(150, 35) <<endl; cout<<"gcd(1026, 405) = "<<gcd(1026, 405)<<endl; cout<<"gcd(83, 240) = “ <<gcd(83, 240) <<endl; return 0; } OUTPUT: Fibonacci(0) = 0 Fibonacci(1) = 1 Fibonacci(2) = 1 Fibonacci(3) = 2 Fibonacci(4) = 3 Fibonacci(5) = 5 Recursion Functions – Example 3
19.
19 Default Arguments Adefault argument is a value provided for one or more parameter in a function declaration that is automatically assigned by the compiler if no value is provided for those parameters in function call. If the value is passed for it, the default value is overwritten by the passed value. If a function is declared and defined separately, the default values must be in the declaration, not in definition. In a function with multiple parameters, default values must be provided from the rightmost parameter to the left. It means that if a parameter has a default argument, all parameters to its right must also have default values. Set defaults in function prototype int myFunction( int x , int y = 2, int z = 3 ); myFunction(3) x = 3, y and z get defaults (rightmost) myFunction(3, 5) x = 3, y = 5 and z gets default myFunction(3, 5, 7) x = 3, y = 5 and z = 7
20.
Variable number ofparameters #include <iostream> using namespace std; int calc3(int x, int y, int z) { return (x + y) / z; } int calc2(int x, int y) { return calc3(x, y, 1); } int calc1(int x) { return calc3(x, 10, 1); } int calc0(void) { return calc3(20, 10, 1); } int main(void) { cout << calc3( 30 , 20, 2 ) << endl; cout << calc2( 30 , 20 ) << endl; cout << calc1( 30 ) << endl; cout << calc0( ) << endl; return 0; }
21.
Default Parameters #include <iostream> usingnamespace std; int calc(int x = 20, int y = 10, int z = 1) { return (x + y) / z; } int main(void) { cout << calc( 30 , 20, 2 ) << endl; cout << calc( 30 , 20 ) << endl; cout << calc( 30 ) << endl; cout << calc( ) << endl; return 0; }
22.
22 Function Overloading Functionoverloading Functions with same name and different parameters Should perform similar tasks I.e., function to square ints and function to square floats int square(int x) { return x * x; } float square(float x) { return x * x; } Overloaded functions distinguished by signature Number of arguments Argument types Sequence of arguments Not by the return type of the function
23.
Functions with similartasks #include <iostream> using namespace std; int maximum_int(int x, int y) { return x > y ? x : y; } long maximum_long(long x, long y) { return x > y ? x : y; } double maximum_double(double x, double y) { return x > y ? x : y; } float maximum_float(float x, float y) { return x > y ? x : y; } int main(void) { cout << maximum_int( 1 , 2 ) << endl; cout << maximum_long( 1L , 2L ) << endl; cout << maximum_float( 1.1F , 2.1F ) << endl; cout << maximum_double( 1.1 , 2.1 ) << endl; return 0; }
24.
Function Overloading #include <iostream> usingnamespace std; int maximum(int x, int y) { return x > y ? x : y; } long maximum(long x, long y) { return x > y ? x : y; } double maximum(double x, double y) { return x > y ? x : y; } float maximum(float x, float y) { return x > y ? x : y; } int main(void) { cout << maximum( 1 , 2 ) << endl; cout << maximum( 1L , 2L ) << endl; cout << maximum( 1.1F , 2.1F ) << endl; cout << maximum( 1.1 , 2.1 ) << endl; return 0; }