Title: Modular%20Programming
1Modular 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?
2Functions 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)
- printf(" \n")
- printf("\n")
-
-
-
- 135.68
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 gt 1 --i)
- product i
-
- / Returns function result /
- return (product)
5Functions 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- 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 gt n2) largern1
- else largern2
- return(larger)
-
7A 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 n6 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 gt 1 --i)
- product i
-
- / Returns function result /
- return (product) Returns the result
value of 720
8 Logical FunctionsThe 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)
9Function 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 ltmath.hgt
- / 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 numbergt ")
- scanf("lf", num 1)
- printf("Enter an integergt ")
- scanf("d", num 2)
- / Call scale and display result. /
- printf("Result of call to function scale is
.3f\n",
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 numbergt 2.5
- Enter an integergt -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 2.5 x2.5
- num_2 -2 n-2
-
scale_factor?
12Argument 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
13Case 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 lt 2
- Display an error message
- else if n lt NMAX
- Do Step 2 and 3
- else
- Display an error message
- 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
- else
- Display the smallest divisor of n
15- include ltstdio.hgt
- 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 numbergt ") - scanf("d", n)
- / Checks that the number is in the range
2...NMAX / - if (n lt 2)
- printf("Error number too small. The
smallest prime is 2.\n") - else if (n lt NMAX)
- / Finds the smallest divisor (gt 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)
16Step 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 ltmath.hgt
- / 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 gt sqrt(n))
- divisor n
- else if ((n trial) 0)
- divisor trial
18Function 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
19Pointers
- 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
pointers direct value. - For example nump is 84
84
1024
20Meaning 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
21Example 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 lt 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)
22Example of a program that calls a function with
multiple output arguments
- / Demonstrates the use of a function with input
and output parameters./ - include ltstdio.hgt
- include ltmath.hgt
- 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 analyzegt ")
- 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)
Enter a value to analyzegt 35.817 Parts of
35.8170 sign whole number magnitude 35
fractional part 0.8170
23Side 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
?
fracp
fr
7423
?
magnitude
?
24More 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- 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
1 / function fun-two can be called here - . . .
- / end one /
- int
- fun_two(int one, char anarg) / header
2 / -
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("dcd", nump,
slash,denomp ) -
- while (error)
27Recursive 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
28Recursive 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 1 simple case
- 1.2 Add 6 to the result
- 2. Add 6 to the result of problem 1
29Recursive Functions
- /
- Performs integer multiplication using
operator. - Assumes n gt 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)
3018
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
31Local Variable and Parameter Stack of
multiply(6,3)
n
m
ans
?
6
3
1
6
2
?
2
6
3
?
6
1
?
n
m
ans
6
2
?
3
?
6
3
7
6
3
?
return from the third call
6
1
6
n
m
ans
6
2
?
4
18
6
3
8
6
3
?
6
2
?
return from the first call
5
6
3
?
6
2
12
return from the second call
6
6
3
?
32Tracing 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
printf is used to make a self-trace recursive
function
33Case 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 /
34Design 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)lt0
- 1.3.2 Find the root by
bisectingx_l,x_mid - 1.3.3 Find the root by
bisectingx_mid, x_r -
35Implementation
- 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 lt epsilon) /
simple case 1 / - root x_mid
- else if (f(x_mid) 0.0) /
simple case 2 / - root x_mid
- else if (f(x_l) f(x_mid) lt 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)
36Case 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)
37Analysis
- 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 /
38Design
- 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
39Implementation (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) - break
- case ''
- multiply_fractions(n1, d1, n2,
d2, n_ans, d_ans) - break
- case '/'
- multiply_fractions(n1, d1, d2,
n2, n_ans, d_ans) -
- reduce_fraction(n_ans, d_ans)
40Testing
- 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.
41Stup 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
42Testing
- 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.
43Common 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.