Post on 26-Dec-2015
Repetition
Repetition
Conditional loops while do while
Counting loops for loops
Arrays Recursion
Loops
Loop Introduction
Loops allow statements to be repeated The code to be repeated is in the loop
body One repetition of the body is called an
iteration Loops are structurally similar to if
statements The loop control statement(s) are
contained in ()s after the keyword The loop body is contained in {}s
While Loop
A while loop consists of the keyword while, a condition and a loop body The condition is a Boolean expression▪ Just like an if statement condition
The loop iterates until the condition is no longer true (while it is true)
The loop body should include code that eventually makes the condition false Or the loop will iterate for ever (an
infinite loop)
Factorial
// PRE: x must be a +ve integer// Function that returns the factorial of xlong long fact(int x){ long long result = 1;
int i = 1; //loop control variable while (i <= x){ result = result * i;
i++;}return result ;
}
Write a function that returns the factorial of the integer parameter:e.g. fact(5) = 5! = 5 * 4* 3 * 2 * 1 = 120
i must be incremented in the loop
The function does not handle –ve numbersNote the indentation of the statements in the function and the loop
don't put a ; here – it makes an empty loop
condition
While Flowchart
... program ...
Loop body
true
Rest of program
false
while statements contain a condition If the condition is
true the body is executed
Then the condition is tested again
If the condition is false the program continues from the end of the loop body
Entry Condition
A while loop has an entry condition If the condition is initially false the loop
body will not be processed at all Sometimes the first iteration should
occur outside of and before the loop So that the variable being evaluated in
the condition can be initialized appropriately
Summing Numbers
// Function that returns the sum of values// entered by the user int sum(){ int result = 0;
int next;printf("Enter a number, 0 to end");scanf("%d", &next);
while (next != 0){ result += next;
printf("Enter a number, 0 to end");scanf("%d", &next);
}return result ;
}
Write a function that sums numbers until the user enters 0
Because next controls the loop it needs a value before the loop starts
Although there are some alternatives:
Initialize next to non-zero and then get input before adding to result, orUse a do ... while loop
Do While Loop
A do ... while loop's condition comes after the loop body The loop body will iterate at least once Whereas a while loop will not iterate at all if the
condition is initially false Any do ... while loop can be replaced by while
Possibly needing some extra statements before the loop statement
Some people prefer while loops because the condition comes first
Do While Factorial
// PRE: x must be a +ve integer// Function that returns the factorial of xlong long fact2(int x){ long long result = 1;
int i = 1; //loop control variable do { result = result * i;
i++;} while (i <= x);return result ;
}
note the ; after the condition
Write a function that returns the factorial of the integer parameter:e.g. fact(5) = 5! = 5 * 4* 3 * 2 * 1 = 120
Counting Loops
Loop bodies are often repeated a certain number of times Rather than ending at an indeterminate
time▪ e.g. factorial function, processing the values
in a list For loops can be used to iterate a
given number of times By incrementing an integer variable And ending when the variable reaches a
value For loops can do anything that while
loops can
For Factorial
// PRE: x must be a +ve integer// Function that returns the factorial of xlong long fact3(int x){ long long result = 1;
for (int i = 1; i <= x; i++){ result = result * i;
}return result ;
}
The loop control statement consists of three statements
Write a function that returns the factorial of the integer parameter:e.g. fact(5) = 5! = 5 * 4* 3 * 2 * 1 = 120
initialization
condition
increment
In this example the loop control variable is also declared in the initialization statement
condition
Controlling For Loops
Initialization
Increment
true
Loop Body
Rest of Program
false
for statements consist of three expressions Separated by ;s
Initialization Executed only once
Condition Tested before each iteration▪ The last time the condition is
tested there is no iteration
▪ Since the test returns false
Increment Applied after each iteration
More About for Loops
It is usual to use for loops as counting loops Initialize the loop control variable Test to see if the end of the count is reached Increment the count (the loop control variable)
The for loop structure is much more general An expression evaluated once at the beginning A condition that is evaluated before each iteration▪ The body is only executed if the condition is true
An expression evaluated once after each iteration
Comma Operator
The comma operator evaluates a list of expressions returning the last expression e.g. z = (x = 1, y = x + 1); x = 1 is evaluated first (assigning 1 to x) y = x + 1 is then evaluated (assigning 2 to y) The comma expression returns the value of y▪ So z is also assigned 2
It is most commonly used in for loops To allow multiple initialization or increment
statements
break and continue
The break and continue statements can be used to change flow of control
The break statement terminates the processing of a loop or switch statement It ends evaluation of its enclosing body And switches control to the next statement after the
closing } The continue statement terminates the processing of
the current loop iteration And then continues with the loop, first testing its condition Like goto, continue and break can make programs harder to
understand
Nested Loops
Like if statements, loops can be nested One loop can contain another loop
The use of functions can make nested loops easier to understand Particularly if one of the nested loops is
placed inside a function Nested loops may cause a program
to run slowly But may also be unavoidable
Which Loop?
There is a large element of choice What you can do with one loop, you can
do with another For loops are a natural choice for
counting with an index While loops are a natural choice for
indefinite iteration Such as when the loop ends based on
user input
Character Input and Output
Character I / O
The scanf and printf functions are generalized input and output functions
There are also specialized input and output functions Particularly relating to characters and
strings The getchar and putchar functions
are designed for character I/O
getchar()
The getchar() function takes no arguments and returns the next character from inputchar ch;ch = getchar();
getchar() will read any character, including whitespace characters Note that pressing Enter still indicates
that input should be processed
putchar()
The putchar(char) function prints its argumentchar ch = 'a';putchar(ch);
Neither getchar or putchar require format specifications Since both functions work only with
characters Both functions are defined in stdio.h
Counting Letters
Write a function that prints the number of 'e' characters in a sentence
void e_count(){char ch;int count = 0;
ch = getchar();
while(ch != '\n'){if(ch == 'e'){
count++;ch = 'E';
}putchar(ch);ch = getchar();
}printf("\n\nYour input contained %d 'e's\n\n",count);
}
Complex Expressions
The function shown previously has an initial call to getchar before the while statement And contained a call to getchar in the loop body These calls can be made in the while condition
//...ch = getchar();
while(ch != '\n'){//...ch = getchar();
}//...
//...while((ch = getchar()) != '\n'){
//...}//...
important!
without the brackets
Character Functions
ctype.h contains character functions There are two functions to change the
case of a character toLower(char)▪ If the argument is uppercase it returns the
lowercase version, otherwise it returns the original argument
toUpper(char)▪ If the argument is lowercase it returns the
uppercase version, otherwise it returns the original argument
More Character Functions Test functions that return true (1) or false(0)
isalnum(char) – alphanumeric (alphabetic or numeric) isalpha(char) – alphabetic isblank(char) – space, tab or newline iscntrl(char) – control character (like Ctrl+C) isdigit(char) – digit isgraph(char) – a printable character, except space islower(char) – lowercase character isupper(char) – uppercase character ispunct(char) – punctuation isprint(char) – a printable character isspace(char) – a space isxdigit(char) – a hexadecimal digit
A printable character is one that can be printed – in contrast to a control character
Arrays
Arrays
Introduction Array fundamentals
Declaring arrays Indexing arrays Initializing arrays
Arrays and functions Keeping track of array size
Array Introduction
An array is a sequence of values of the same type Like a list of values Each value is a single element of the list
An array is a collection of values The entire collection can be referenced,
or Its individual elements
Average Grades
Let’s say we want to write a program to input grades for a course Assume that 44 students are registered Input each grade, one at a time, and
store it Once the grades are input we can
use them to calculate the average grade
Average Grades …
In a world without arrays (or similar structures) we need a separate variable for each gradedouble grade1 = 0;double grade2 = 0;double grade3 = 0;…double grade42 = 0;double grade43 = 0;double grade44 = 0;
Let's assume that these are global variables declared outside the main function
Average Grades …
We need to input the data into each variable We also need to make sure that grades are
entered in the correct variables if (count == 1)
scanf(&grade1);else if (count == 2)
scanf(&grade2);…else if (count == 44)
scanf(&grade44);
This big, ugly IF statement should go in an input function
Assume that input is from the keyboard
And could be written as a switch statement
Average Grades …
Assume that all of the grades have been entered We can now calculate the average
Let’s make a separate function to do this double getAverage( … )
Ideally, functions should be self contained Input is passed using a parameter list And the desired output is returned But we would need 44 parameters for this
function!▪ So, let’s just use the previously defined global
variables▪ Which is bad, because global variables
Average Grades …
double getAverage (){double sum = 0;sum += grade1;sum += grade2;sum += grade3;sum += grade4;sum += grade5;sum += grade6;sum += grade7;sum += grade8;sum += grade9;
This is what the getAverage function would look like …
Average Grades …
// …sum += grade10;sum += grade11;sum += grade12;sum += grade13;sum += grade14;sum += grade15;sum += grade16;sum += grade17;sum += grade18;sum += grade19;
You can’t put this in a loop because the variable that is added is different each time
Average Grades …
// … sum += grade20;sum += grade21;sum += grade22;sum += grade23;sum += grade24;sum += grade25;sum += grade26;sum += grade27;sum += grade28;sum += grade29;
Good thing it’s not a class with 250 students in it or this would be really boring
Average Grades …
// … sum += grade30;sum += grade31;sum += grade32;sum += grade33;sum += grade34;sum += grade35;sum += grade36;sum += grade37;sum += grade38;sum += grade39;
Are we there yet?
Average Grades …
// … sum += grade40;sum += grade41;sum += grade42;sum += grade43;sum += grade44;return sum / 44;
}
Right, done, that’s it!
… And Finally …
Here is the same function, this time assuming that the grade data was stored in an arraydouble getAverage(double arr[], int size){
double sum = 0;for (int i = 0; i < size; ++i){sum += arr[i];
}return sum / size;
}
What Is An Array?
An array variable is a collection of other variables You can think of an array as something
that contains variables This is important because an integer
array is not an integer, it is a collection of integers
The items stored in an array (elements) are stored sequentially in main memory This is an important implementation
issue
Declaring Arrays
An array is declared with a type, and []s to indicate that the variable is an array The type is the type of the contents of
the arrayint score[10]
type of the data stored in the array
brackets declare the variable as an array
size of the array
Array Indexing
The elements of the array are accessed using an index Indexes are the addresses of the
elements▪ The first element always has an index of 0▪ The last index is always array size – 1
Array indexes follow the name of the array and are enclosed in []s Individual array elements are used in
exactly the same way as variables
Using an Array
1 2 3 4 4 3
arr[0]
arr[1]
arr[2]
arr[3] i x
represents stack memory, where each cell represent 4 bytes
int arr[4];int x;for(int i = 0; i < 4; ++i){
arr[i] = i + 1;}x = arr[2]; //access 3rd. element
result of the statements shown above
Initializing Arrays
Array elements have to be given values individually Although this can be performed in a loop
There is a special shorthand notation for initializing arrays when they are declared int arr[] = {1, 3, 7, 9}; This shorthand notation is only allowed
on the same line as the declaration
Array Size
Array size must be specified when the array is declared It must be a literal (a number) or A constant The size can not be given using a
variable Therefore an array's size cannot
change during the life of a program It is specified at compile time
Arrays and Loops
Arrays are often processed using loops Each element in an array is accessed in
turn The loop control variable is used as an
index into the array The loop terminates once every element
of the array has been processed▪ When the loop control variable is equal to the
size of the array
For Loops
// Assume an int array named arr,// and a constant called ARR_SIZE// The loop prints the contents of arr
for (int i = 0; i < ARR_SIZE; i++){printf("%d\n", arr[i]);
}
The condition is i < ARR_SIZE because the last legal index is ARR_SIZE – 1
While Loops
// Assume an int array named arr,// and a constant called ARR_SIZE// The loop prints the contents of arr
int i = 0;while (i < ARR_SIZE){
printf("%d\n", arr[i]);i++;
} A very similar loop to the for loop, don't forget to increment the index, i
Size as a Constant
It is much better to define array size as a constant than to use a literal value
If the programmer wants to change the array size this only needs to be done once Use the constant whenever the array
size is referenced, and Avoid using magic numbers!
Index Out of Bounds
What happens if a program attempts to access a non-legal index?
A run-time error occurs, either An illegal attempt to access a memory
location has been made (… stack is corrupted …) , or
Something less predictable Always ensure that an index is legal
Between 0 and array size – 1
Aside – Using Arrays
Make sure that you distinguish between an array and its contents int arr[4];▪ arr is the entire array▪ arr[1] is one element of the array
The array is a container of integers, one element is an integer They are not interchangeable
Is the Array Full?
It is often important to know how much of an array is used Unassigned elements shouldn't be
processed▪ e.g. summing or calculating the average of an
array Consider what input a function
requires The array, and its maximum size The array, and current size▪ i.e. the number of elements actually used
The array, its maximum size, and its current size
Arrays and Functions
Array and Functions
Arrays arguments can be passed to functions So parameter lists can include arrays The array type, and the fact that it is an
array must be specified in the parameter list▪ An array is specified just like any declaration
A function header for an array sum function int sumArray(int arr[], int size){
Sum Function
// Sums the array, returning the sumint sumArray(int arr[], int size){
int sum = 0;for (int i = 0; i < size; i++){
sum += arr[i];}return sum;
}
size is used to specify the size of the arrayTo use this function give it the appropriate arguments like any other function
x = sumArrray(myArr, ARR_SIZE);
notice no []s, it’s the name of the variable, not a declaration
Searching Arrays
A common array task is to search an array for a particular value
int search(int arr[], int size, int x){for (int i = 0; i < size; i++){
if (arr[i] == x)return i;
}return -1;
} Return -1 if the target is not found, as it is not a valid array index
Return the index of the target as soon as it is found
Changing Array Contents
What happens if you pass an array to a function that changes the array parameter?
void doubleArray(int arr[], int size){for (int i = 0; i < size; i++){
arr[i] = arr[i] * 2;}
}
The function doubles each of the values stored in the array parameter
Array Parameters
int main(){
int arr[] = {1, 2, 3};doubleArray(arr, ARR_SIZE);for(int i = 0; i < 3; ++i){
printf("%d\n",arr[i]);}return 0;
}What has happened? The elements of the array passed to the function have changed, this normally doesn't happen with arguments …Remember that an array variable is actually a pointer to the first element of the array
What's an Array?
To understand what is going on in the previous example we need to know more It's easy to think of an array as a
container, like a bookcase But a bookcase is a structure in its own
right An array is just a collection of values
All of the same type, and Stored in sequence in main memory
More About Arrays
An array is a sequence of bytes in main memory reserved for the array contents e.g. int arr[10]; ▪ Reserves 40 contiguous bytes (4 byte ints, 4 * 10 =
40)
▪ Each element can be referenced using indexes So arr is a pointer to the first array element
Containing the address of the first array element These two statements print the same address▪ printf("%p", arr);
▪ printf("%p", &arr[0]);
More About Indexing
Consider this assignment statement: arr[8] = 23;
To find this array element Look up the address stored in arr Multiply type size (4 for an int) by the
index Add this to the address to find the
element Known as an offset calculation
Sorting Arrays
It is sometimes useful that a function changes an array passed to it A common example of this is sorting an
array There are many different sorting
algorithms Selection sort, Insertion sort, Bubble
sort, ... Quicksort, Mergesort, Radix sort, ...
The algorithms differ in how efficient they are
Selection Sort
Selection sort is a simple sorting algorithm that repeatedly finds the smallest item The array is divided into a sorted part
and an unsorted part Repeatedly swap the first unsorted
item with the smallest unsorted item Starting with the element with index 0,
and Ending with last but one element (index
n – 1)
Selection Sort
23 41 33 81 07 19 11 45 find smallest unsorted - 7 comparisons
07 41 33 81 23 19 11 45 find smallest unsorted - 6 comparisons
07 11 33 81 23 19 41 45 find smallest unsorted - 5 comparisons
07 11 19 81 23 33 41 45 find smallest unsorted - 4 comparisons
07 11 19 23 81 33 41 45 find smallest unsorted - 3 comparisons
07 11 19 23 33 81 41 45 find smallest unsorted - 2 comparisons
07 11 19 23 33 41 81 45 find smallest unsorted - 1 comparison
07 11 19 23 33 41 45 81
void selectionSort(int arr[], int size){for(int i = 0; i < size -1; ++i){
int smallest = i;// Find the index of the smallest elementfor(int j = i + 1; j < size; ++j){
if(arr[j] < arr[smallest]){smallest = j;
}}// Swap the smallest with the current itemtemp = arr[i];{arr[i] = arr[smallest];arr[smallest] = temp;
}}
Selection Sort Algorithm
inner loop
outer loop
Terminating Loops
Be careful when specifying loop conditions Particularly when working with arrays Being off by one with an index value
may result in a runtime error▪ Or worse ...
Where possible use <, >, <=, or >= as conditions rather than == or != As an example of this we will look at a
function to reverse the contents of an array
Print Array Function
// Function to print an integer arrayvoid printArray(int arr[], int size){
printf("{");for(int i=0; i < size; i++){
printf("%d", arr[i]);if(i != size-1){
printf(",");}
}printf("}");
}
This function prints the contents of a (small) array
Separates array elements by commas
Note that I didn't use i != size here
Reverse Function
// Function to reverse the contents of an arrayvoid reverse(int arr[], int size){
int lo, hi;for(lo=0, hi=size-1; lo!=hi; lo++, hi--){
int temp = arr[lo];arr[lo] = arr[hi];arr[hi] = temp;
}}
Now let's write the function to reverse an array
This version is broken!
Testing Reverse
int arr[] = {1,2,3,4,5,6,7};int arr_size = sizeof(arr)/sizeof(int);printArray(arr, arr_size);reverse(arr, arr_size);printf("\n\n");printArray(arr, arr_size); so far, so good ...
int arr[] = {1,2,3,4,5,6,7,8};int arr_size = sizeof(arr)/sizeof(int);printArray(arr, arr_size);reverse(arr, arr_size);printf("\n\n");printArray(arr, arr_size);
the for condition should have been lo < hi
they didn`t ...
Array Size Revisited
As noted previously array size must be given a constant value And the size of an array cannot be
changed while the program is running (during run-time)
This is to support the organization of stack memory
It's possible to allocate memory at run-time From a free store of memory, called
dynamic memory
more on this later ...
Returning Arrays
Arrays can be returned from a function However the obvious way of specifying
the return type is illegal▪ int[] getAnArray() { …
In addition, returning an array raises the question of how big it is
This doesn't work
more on this later ...
Recursion
More Repetition
We've seen while loops and for loops – two methods of performing repetition There is another way to repeat a process▪ That uses function calling instead of loops
Consider the (much seen) factorial example Note that the factorial of 5 = 5 *4! ▪ Let`s state this more generally
The factorial of x = x * (x - 1)! And the factorial of 1 = 1
Yet Another Factorial Function
Let's write a C function to compute factorials using the ideas presented previously x! = x * (x - 1)! and 1! = 1// PRE: x must be a +ve integer
// Function that returns the factorial of xlong long fact4(int x){
if(x == 1){
return 1;}else{
return x * fact4(x-1);}
}
does this work?
Testing Factorial
void recursionTest(){
int x = 10;printf("%d! = %lld", x, fact4(x));
}
incidentally, in case you were wondering why these functions return long longs, here is 20!
Recursive Functions
The fact4 function is a recursive function Because it calls itself
// PRE: x must be a +ve integer// Function that returns the factorial of xlong long fact4(int x){
if(x == 1){
return 1;}else{
return x * fact4(x-1);}
}
base case
recursive case
Recursive Functions
The fact4 function is recursive A recursive function calls itself Each call to a recursive function results in a
separate call to the function, with its own input Recursive functions are just like other
functions The invocation is pushed onto the call stack And removed from the call stack when the end
of the function or a return statement is reached Execution returns to the previous function call
data ... 4 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
data ... 4 4 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
x result
data ... 4 4 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 0 3 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
fact(3)
x result x result
data ... 4 4 0 3 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 0 3 0 2 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
fact(3)
fact(2)
x result x result x result
data ... 4 4 0 3 0 2 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 0 3 0 2 0 1 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
fact(3)
fact(2)
fact(1)
x result x result x result x result
data ... 4 4 0 3 0 2 0 1 0 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 0 3 0 2 0 1 1 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
fact(3)
fact(2)
fact(1)
x result x result x result x result
data ... 4 4 0 3 0 2 0 1 1 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 0 3 0 2 2 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
fact(3)
fact(2)
x result x result x result
data ... 4 4 0 3 0 2 2 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 0 3 6 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
fact(3)
x result x result
data ... 4 4 0 3 6 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 4 24 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
fact(4)
int x = 4;printf("%d! = %d", x, factorial(x));
x result
data ... 4 4 24 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
data ... 4 ...
address ... 2056 2060 2064 2068 2072 2076 2080 2084 2088 ...
Recursion and Memory
int factorial(int x){ int result = 0; if(x == 1) result = 1; else result = x * factorial(x-1); return result;}
call stack – shown as 4 byte cells (since we just allocate space for ints)
slightly different version to show what is going on in memory
int x = 4;printf("%d! = %d", x, factorial(x));
Recursive Function Anatomy
Recursive functions do not use loops to repeat instructions But use recursive calls, in if statements
Recursive functions consist of two or more cases, there must be at least one Base case, and one Recursive case
Base Case
The base case is a smaller problem with a simpler solution This problem’s solution must not be
recursive▪ Otherwise the function may never terminate
There can be more than one base case And base cases may be implicit
Recursive Case
The recursive case is the same problem with smaller input The recursive case must include a
recursive function call There can be more than one recursive
case
Finding Recursive Solutions
Define the problem in terms of a smaller problem of the same type The recursive part e.g. return x * factorial(x-1);
And the base case where the solution can be easily calculated This solution should not be recursive e.g. if (x == 1) return 1;
Designing Recursive Solutions
How can the problem be defined in terms of smaller problems of the same type? By how much does each recursive call
reduce the problem size? By 1, by half, …?
What is the base case that can be solved without recursion? Will the base case be reached as the
problem size is reduced?
Warning – Stack Overflow
Here is a recursive sum function (very similar to factorial)
int sum(int x){if(x == 1){
return 1;}else{
return x + sum(x-1);}
}
And here is what happens when you call sum(5000)
Stack Overflow
Recursive algorithms have more overhead than similar iterative algorithms Because of the repeated function calls This may cause a stack overflow▪ The area of memory allocated to the call stack is used
up Some algorithms can still be implemented
recursively in a safe way Will the recursive factorial cause a stack
overflow?