Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
2 views

9 - Functions - Programming Language

Lecture de la uptp para pl de funciones
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views

9 - Functions - Programming Language

Lecture de la uptp para pl de funciones
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 86

Functions

Shanq-Jang Ruan (阮聖彰), Ph. D.


Distinguished Professor
Dept. Electronic and Computer Engineering
National Taiwan University of Science and Technology

1
Introduction
 A function is a series of statements that have been
grouped together and given a name.
 Each function is essentially a small program, with
its own declarations and statements.
 Advantages of functions:
A program can be divided into small pieces that are
easier to understand and modify.
 We can avoid duplicating code that’s used more than
once.
 A function that was originally part of one program
can be reused in other programs. 2
Program: Computing Averages
 A function named average that computes the
average of two double values:
double average(double a, double b)
{
return (a + b) / 2;
}
 The word double at the beginning is the return
type of average.
 The identifiers a and b (the function’s parameters)
represent the numbers that will be supplied when
average is called.
3
Program: Computing Averages
 Every function has an executable part, called the
body, which is enclosed in braces.
 The body of average consists of a single
return statement.
 Executing this statement causes the function to
“return” to the place from which it was called; the
value of (a + b) / 2 will be the value returned by
the function.

4
Program: Computing Averages
 A function call consists of a function name followed
by a list of arguments.
 average(x, y) is a call of the average function.
 Arguments are used to supply information to a
function.
 The call average(x, y) causes the values of x and y to
be copied into the parameters a and b.
 An argument doesn’t have to be a variable; any
expression of a compatible type will do.
 average(5.1, 8.9) and average(x/2, y/3)
are also acceptable. 5
Program: Computing Averages
 We’ll put the call of average in the place where
we need to use the return value.
 A statement that prints the average of x and y:
printf("Average: %g\n", average(x, y));
The return value of average isn’t saved; the
program prints it and then discards it.
 If we had needed the return value later in the
program, we could have captured it in a variable:
avg = average(x, y);

6
average.c
/* Computes pairwise averages of three numbers */

#include <stdio.h>

double average(double a, double b)


{
return (a + b) / 2; What if we skip double?
}
average(double a, double b)
int main(void) {
{ return (a + b) / 2;
double x, y, z; }
printf("Enter three numbers: ");
scanf("%lf%lf%lf", &x, &y, &z);
printf("Average of %g and %g: %g\n", x, y, average(x, y));
printf("Average of %g and %g: %g\n", y, z, average(y, z));
printf("Average of %g and %g: %g\n", x, z, average(x, z));

return 0;
}

7
Program: Computing Averages
 The average.c program reads three numbers and
uses the average function to compute their
averages, one pair at a time:
Enter three numbers: 3.5 9.6 10.2
Average of 3.5 and 9.6: 6.55
Average of 9.6 and 10.2: 9.9
Average of 3.5 and 10.2: 6.85

8
Computing Averages: Function Position

9
Computing Averages without
Return Type

10
Computing Averages without
Return Type

11
Program: Printing a Countdown
 To indicate that a function has no return value, we specify
that its return type is void:
void print_count(int n)
{
printf("T minus %d and counting\n", n);
}
 void is a type with no values.
 A call of print_count must appear in a statement by
itself:
print_count(i);
 The countdown.c program calls print_count 10
times inside a loop.
12
countdown.c
/* Prints a countdown */

#include <stdio.h>

