Professional Documents
Culture Documents
Function Definitions
Storage Classes
Scoping Rules
In-class Exercises
What are Functions?
𝑓 𝑥 = 2𝑥
𝑓 𝑥, 𝑦 = 𝑥 2 + 17𝑦
It also allows me to not worry about the details of implementation of this function (if it is written by
somebody else).
In more formal terms…
A function declaration is specified this way:
}
Why do we use Functions in
Programming?
We would like to take in the scores of all the students in each class and compute the following:
◦ The minimum
◦ The maximum
◦ The mean
◦ Keep taking the input until -1 was entered
printf("Please enter the scores of the students on the quiz. If you are done, enter -1.\n“);
do //we're going to use a do-while loop here. This loop exits if either the user enters -1 or the maximum limit of the array is
reached
scanf_s(“%f”, temp_score);
if (temp_score != -1)
{
score[i] = temp_score;
i++;
} while ((temp_score != -1) && (num_filled[i] < num_students)); //num_students is the variable storing the length of the array.
Why do we use Functions in
Programming?
Finding the min, and max, and computing the mean:
float mean = sum / num_students; //...and divide by the number of students who took this quiz
}
Why do we use Functions in
Programming?
So instead of all this code: I could simply replace it with:
//Find min and max:
min = compute_min(score);
float min = score[0], max = score[0], sum = 0;
max[i] = score[i];
//Compute mean:
float mean = sum / num_students; //...and divide by the number of students who
took this quiz
}
In Summary, This is what we
are doing
Top-Down Design (also called stepwise refinement)
◦ Break the algorithm into subtasks
◦ Break each subtask into smaller subtasks
◦ Eventually the smaller subtasks are trivial to
implement in the programming language => we implement those in a function which can be reused
(called) many times and even shared across different programs!
function header
int get_min(int val1, int val2, int val3)
min = val2;
min = val3;
return(min);
function body
How do I use (call) this function?
void main()
int x, y, z, min;
min = get_min(x,y,z);
}
Functions
In top-down design, a subtask might produce
◦ No value (just input or output for example)
◦ One value
◦ More than one value
C = (5/9) (F – 32)
◦ What is the problem with the formula above?
c_temperature = celsius(f_temperature);
void-Function Definition
Two main differences between void-function definitions and the definitions of functions that return one value
◦ Keyword void replaces the type of the value returned
◦ E.g. void main() {…}
◦ void means that no value is returned by the function
◦ The return statement does not include and expression
Example:
void show_results(float f_degrees, float c_degrees)
f_degrees, c_degrees);
return;
}
Void-Function Definition
Using a void-Function
Example:
show_results(32.5, 0.3);
if (number == 0)
return;
}
Another example of Void-
Functions: The Main Function
The main function in a program is used like a void function…do you have to
end the program with a return-statement?
◦ Because the main function is defined to return a value of type int, the return is needed
◦ return 0 can be omitted, but many compilers still require it
Example 2
Write a program that computes the average of three floating numbers. Use modular programming
techniques (another term for functions).
Example 2
//Write a program that computes the average of three floating scanf_s("%f %f %f", &num1, &num2, &num3);
numbers. Use modular programming techniques (another term for
functions). average_value = avg(num1, num2, num3);
float avg(float, float, float); //Here is where you actually define the functionality/body of the
function
#include<iostream> cout << "The average of the three numbers is: " << average_value
<< endl;
1 4 9 16 25 36 49 64 81 100
Square Function
Random Function
Function that returns a (pseudo) randomly selected value.
The values are computed based on a complex mathematical formula, but still the values *could*
be calculated so that the output is not random at all!
In some languages, you can seed the random function with the current time or some value. This
will help make the function a bit less predictable.
Very useful for sampling, randomizing the order of items, simulations, etc.
How does the randomization
process work?
0 5
1 7
𝑓(𝑥) 2 1
3 0
4 18
The rand Function
//rand function and rand seed
However, every time I
#include<stdio.h> run this, I get 41 on
#include<stdlib.h> my machine!!
printf("%d", v1);
return 0;
}
We need to seed our function with
some value that keeps changing!
0 5
1 7
𝑥 = 11
12
2
𝑓(𝑥) 2 1
3 0
4 18
Random Seed
Let’s build a number guessing game! The computer selects a random number between 1 and 10
inclusive and the player is asked to guess that number.
If the player guesses a larger number, the computer says that the secret number is smaller
If the player guesses a smaller number, the computer says that the secret number is larger
do {
//Get user's guess
printf("Guess the number (between 1 and 10
inclusive):\n");
scanf_s("%d", &iGuess);
x
0 RAND_MAX
y
r1 r2
𝑥−0 𝑦−𝑟1
𝑅𝐴𝑁𝐷𝑀𝐴𝑋 −0
= 𝑟2−𝑟1
𝑥∗ 𝑟2−𝑟1
𝑦 = 𝑅𝐴𝑁𝐷 + 𝑟1
𝑀𝐴𝑋
Changing the range of Rand to
be between 20 and 30
𝑥∗ 𝑟2−𝑟1
𝑦= + 𝑟1
𝑅𝐴𝑁𝐷𝑀𝐴𝑋
𝑥∗ 30−20
𝑦= 𝑅𝐴𝑁𝐷𝑀𝐴𝑋
+ 20
Let’s try!
/* rand example: guess the number */
#include<stdio.h> /* printf, scanf, puts, NULL */ else if (iSecret > iGuess)
#include<stdlib.h> /* srand, rand */ printf("The secret number is higher\n");
#include<time.h> /* time */
} while (iSecret != iGuess);
do {
//Get user's guess
printf("Guess the number (between 1 and 10
inclusive):\n");
scanf_s("%d", &iGuess);
do {
//Get user's guess
printf("Guess the number (between 1 and 10
inclusive):\n");
scanf_s("%d", &iGuess);
}
Output
2. Function to generate the random numbers and count their occurrence, returning the filled array.
int main()
display_hist(hist);
return 0;
}
Passing by Reference
& Scoping Rules
Function Calls: Scoping Rules
When we jump into the body of a function:
◦ Variables declared inside are local to this function
◦ This means that they cannot be seen, accessed, or modified by any code outside this function.
◦ We call these variables: local variables
◦ This is the default setup, unless we explicitly state that we want a particular variable to be a global variable.
Global variable
◦ Available to more than one function as well as the main part of the program
◦ Declared outside any function body
◦ Declared outside the main function body
◦ Declared before any function that uses it
double volume(double);
int main()
{…}
◦ PI is available to the main function and to function volume
Passing by Reference vs Passing
by Value
Passing by Value vs. by
Reference
Email Post
Document
Function Calls: Passing by
Value
Functions we have designed so far
◦ Create local copies of the variables being passed to them (passing by value)
◦ Can only return one and only one value.
1000 20 x
1001
1002
Passing by Reference vs Passing
by Value
1000 20 x
1001
1002
Call-by-Reference Parameters
Call-by-value is not adequate when we need a sub-task to obtain input values
◦ Call-by-value means that the formal parameters receive the values of the arguments
◦ To obtain input values, we need to change the variables that are arguments to the function
◦ Recall that we have changed the values of formal parameters in a function body, but we have not changed the arguments found in the
function call (recall the cup of coffee example)
What if we would like to return more than one value? What about an array?
Passing by Reference vs Passing
by Value
Pointers
A pointer is the memory address of a variable
Pointers are declared as:
p
float* p;
?
This identifies p as a pointer variable of type “pointer to float”.
This stores the memory address of a float variable in p.
To access the contents real memory item with address 101, we use *p.
If we only refer to p, we are accessing the address of the memory block, and not the contents
of the memory block.
Pointers Tell
Where To Find A Variable
The ? in the memory cell pointed to by p indicates that its contents are undefined after
float* p; is executed.
How do I assign a value to the memory location pointed to by p?
*p = 15.5;
p
15.5
How do we specify a Call-by-
Reference?
void plus_one(int* x); //This void plus_one(int* x)
is how I define the function
{
heading
*x = *x+1;
void main()
}
{
int n = 1;
plus_one(&n);
}
Call-By-Reference:
Example
//Program to demonstrate call-by-reference void get_numbers(int* input1, int* input2)
{
#include<stdio.h> printf("Enter two integers: ");
scanf_s("%d %d", input1, input2); //NOTE HERE: There is
void get_numbers(int *input1, int *input2); NO &!!!
//Reads two ints from the keyboard. }
void swap_values(int *v1, int *v2); void swap_values(int* v1, int* v2)
//Interchanges the values of v1 and v2 {
int temp;
void show_results(int output1, int output2);
//Shows the values of v1 and v2, in that order. temp = *v1;
*v1 = *v2;
int main() *v2 = temp;
{ }
int first_num, second_num;
void show_results(int output1, int output2)
get_numbers(&first_num, &second_num); {
swap_values(&first_num, &second_num); printf("The swapped numbers are: %d %d",
show_results(first_num, second_num); output1, output2);
}
return 0;
}
Call-By-Reference Details
Call-by-reference works almost as if the argument variable is substituted for
the formal parameter, not the argument’s value
In reality, the memory location of the argument variable is given to the formal
parameter
◦ Whatever is done to a formal parameter in the function body, is actually done to the value at the memory
location of the argument variable
Passing by Reference vs Passing
by Value
1000 20 x
1001
1002
Passing by Reference vs Passing
by Value
1000 20 x
1001
1002
Example: Sorting an Array
Ascendingly
We still don’t know how to pass an entire array to a function. This will be revealed when we talk
about pointers.
For now, we want to build a modular code to sort the contents of an array in an ascending order
Example: Sorting an Array
Ascendingly
//Libraries bool swapped = true; void swap(float* a, float* b)
#include <stdio.h> do {
#include<stdbool.h> { float temp = *a;
swapped = false; //assume *a = *b;
//Declare function prototype array is sorted unless I *b = temp;
void swap(float*, float*); //This is a perform a swap }
function that will be used to swap the for (int i = 0; i < size - 1;
value of two variables i++) void display_array(float a)
void display_array(float); { {
if (arr[i] > arr[i + 1]) printf("%f ", a);
void main() { }
{ swap(&arr[i], &arr[i
enum { size = 5 }; + 1]);
float arr[size]; swapped = true;
}
printf("Please enter the %d values }
to sort.\n", size); } while (swapped);
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
scanf_s("%f", &arr[i]); display_array(arr[i]);
//Notice here I have the & }
sign again!!
} }
Example: Sorting an Array
Ascendingly Output
Example:
void good_stuff(int* par1, int par2, double* par3);
◦ par1 and par3 are call-by-reference formal parameters
◦ Changes in par1 and par3 change the argument variable
◦ par2 is a call-by-value formal parameter
◦ Changes in par2 do not change the argument variable
Choosing Parameter Types*
How do you decide whether a call-by-reference or call-by-value formal
parameter is needed?
◦ Does the function need to change the value of the
variable used as an argument?
◦ Yes? Use a call-by-reference formal parameter
◦ No? Use a call-by-value formal parameter
Comparing
Argument-Passing
Mechanisms
//Comparing pass by reference(PBR) with pall by value (PBV): printf("n1 after function call = %d\n", n1);
printf("n2 after function call = %d\n", n2);
#include<stdio.h>
}
void do_stuff(int, int*);
//par1_value is a pass-by-value parameter
//par2_value is a pass-by-reference parameter void do_stuff(int par1_value, int* par2_ref)
{
int main() par1_value = 111;
{ printf("par1_value inside function call = %d\n",
int n1; par1_value);
int n2;
*par2_ref = 222;
n1 = 1; printf("par2_ref inside function call = %d\n", *par2_ref);
n2 = 2;
return 0;
printf("n1 before function call = %d\n", n1);
printf("n2 before function call = %d\n", n2); }
do_stuff(n1, &n2);
Output