Presentation is loading. Please wait.

Presentation is loading. Please wait.

Modular Programming Advantages of using functions (to make a modular program) are: Changing the program into separate pieces Code reusing Easier modification.

Similar presentations


Presentation on theme: "Modular Programming Advantages of using functions (to make a modular program) are: Changing the program into separate pieces Code reusing Easier modification."— Presentation transcript:

1 Modular Programming Advantages of using functions (to make a modular program) are: Changing the program into separate pieces Code reusing Easier modification and maintenance of the program More understandable program Functions can be called from anywhere in the main program with different input data Functions enable the programmers to generate their own libraries of the functions. How is the information exchanging between the main function and function subprograms?

2 Functions with input arguments
The arguments of the functions are used to carry information between the function subprogram and the main function Input arguments carry information into the function subprogram Output arguments are the return results of the functions Examples: c = factorial(n) / (factorial(r)*factorial(n-r)); print_rboxed(135.68); actual parameters

3 Calling print_rboxed(135.68)
/* * Displays a real number in a box. */ void print_rboxed(double rnum) { printf("***********\n"); printf("* *\n"); printf("* %7.2f *\n", rnum); } *********** * * * * Formal Parameter

4 /* * Computes n! for n greater than or equal to zero */ int indicates function result is an integer number factorial(int n) { int i, /* local variables */ product = 1; /* Computes the product n x (n-1) x (n-2) x ... x 2 x 1 */ for (i = n; i > 1; --i) { product *= i; } /* Returns function result */ return (product);

5 Functions with input arguments
The local and formal parameters of a function cannot be referenced by name in other functions Functions can not reference the variables defined in the main by the name Functions can use the constant names (#define ..) if they are in the same file. Also functions should have been defined after the constant names definition

6 function interface comment
Syntax of function definition function interface comment return-type function-name(formal parameter declaration list) { local variable declarations executable statements } Example: /* Finds the larger of two numbers */ double bigger(double n1, double n2) double larger; if (n1 > n2) larger=n1; else larger=n2; return(larger);

7 A function can be called with different actual parameters
A function can be called with different actual parameters. for example for finding the number of combinations of selecting 2 items from 6 items without regards to order main program calls factorial 3 times: c = factorial(6) / (factorial (2) * factorial(6-2); Calling factorial with n=6 in the main program int factorial(int n) value of 6 copies into n { int i, /* local variables */ product = 1; /* Computes the product n x (n-1) x (n-2) x ... x 2 x 1 */ for (i = n; i > 1; --i) { product *= i; } /* Returns function result */ return (product); Returns the result value of 720

8 Logical Functions The type int result by a function can be interpret as a logical value:
Function That Checks Whether a Value Is Even /* * Indicates whether or not num is even (divisible by 2): * returns 1 if it is, 0 if not */ int even(int num) { int ans; ans = ((num % 2) == 0); return (ans); }

9 Function with Multiple Arguments
/* * Multiplies its first argument by the power of 10 specified * by its second argument. */ double scale(double x, int n) { double scale_factor; /* local variable */ scale_factor = pow(10, n); return (x * scale_factor); } A function can be tested by a program (driver program) included main function and a call to that function

10 Testing Function scale
/* * Tests function scale. */ #include <math.h> /* Function prototype */ double scale(double x, int n); int main(void) { double num 1; int num 2; /* Get values for num 1 and num 2 */ printf("Enter a real number> "); scanf("%lf", &num 1); printf("Enter an integer> "); scanf("%d", &num 2); /* Call scale and display result. */ printf("Result of call to function scale is %.3f\n", scale(nu_m 1, num 2)); return (0); }

11 double scale(double x, int n) { double scale_factor; /* local variable - 10 to power n */ scale_factor = pow(10, n); return (x * scale_factor); } Output: Enter a real number> 2.5 Enter an integer> -2 Result of call to function scale is 0.025 After calling function scale in the main Function main data area Function scale data area num_1 = x=2.5 num_2= n=-2 scale_factor=?

12 Argument List Correspondence
The number of actual arguments in a call to a function must be the same as the number of formal arguments listed in the function definition The order of actual argument must be the same as the order of formal arguments Each actual argument must be of a data type that can be assigned to the corresponding formal parameter with no unexpected loss of information

13 Case Study with Top-Down Design
Problem: Write a program that finds the smallest divisor of a number or determines that the number is a prime number. Analysis Constant: NMAX 1000 Input: int n Output: int min_div

14 Design Algorithm: Get the number to check whether it is prime 1.1 Get a value for n 1.2 if n < 2 Display an error message else if n <= NMAX Do Step 2 and 3 else 2. Find smallest divisor other than 1, or determine number is prime 3. Display smallest divisor or a message number is prime 3.1 if the smallest divisor is n Display a message that n is prime Display the smallest divisor of n

15 #include <stdio.h>
#define NMAX 1000 Int main(void) { int n, /* ckeck for prime*/ min_div; /* minimum divisor */ /* Gets a number to test. */ printf("Enter a number that you think is a prime number> "); scanf("%d", &n); /* Checks that the number is in the range 2...NMAX */ if (n < 2) { printf("Error: number too small. The smallest prime is 2.\n"); } else if (n <= NMAX) { /* Finds the smallest divisor (> 1) of n */ min_div = find_div(n); /* Displays the smallest divisor or a message that n is prime. */ if (min_div == n) printf("%d is a prime number.\n", n); else printf("%d is the smallest divisor of %d.\n", min_div, n); } else { printf("Error: largest number accepted is %d.\n", NMAX); } return (0);

16 Step 2 as a sub-problem: Function find_div
Analysis Input (formal parameter) int n Output (result to return) int divisor Local variable int trial Design 1. if n is even, set divisor to 2, otherwise, set divisor to 0 and trial to 3 2. As long as divisor is 0, keep trying odd integers (trial). If a divisor is found, store it in divisor. If trial exceeds , store n in divisor. 3. Return divisor

17 #include <math.h>
/* Finds the smallest divisor of n between 2 and n (n is greater than 1) */ Int find_div(int n) { int trial, /* current candidate for smallest divisor of n */ divisor; /* smallest divisor of n; zero means divisor not yet found */ /* Chooses initialization of divisor and trial depends on n being even or odd. */ if (even(n)) { divisor = 2; } else { divisor = 0; trial = 3; } /* Tests each odd integer as a divisor of n until a divisor is found */ while (divisor == 0) { if (trial > sqrt(n)) divisor = n; else if ((n % trial) == 0) divisor = trial; else trial += 2; return (divisor); /* Returns problem output to calling module. */

18 Function Output Parameters with Pointers
So far the return part of a function ,at most could only return one result value. By using pointers functions can return multiple result values to the caller So far the input argument values could be passed only by the values. It means the value of actual parameters are copied into the value of formal parameters and call to the functions can not change value of arguments. By using pointers the address of the arguments can be passed to the functions and the value of these arguments can be changed by the functions. For example the second argument of the scanf or fscanf is passing by address when calling scanf of fscanf

19 Pointers A pointer is a variable whose value is the address of a memory cell that reserved for another variable For example: int *nump means nump is a pointer to another variable of type int: n nump Each pointer has two parts: 1- Direct value of a pointer, which is an address of a memory cell. For example nump is 1024 2- Indirect value of a pointer, which is the value of the memory cell whose address is the pointer’s direct value. For example *nump is 84 84 1024

20 Meaning of * Symbol “*” can be used for all of these purposes
Binary operator. For example: 2 * 3 means 2 times 3 For file pointer. For example FILE *inp; means inp is a pointer to file Definition of the pointers. For example: char *singp; means signp is of type “pointer to char”. Note that signp is address of a memory cell. 4. Unary operator. for example “*nump” gets 84 which is the int value and can be used in the expressions. Also “*singp” is a char value such as ‘a’ or ‘b’

21 Example of a function that uses arguments of the type of pointers
/*Separates a number into three parts: a sign (+, -, or blank), a whole number magnitude, and a fractional part.*/ void separate(double num, /* input - value to be split */ char *signp, /* output - sign of num */ int *wholep, /* output - whole number magnitude of num */ double *fracp) /* output - fractional part of num */ { double magnitude; /* local variable - magnitude of num */ /* Determines sign of num */ if (num < 0) *signp = '-'; else if (num == 0) *signp = ' '; else *signp = '+'; /* Finds magnitude of num (its absolute value) and separates it into whole and fractional parts */ magnitude = fabs(num); *wholep = floor(magnitude); *fracp = magnitude - *wholep; }

22 Example of a program that calls a function with multiple output arguments
/* Demonstrates the use of a function with input and output parameters.*/ #include <stdio.h> #include <math.h> void separate(double num, char *signp, int *wholep, double *fracp); int main(void) { prototype of separate double value; /* input - number to analyze */ char sn; /* output - sign of value */ int whl; /* output - whole number magnitude of value */ double fr; /* output - fractional part of value */ /* Gets data */ printf("Enter a value to analyze> "); scanf("%lf", &value); /* Separates data value into three parts */ separate(value, &sn, &whl, &fr); /* Prints results */ printf("Parts of %.4f\n sign: %c\n", value, sn); printf(" whole number magnitude: %d\n", whl); printf(" fractional part: %.4f\n", fr); return (0); } separate should be defined here…. Enter a value to analyze> Parts of sign: + whole number magnitude: 35 fractional part:

23 Side effect of function call separate(value, &sn, &whl,&fr)
Function main Function separate Data Area Data Area value value 35.817 35.817 sign sn 7421 ? Address of sn = &sn whl wholep 7422 ? fr fracp 7423 ? magnitude ?

24 More on Functions When a pointer is passed to a function it can be used as “output” or “input/output” parameter. Scope of the name refers to the region of a program where the name is visible For example scope of the formal and local variables, is from their declaration to the closing brace of a function in which they are declared The scope of predefine constants is the whole program (they are global) If the same name is repeated to declare the variable one of them may shadow another one. For example in the following example fun-two can be called by one, main and itself but function one can only ba called by main and itself not fun-two

25 void one(int anarg, double second); /* prototype 1 */
#define MAX 950 #define LIMIT 200 void one(int anarg, double second); /* prototype 1 */ int fun_two(int one, char anarg); /* prototype 2 */ int main(void) { int localvar; both of two functions one and fun_two can be called here . . . } /* end main */ void one(int anarg, double second) /* header 1 */ int onelocal; /* local */ function fun-two can be called here } /* end one */ fun_two(int one, char anarg) /* header 2 */ int localvar; /* local */ function one can not be called here } /* end fun_two */

26 Using formal parameters as actual parameters
void scan_fraction(int *nump, /* output - numerator */ int *denomp) /* output - denominator */ { char slash; /* local - character between numerator & denominator */ int status; /* status code returned by scanf indicating number of valid values obtained */ int error; /* flag indicating whether or not an error has been detected in current input */ char discard; /* unprocessed character from input line */ do { /* No errors detected yet */ error = 0; /* Get a fraction from the user */ status = scanf("%d%c%d", nump, &slash,denomp ); …………… } while (error); }

27 Recursive Functions A function that calls itself is said to be recursive Also if f1 calls f2 and f2 calls f1, f1 is considered as a recursive function A recursive algorithm has the following form: if this is a simple case solve it else redefine the problem using recursion For the simple case of the problem a straightforward, non-recursive solution is known

28 Recursive Functions For example to calculate the multiplication of 6 by 3 when only we allowed to use the addition operation: The simple case is multiplication of 6 by 1 And the recursive algorithm is: 1. Multiply 6 by 2. 1.1 Multiply 6 by simple case 1.2 Add 6 to the result 2. Add 6 to the result of problem 1

29 Recursive Functions /*
* Performs integer multiplication using + operator. * Assumes n > 0 */ int multiply(int m, int n) { int ans; if (n == 1) ans = m; /* simple case */ else ans = m + multiply(m, n - 1); /* recursive step */ return (ans); }

30 Tracing a recursive function
18 multiply (6,3) Tracing a recursive function m is 6 n is 3 3 == 1 is false ans is 6 + multiply(6, 2) return ans Each activation frame corresponding to each function call m is 6 n is 2 2 == 1 is false ans is 6 + multiply(6, 1) return ans 12 m is 6 n is 1 1 == 1 is true ans is 6 return ans 6

31 Local Variable and Parameter Stack of multiply(6,3)
ans Local Variable and Parameter Stack of multiply(6,3) 1 6 3 ? 6 2 ? 2 6 3 ? 6 1 ? m n ans 6 2 ? 3 6 3 ? 7 6 3 ? return from the third call 6 1 6 m n ans 4 6 2 ? 8 6 3 18 6 3 ? 6 2 ? return from the first call 5 6 3 ? 6 2 12 return from the second call 6 6 3 ?

32 Tracing a Recursive Function
int multiply(int m, int n) { int ans; printf("Entering multiply with m = %d, n = %d\n", m, n); if (n == 1) ans = m; /* simple case */ else ans = m + multiply(m, n - 1); /* recursive step */ printf("multiply(%d, %d) returning %d\n", m, n, ans); return (ans); } Entering multiply with m = 8, n = 3 Entering multiply with m = 8, n = 2 Entering multiply with m = 8, n = 1 multiply(8, 1) returning 8 multiply(8, 2) returning 16 multiply(8, 3) returning 24 printf is used to make a self-trace recursive function

33 Case Study: Bisection Method for Finding Roots
Problem: Develop a function bisect that approximates a root of a function f on an interval that contains an odd number of roots Analysis Input: double x_l, x_r; /* endpoints of interval */ double epsilon; /* error tolerance */ Output: double root; /* approximate root of f */ Variable: double x_mid; /*interval midpoint */

34 Design: Algorithm 1. if this is a simple case, solve it
1.1 simple case 1 if interval shorter than epsilon, return the midpoint 1.2 simple case 2 if function value at midpoint is zero, return midpoint else redefine the problem using recursion 1.3 bisect interval and execute a recursive call on the half interval that contains the root 1.3.1 if f(x_l)*f(x_mid)<0 1.3.2 Find the root by bisecting[x_l,x_mid] 1.3.3 Find the root by bisecting[x_mid, x_r]

35 Implementation: double
bisect(double x_l, /* input - endpoints of interval in which */ double x_r, /* to look for a root */ double epsilon) /* input - error tolerance */ { double root, /* approximate root */ x_mid; /* interval midpoint */ /* Compute midpoint of interval */ x_mid = (x_l + x_r) / 2.0; if (x_r - x_l < epsilon) /* simple case 1 */ root = x_mid; else if (f(x_mid) == 0.0) /* simple case 2 */ else if (f(x_l) * f(x_mid) < 0.0) /* root in [x_l, x_mid] */ root = bisect(x_l, x_mid, epsilon); else /* root in [x_mid, x_r] */ root = bisect(x_mid, x_r, epsilon); return (root); }

36 Case Study: Performing Arithmetic Operations on Common Fractions
Problem: Write a program that will allow you to add, subtract, multiply, and divide common fractions. The program will prompt you for a fraction, an operator, and another fraction and then display the problem and the result. The process will be repeated until you enter an n to answer the question, Continue? (y/n)

37 Analysis Input: int n1, d1; /* numerator, denominator of first fraction */ int n2, d2; /* second fraction */ char op; /* arithmetic operator + - * / */ char again; /* whether to continue */ Output: int n_ans; /* numerator of answer */ int d_ans; /* denominator of answer */

38 Design 1. Initialize again to y 2. As long as user wants to continue
3. Get a fraction problem 3.1 Get first fraction 3.2 Get operator 3.3 Get second fraction 4. Compute the result 4.1 Select a task based on operator 4.2 Put the result fraction in reduced form 5. Display problem and result 6. Check if user wants to continue

39 Implementation (Step 4 of the Algorithm)
/* Gets a fraction problem */ scan_fraction(&n1, &d1); op = get_operator(); scan_fraction(&n2, &d2); /* Computes the result */ switch (op) { case '+': add_fractions(n1, d1, n2, d2, &n_ans, &d_ans); break; case '-': add_fractions(n1, d1, -n2, d2, &n_ans, &d_ans); case '*': multiply_fractions(n1, d1, n2, d2, &n_ans, &d_ans); case '/': multiply_fractions(n1, d1, d2, n2, &n_ans, &d_ans); } reduce_fraction(&n_ans, &d_ans);

40 Testing A stub is a skeleton function that consists of a header, trace messages and assigned values to the output parameters. Using stubs for incomplete functions enables testing of the flow of control among the other functions before these function are completed. The process of testing the flow control between a main and subordinate functions is called top-down testing.

41 Stup for Function multiply_fractions
/* ***** STUB ***** * Multiplies fractions represented by pairs of integers. * Product of n1/d1 and n2/d2 is stored in variables pointed * to by n_ansp and d_ansp. Result is not reduced. */ void multiply_fractions(int n1, int d1, /* input - first fraction */ int n2, int d2, /* input - second fraction */ int *n_ansp, /* output - */ int *d_ansp) /* product of two fractions */ { /* Displays trace message */ printf("\nEntering multiply fractions with\n"); printf("n1 = %d, d1 = %d, n2 = %d, d2 = %d\n", n1, d1, n2, d2); /* Defines output arguments */ *n_ansp = 1; *d_ansp = 1; }

42 Testing The stub functions can be completed and test individually. A test of an individual function is referred to as unit test. When a module is completed and tested, it can be substituted for its stub in the program. Bottom-up testing is the process of testing individual functions of a program. Testing the entire program after replacing all its stubs with the pre-tested functions is referred to as system integration test.

43 Common Programming Errors
The correspondence between actual parameters and formal parameters (number, type, order) Actual output arguments must be of the same pointer types as the corresponding formal parameters. Recursive functions should be tested to make sure they terminate properly If return is using for the expression containing the call to the recursive function, every path through a non-void function should lead to a return statement.


Download ppt "Modular Programming Advantages of using functions (to make a modular program) are: Changing the program into separate pieces Code reusing Easier modification."

Similar presentations


Ads by Google