void print_count(int n)
{
printf("T minus %d and counting\n", n);
}
How about this time?
int main(void) print_count(int n)
{ {
int i; printf("T minus %d and
counting\n", n);
for (i = 10; i > 0; --i) }
print_count(i);

return 0;
}

13
Printing a Countdown without
Return Type

14
Program: Printing a Pun
(Revisited)
 When a function has no parameters, the word void is placed
in parentheses after the function’s name:
void print_pun(void)
{
printf("To C, or not to C: that is the question.\n");
}
 To call a function with no arguments, we write the function’s
name, followed by parentheses:
print_pun();
The parentheses must be present.
 The pun2.c program tests the print_pun function.

15
pun2.c
/* Prints a bad pun */

#include <stdio.h>

void print_pun(void)
{
printf("To C, or not to C: that is the question.\n");
}

int main(void)
{
print_pun();
return 0;
}

16
Function with ( )

17
Function Definitions
 General form of a function definition:
return-type function-name ( parameters )
{
declarations
statements
}

18
Function Definitions
 The return type of a function is the type of value
that the function returns.
 Rules governing the return type:
 Functions may not return arrays.
 Specifying that the return type is void indicates that
the function doesn’t return a value.
 If the return type is omitted in C89, the function is
presumed to return a value of type int.
 In C99, omitting the return type is illegal.

19
Function Definitions
 As a matter of style, some programmers put the
return type above the function name:
double
average(double a, double b)
{
return (a + b) / 2;
}
 Putting the return type on a separate line is
especially useful if the return type is lengthy, like
unsigned long int.

20
Function Definitions
 After the function name comes a list of parameters.
 Each parameter is preceded by a specification of its
type; parameters are separated by commas.
 If the function has no parameters, the word void
should appear between the parentheses.

21
Function Definitions
 The body of a function may include both
declarations and statements.
 An alternative version of the average function:
double average(double a, double b)
{
double sum; /* declaration */

sum = a + b; /* statement */
return sum / 2; /* statement */
}

22
Function Definitions
 Variables declared in the body of a function
can’t be examined or modified by other
functions.
 In C89, variable declarations must come first,
before all statements in the body of a function.
 In C99, variable declarations and statements

can be mixed, as long as each variable is


declared prior to the first statement that uses
the variable.
23
Function Definitions
 The body of a function whose return type is void
(a “void function”) can be empty:
void print_pun(void)
{
}
 Leaving the body empty may make sense as a
temporary step during program development.

24
Function Calls
 A function call consists of a function name followed
by a list of arguments, enclosed in parentheses:
average(x, y)
print_count(i)
print_pun()
 If the parentheses are missing, the function won’t be
called:
print_pun; /*** WRONG ***/
This statement is legal but has no effect.

25
Function Calls
 A call of a void function is always followed by a
semicolon to turn it into a statement:
print_count(i);
print_pun();
 A call of a non-void function produces a value
that can be stored in a variable, tested, printed, or
used in some other way:
avg = average(x, y);
if (average(x, y) > 0)
printf("Average is positive\n");
printf("The average is %g\n", average(x, y));

26
Function Calls
 The value returned by a non-void function can
always be discarded if it’s not needed:
average(x, y); /* discards return value */
This call is an example of an expression statement:
a statement that evaluates an expression but then
discards the result.

27
Function Calls
 Ignoring the return value of average is an odd
thing to do, but for some functions it makes sense.
 printf returns the number of characters that it
prints.
 After the following call, num_chars will have the
value 9:
num_chars = printf("Hi, Mom!\n");
 We’ll normally discard printf’s return value:
printf("Hi, Mom!\n");
/* discards return value */
28
Function Calls
 To make it clear that we’re deliberately discarding
the return value of a function, C allows us to put
(void) before the call:
(void) printf("Hi, Mom!\n");
 Using (void) makes it clear to others that you
deliberately discarded the return value, not just
forgot that there was one.

29
Program:
Testing Whether a Number Is Prime
 The prime.c program tests whether a number is
prime:
Enter a number: 34
Not prime
 The program uses a function named is_prime
that returns true if its parameter is a prime number
and false if it isn’t.
 is_prime divides its parameter n by each of the
numbers between 2 and the square root of n; if the
remainder is ever 0, n isn’t prime.
30
prime.c
/* Tests whether a number is prime */

#include <stdbool.h> /* C99 only */


#include <stdio.h>

bool is_prime(int n)
{
int divisor;

if (n <= 1)
return false;
for (divisor = 2; divisor * divisor <= n; divisor++)
if (n % divisor == 0)
return false;
return true;
}

31
int main(void)
{
int n;

printf("Enter a number: ");


scanf("%d", &n);
if (is_prime(n))
printf("Prime\n");
else
printf("Not prime\n");
return 0;
}

32
Practice
 Perfect number, a positive integer that is equal to
the sum of its proper divisors. The smallest perfect
number is 6, which is the sum of 1, 2, and 3
 The program uses a function named is_prefect
that returns true if its parameter is a perfect
number and false if it isn’t.
 Please write perfect.c program to list all the
perfect numbers under 10000.

33
#include <stdio.h>

int is_perfect(int n) {
int j, total=0;
for (j = 1; j < n; j++) {
if ((n % j) == 0) total += j;
}
return n == total ? 1 : 0;
}

int main(void)
{
int i, j, total = 0;
for ( i = 1; i <= 10000; i++)
{
if (is_perfect(i)) printf("%d ", i);

}
return 0;
}
34
Function Declarations
 C doesn’t require that the definition of a function
precede its calls.
 Suppose that we rearrange the average.c
program by putting the definition of average after
the definition of main.

35
Function Declarations
#include <stdio.h>

int main(void)
{
double x, y, z;
printf("Enter three numbers: ");
scanf("%lf%lf%lf", &x, &y, &z);
printf("Average of %g and %g: %g\n", x, y, average(x, y));
printf("Average of %g and %g: %g\n", y, z, average(y, z));
printf("Average of %g and %g: %g\n", x, z, average(x, z));
return 0;
}
double average(double a, double b)
{
return (a + b) / 2;
}

36
Function Declarations
 When the compiler encounters the first call of
average in main, it has no information about the
function.
 Instead of producing an error message, the compiler
assumes that average returns an int value.
 We say that the compiler has created an implicit
declaration of the function.

37
Function Declarations
 The compiler is unable to check that we’re passing
average the right number of arguments and that
the arguments have the proper type.
 Instead, it performs the default argument
promotions and hopes for the best.
 When it encounters the definition of average later
in the program, the compiler notices that the
function’s return type is actually double, not int,
and so we get an error message.

38
Function Declarations
 One way to avoid the problem of call-before-
definition is to arrange the program so that the
definition of each function precedes all its calls.
 Unfortunately, such an arrangement doesn’t always
exist.
 Even when it does, it may make the program harder
to understand by putting its function definitions in
an unnatural order.

39
Function Declarations
 Fortunately, C offers a better solution: declare each
function before calling it.
 A function declaration provides the compiler with a brief
glimpse at a function whose full definition will appear
later.
 General form of a function declaration:
return-type function-name ( parameters ) ;
 The declaration of a function must be consistent with the
function’s definition.
 Here’s the average.c program with a declaration of
average added.
40
Function Declarations
#include <stdio.h>
double average(double a, double b); /* DECLARATION */
int main(void)
{
double x, y, z;
printf("Enter three numbers: ");
scanf("%lf%lf%lf", &x, &y, &z);
printf("Average of %g and %g: %g\n", x, y, average(x, y));
printf("Average of %g and %g: %g\n", y, z, average(y, z));
printf("Average of %g and %g: %g\n", x, z, average(x, z));
return 0;
}
double average(double a, double b) /* DEFINITION */
{
return (a + b) / 2;
}

41
Function Declarations
 Function declarations of the kind we’re discussing
are known as function prototypes.
 C also has an older style of function declaration in
which the parentheses are left empty.
 A function prototype doesn’t have to specify the
names of the function’s parameters, as long as their
types are present:
double average(double, double);
 It’s usually best not to omit parameter names.

42
Function Declarations
 C99 has adopted the rule that either a declaration or
a definition of a function must be present prior to
any call of the function.
 Calling a function for which the compiler has not
yet seen a declaration or definition is an error.

43
Arguments
 In C, arguments are passed by value: when a
function is called, each argument is evaluated and
its value assigned to the corresponding parameter.
 Since the parameter contains a copy of the
argument’s value, any changes made to the
parameter during the execution of the function don’t
affect the argument.

44
Arguments
 The fact that arguments are passed by value has
both advantages and disadvantages.
 Since a parameter can be modified without affecting
the corresponding argument, we can use parameters
as variables within the function, reducing the
number of genuine variables needed.

45
Arguments
 Consider the following function, which raises a
number x to a power n:
int power(int x, int n)
{
int i, result = 1;

for (i = 1; i <= n; i++)


result = result * x;

return result;
}

46
Arguments
 Since n is a copy of the original exponent, the
function can safely modify it, removing the need for
i:
int power(int x, int n)
{
int result = 1;

while (n-- > 0)


result = result * x;

return result;
}
47
Arguments
 C’s requirement that arguments be passed by value
makes it difficult to write certain kinds of functions.
 Suppose that we need a function that will decompose a
double value into an integer part and a fractional part.
 Since a function can’t return two numbers, we might try
passing a pair of variables to the function and having it
modify them:
void decompose(double x, long int_part,
double frac_part)
{
int_part = (long) x;
frac_part = x - int_part;
}

48
Arguments
 A call of the function:
decompose(3.14159, i, d);
 Unfortunately, i and d won’t be affected by the
assignments to int_part and frac_part.
 Chapter 11 shows how to make decompose work
correctly.

49
Argument Conversions
 C allows function calls in which the types of the
arguments don’t match the types of the parameters.
 The rules governing how the arguments are
converted depend on whether or not the compiler
has seen a prototype for the function (or the
function’s full definition) prior to the call.

50
Argument Conversions
 The compiler has encountered a prototype prior to
the call.
 The value of each argument is implicitly converted
to the type of the corresponding parameter as if by
assignment.
 Example: If an int argument is passed to a
function that was expecting a double, the
argument is converted to double automatically.

51
Argument Conversions
 The compiler has not encountered a prototype
prior to the call.
 The compiler performs the default argument
promotions:
 float arguments are converted to double.
 The integral promotions are performed, causing char
and short arguments to be converted to int. (In
C99, the integer promotions are performed.)

52
Argument Conversions
 Instead, the compiler performs the default argument promotions
on x, with no effect.
 Since it’s expecting an argument of type int but has been given
a double value instead, the effect of calling square is
undefined.
 The problem can be fixed by casting square’s argument to the
proper type:
printf("Square: %d\n", square((int) x));
 A much better solution is to provide a prototype for square
before calling it.
 In C99, calling square without first providing a declaration or
definition of the function is an error.
54
Array Arguments
 Example:
int sum_array(int a[], int n)
{
int i, sum = 0;

for (i = 0; i < n; i++)


sum += a[i];
return sum;
}
 Since sum_array needs to know the length of a,
we must supply it as a second argument.

56
Array Arguments
 The prototype for sum_array has the following
appearance:
int sum_array(int a[], int n);
 As usual, we can omit the parameter names if we
wish:
int sum_array(int [], int);

57
Array Arguments
 When sum_array is called, the first argument will be the
name of an array, and the second will be its length:
#define LEN 100

int main(void)
{
int b[LEN], total;

total = sum_array(b, LEN);

}
 Notice that we don’t put brackets after an array name when
passing it to a function:
total = sum_array(b[], LEN); /*** WRONG ***/

58
Array Arguments
 A function has no way to check that we’ve passed it
the correct array length.
 We can exploit this fact by telling the function that
the array is smaller than it really is.
 Suppose that we’ve only stored 50 numbers in the b
array, even though it can hold 100.
 We can sum just the first 50 elements by writing
total = sum_array(b, 50);

59
Array Arguments
 Be careful not to tell a function that an array
argument is larger than it really is:
total = sum_array(b, 150); /*** WRONG ***/
sum_array will go past the end of the array,
causing undefined behavior.

60
Array Arguments
 A function is allowed to change the elements of an
array parameter, and the change is reflected in the
corresponding argument.
 A function that modifies an array by storing zero
into each of its elements:
void store_zeros(int a[], int n)
{
int i;

for (i = 0; i < n; i++)


a[i] = 0;
}
61
Array Arguments
 A call of store_zeros:
store_zeros(b, 100);
 The ability to modify the elements of an array
argument may seem to contradict the fact that C
passes arguments by value.
 Chapter 12 explains why there’s actually no
contradiction.

62
Array Arguments
 If a parameter is a multidimensional array, only the length
of the first dimension may be omitted.
 If we revise sum_array so that a is a two-dimensional
array, we must specify the number of columns in a:
#define LEN 10
int sum_two_dimensional_array(int a[][LEN], int n)
{
int i, j, sum = 0;
for (i = 0; i < n; i++)
for (j = 0; j < LEN; j++)
sum += a[i][j];
return sum;
}
63
Array Arguments
 Not being able to pass multidimensional arrays with
an arbitrary number of columns can be a nuisance.
 We can often work around this difficulty by using
arrays of pointers.
 C99’s variable-length array parameters provide an
even better solution.

64
practice

1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24

80
Answer

81
The return Statement
 A non-void function must use the return
statement to specify what value it will return.
 The return statement has the form
return expression ;
 The expression is often just a constant or variable:
return 0;
return status;
 More complex expressions are possible:
return n >= 0 ? n : 0;

82
The return Statement
 If the type of the expression in a return statement
doesn’t match the function’s return type, the
expression will be implicitly converted to the return
type.
 Ifa function returns an int, but the return statement
contains a double expression, the value of the
expression is converted to int.

83
The return Statement
 return statements may appear in functions whose
return type is void, provided that no expression is
given:
return; /* return in a void function */
 Example:
void print_int(int i)
{
if (i < 0)
return;
printf("%d", i);
}
84
The return Statement
 A return statement may appear at the end of a
void function:
void print_pun(void)
{
printf("To C, or not to C: that is the question.\n");
return; /* OK, but not needed */
}

Using return here is unnecessary.


 If a non-void function fails to execute a
return statement, the behavior of the program
is undefined if it attempts to use the function’s
return value.
85
Program Termination
 Normally, the return type of main is int:
int main(void)
{

}
 Older C programs often omit main’s return type,
taking advantage of the fact that it traditionally
defaults to int:
main()
{

}
86
Program Termination
 Omitting the return type of a function isn’t legal in
C99, so it’s best to avoid this practice.
 Omitting the word void in main’s parameter list
remains legal, but—as a matter of style—it’s best to
include it.

87
Practice

88
Program Termination
 The value returned by main is a status code that
can be tested when the program terminates.
 main should return 0 if the program terminates
normally.
 To indicate abnormal termination, main should
return a value other than 0.
 It’s good practice to make sure that every C
program returns a status code.

89
The exit Function
 Executing a return statement in main is one way
to terminate a program.
 Another is calling the exit function, which
belongs to <stdlib.h>.
 The argument passed to exit has the same
meaning as main’s return value: both indicate the
program’s status at termination.
 To indicate normal termination, we’d pass 0:
exit(0); /* normal termination */

90
The exit Function
 Since 0 is a bit cryptic, C allows us to pass
EXIT_SUCCESS instead (the effect is the same):
exit(EXIT_SUCCESS);
 Passing EXIT_FAILURE indicates abnormal termination:
exit(EXIT_FAILURE);
 EXIT_SUCCESS and EXIT_FAILURE are macros
defined in <stdlib.h>.
 The values of EXIT_SUCCESS and EXIT_FAILURE
are implementation-defined; typical values are 0 and 1,
respectively.

91
The exit Function
 The statement
return expression;
in main is equivalent to
exit(expression);
 The difference between return and exit is that
exit causes program termination regardless of
which function calls it.
 The return statement causes program termination
only when it appears in the main function.

92
Practice

93
Recursion
 A function is recursive if it calls itself.
 The following function computes n! recursively,
using the formula n! = n × (n – 1)!:
int fact(int n)
{
if (n <= 1)
return 1;
else
return n * fact(n - 1);
}

94
Recursion
 To see how recursion works, let’s trace the
execution of the statement
i = fact(4);

95
Recursion
 The following recursive function computes xn, using
the formula xn = x × xn–1.
int power(int x, int n)
{
if (n == 0)
return 1;
else
return x * power(x, n - 1);
}

96
Recursion
 i = power(2, 3);

97
Recursion
 We can condense the power function by putting a
conditional expression in the return statement:
int power(int x, int n)
{
return n == 0 ? 1 : x * power(x, n - 1);
}
 Both fact and power are careful to test a
“termination condition” as soon as they’re called.
 All recursive functions need some kind of
termination condition in order to prevent infinite
recursion.
98
Practice
 In 1202, Italian mathematician Leonardo Pisano (also known as Fibonacci,
meaning "son of Bonacci") pondered the question: Given optimal
conditions, how many pairs of rabbits can be produced from a single pair of
rabbits in one year? This thought experiment dictates that the female rabbits
always give birth to pairs, and each pair consists of one male and one
female.
 Think about it -- two newborn rabbits are placed in a fenced-in yard and left
to, well, breed like rabbits. Rabbits can't reproduce until they are at least
one month old, so for the first month, only one pair remains. At the end of
the second month, the female gives birth, leaving two pairs of rabbits.
When month three rolls around, the original pair of rabbits produce yet
another pair of newborns while their earlier offspring grow to adulthood.
This leaves three pairs of rabbit, two of which will give birth to two more
pairs the following month.
 Write a program to determine the number of rabbits after n months.
https://science.howstuffworks.com/math-concepts/fibonacci-nature.htm99
Practice
Small Pair
Rabbits

Big Pair
Rabbits

Pairs

Pairs

Pairs

Pairs

Pairs

100
Answer

101
The Flow

102
Non-Recursive Version
 Please try to input 45
to test the speed of
recursive and non-
recursive versions.
What is the different?

 Hint: time!

103

You might also like