Preview of Pointers

Download Report

Transcript Preview of Pointers

CS 108 Computing
Fundamentals
April 2, 2015
Review Exam #2
•
Grades not as good as I hoped
•
I drop the lowest of the first 3 exams
•
Exam #3 and #4 will cover much of the same ground
•
We will use today's review of Exam #2 as a means to clear-up
some lack of understanding as well as exam strategy
Recursion
Pronunciation: ree-kur-zhun Function: noun
Etymology: Late Latin recursion, recursio, from recurrere
1 : RETURN
2 : the determination of a succession of elements (as numbers or
functions) by operation on one or more preceding elements
according to a rule or formula involving a finite number of steps
3 : a computer programming technique involving the use of a
procedure, subroutine, function, or algorithm that calls itself in
a step having a termination condition so that successive
repetitions are processed up to the critical step until the
condition is met at which time the rest of each repetition is
processed from the last one called to the first.
Compare with ITERATION
Recursion
•
A recursive function is a function that calls itself.
•
Anything that can be solved iteratively can be also be
solved recursively and vice versa.
•
Recursion is sometimes useful because the recursive
solution to a problem can sometimes be expressed more
simply and succinctly than an iterative solution.
•
Let’s look at a classic example
Example: Factorial
Main Entry: factorial Function: noun
1 : the product of all the positive integers from 1 to n ;
symbol n!
2 : the quantity 0! arbitrarily defined as equal to 1
http://en.wikipedia.org/wiki/Factorial
Example: Factorial
factorial(0) = 1 (by definition… see previous slide)
factorial(1) = 1 * 1
factorial(2) = 2 * 1 *1
factorial(3) = 3 * 2 * 1 *1
factorial(4) = 4 * 3 * 2 *1 *1
factorial(5) = 5 * 4 * 3 * 2 *1 *1
factorial(6) = 6 * 5 * 4 * 3 * 2 *1 *1
factorial(7) = 7 * 6 * 5 * 4 * 3 * 2 *1 *1
factorial(8) = 8 *7 * 6 * 5 * 4 * 3 * 2 *1 *1
First: Factorial Via Iteration
#include <stdio.h> // 1.c
int factorial ( int ) ;
int main (void)
{
int input = 0 , answer = 0;
printf("\n\n The program computes the factorial of an entered integer. ") ;
printf("\n Enter an postive integer: ") ;
scanf("%d", &input ) ;
answer = factorial ( input ) ;
printf("\n\n %d factorial equals: %d \n\n" , input , answer ) ;
return (0) ;
}
// continued on next slide
First: Factorial Via Iteration
// continued from previous slide
int factorial ( int passed_input )
{
int index = 1 , result = 1;
for ( index = 1 ; index <= passed_input ; index++ )
{
result = result * index ;
}
return (result) ;
}
Factorial Via Recursion
factorial(0) = 1 (by definition)
factorial(1) = 1 * 1 is the same as 1 * factorial(0)
factorial(2) = 2 * 1 * 1 is the same as 2 * factorial(1)
factorial(3) = 3 * 2 * 1 * 1 is the same as 3 * factorial(2)
factorial(4) = 4 * 3 * 2 * 1 * 1 is the same as 4 * factorial(3)
factorial(5) = 5 * 4 * 3 * 2 * 1 * 1 is the same as 5 * factorial(4)
factorial(6) = 6 * 5 * 4 * 3 * 2 * 1 * 1 is the same as 6 * factorial(5)
factorial(7) = 7 * 6 * 5 * 4 * 3 * 2 * 1 * 1 is the same as 7 * factorial(6)
factorial(8) = 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 * 1 is the same as 8 * factorial(7)
•
Is there a general way to state our observation of factorials (above)
into rules for an algorithm using factorial(n) as a starting point?
Factorial Via Recursion
factorial(0) = 1 (by definition)
factorial(1) = 1 * 1 is the same as 1 * factorial(0)
factorial(2) = 2 * 1 * 1 is the same as 2 * factorial(1)
factorial(3) = 3 * 2 * 1 * 1 is the same as 3 * factorial(2)
factorial(4) = 4 * 3 * 2 * 1 * 1 is the same as 4 * factorial(3)
factorial(5) = 5 * 4 * 3 * 2 * 1 * 1 is the same as 5 * factorial(4)
factorial(6) = 6 * 5 * 4 * 3 * 2 * 1 * 1 is the same as 6 * factorial(5)
factorial(7) = 7 * 6 * 5 * 4 * 3 * 2 * 1 * 1 is the same as 7 * factorial(6)
factorial(8) = 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 * 1 is the same as 8 * factorial(7)
•
•
If n = = 0 then answer = 1 … factorial(0) = 1
For all other cases, what is the relationship between factorial(n) on
the left side of the assignment operator and the formula on the right
side? The next slide might be more helpful.
Factorial Via Recursion
factorial(0) = 1 (by definition)
factorial(1) = 1 * factorial(0)
factorial(2) = 2 * factorial(1)
factorial(3) = 3 * factorial(2)
factorial(4) = 4 * factorial(3)
factorial(5) = 5 * factorial(4)
factorial(6) = 6 * factorial(5)
factorial(7) = 7 * factorial(6)
factorial(8) = 8 * factorial(7)
•
factorial ( n ) = ??
For all cases other than n = = 0, what is the relationship between
factorial(n) on the left side of the assignment operator and the
formula on the right side?
Factorial Via Recursion
•
First:
answer = 1 if n = = 0 … factorial(0) = 1
•
Second:
otherwise: factorial(n) = n * factorial( n - 1 )
•
Notice that the identifier "factorial" appears on both sides
of the assignment operator
•
How would we write a factorial function to implement
these two rules into a C algorithm ?
Factorial Via Recursion
•
First:
1 if n = 0
•
Second:
n>0
factorial( n ) = n * factorial( n-1 )
int factorial ( int n )
{
if n = = 0
return 1 ;
else
return ( n * factorial ( n – 1 ) );
}
if
Understanding Recursion
•
You can think of a recursive function call as if it were
calling a completely separate function.
•
Understand this about recursively called functions: the
operations that can be performed by recursively called
functions are the same, but the data that is input to each
recursively called function is different
•
The next slide might help to visualize the sameness of
operations and the differences in data through the use of
different (but very, very similar) functions... we’ll pass
factorial_a the value 3.
Understanding Recursion
int factorial_a ( int m )
{
if ( m = = 0 )
return 1;
else
return m * factorial_b ( m - 1 ) ;
}
int factorial_c ( int q )
{
if( q = = 0 )
return 1;
else
return q * factorial_d ( q - 1) ;
}
int factorial_b ( int n )
{
if ( n = = 0 )
return 1;
else
return n * factorial_c ( n - 1) ;
}
int factorial_d ( int r )
{
if( r = = 0 )
return 1;
else
return r * factorial_e ( r - 1) ;
}
•
Let's develop a symbol table for the previous slide which is
incorporated in this program (this program can handle 0 – 3 as inputs,
which is enough to demonstrate the concepts) :
http://web.cs.sunyit.edu/~urbanc/cs_108_mar_31a.txt
•
Let's look at the addresses and values of the variables/parameters
http://web.cs.sunyit.edu/~urbanc/cs_108_mar_31b.txt
•
Notice that each version of the factorial functions does the same thing
Therefore, we can condense this into something more general
•
Recursion Example: Factorial
#include <stdio.h> // 2.c
int factorial ( int ) ;
int main (void)
{
int input = 0 , answer = 0;
printf("\n\n The program computes the factorial of an entered integer. ") ;
printf("\n Enter an postive integer: ") ;
scanf("%d", &input ) ;
answer = factorial ( input ) ;
printf("\n\n %d factorial equals: %d \n\n" , input , answer ) ;
return 0 ;
}
int factorial ( int passed_input )
{
if ( passed_input = = 0) // if cutting, remove the extra space between = and =
return 1 ;
else
return ( passed_input * factorial ( passed_input - 1 ) ) ;
}
•
•
Let's develop a symbol table for the previous slide
which is incorporated in this program:
http://web.cs.sunyit.edu/~urbanc/cs_108_mar_31c.txt
Questions to Guide The Use of Recursion
•
•
•
Can you define the problem in terms of smaller
problem(s) of the same type?
- Think about the factorial problem:
factorial(n) = n * factorial ( n-1 ) if n > 0
Does each recursive call reduce the size of the
problem?
As the problem "shrinks", will you eventually reach a
point where an obvious solution presents itself?
- Again, think about the factorial problem:
factorial (0) = 1
Files and File Access
•
•
•
•
Thus far we have used volatile memory (primary storage)
in our programs
Volatile memory has certain advantages and disadvantages
Long-term storage requires the use of secondary storage
Data files are used by programmers to store and retrieve
data in secondary storage
Files and File Access
•
Data file hierarchy:
- bits (binary digits… 0’s and 1’s)
- bytes (bits grouped together (in 8’s) to form a single
character)
- words or fields (logical groupings of bytes (characters)
that, taken together, can represent data or information
(data in context))
- records (logical groupings of fields that describe an
object or entity)
- files (a collection of records)
Files and File Access
•
•
•
•
In C a file can refer to a data file, but in C a file can also
refer to any concrete device with which we want to
exchange data (monitor, printer, tape drive, hard disk,
etc…)
In C a file stream is the flow of data between a program and
a file
File streams are a series of bytes
File streams are not device dependent… all streams have the
same behavior
Files and File Access
•
•
•
•
File streams have two formats:
- text stream (think readable data or text)
- binary stream (non-readable… think .exe files)
We use pointers to manage file streams that read and write
data… pointers that are used to manage file streams are
called file pointers
C provides an internal structure named FILE that is used to
declare file pointers
We use FILE as a data type when we declare a file pointer
FILE *file_pointer_name ;
#include <stdio.h> // Example of declaring a file pointer using FILE.
int main (void)
{
FILE *read_ptr;
// The names and the number of file pointers
FILE *write_ptr;
// used in program: determined by
FILE *append_ptr; // the programmer.
// We will need to assign a file to a file pointer.
return (0) ;
}
Files and File Access
•
To work with files in C we must do four things:
- create a file pointer (using FILE)
- assign an existing file to the file pointer (using fopen)
•
process the file (read and/or write, transform)
- close the file (using fclose)
stdio.h contains the function fopen
fopen is used in an assignment statement to pass a file
address to a previously declared (by the programmer… us)
file pointer
-
•
•
opens the file (should test the file when opening)
Opening a File
•
fopen syntax:
FILE *file_pointer_name ;
file_pointer_name = fopen ("file_name", "file_mode");
•
fopen example:
FILE *read_ptr ;
read_ptr = fopen ("student_1.dat", "r");
Opening a File
•
File mode: specifies the way to open the file:
"r" opens and existing file for reading
"w" creates a text file for writing
"a" opens an existing file for appending
Opening a File
•
File mode: specifies the way to open the file:
"r+" opens an existing file for reading and/or writing
"w+" creates a text file for reading and/or writing
"a+" opens or creates a file for appending
"rb" creates a binary file for writing
"wb" creates a binary file for writing
"ab" opens an existing binary file for appending
"r+b" opens an existing binary file for reading and/or writing
"w+b" creates a binary file for reading and/or writing
"a+b" opens or creates a binary file for appending
Opening a File
#include <stdio.h> //example of declaring and assigning a file pointer
int main (void)
{
FILE *read_ptr ;
read_ptr = fopen("student_1.dat", "r");
return (0) ;
}
•
•
It’s considered "good practice" to check each file pointer
assignment so that you know each file is successfully
opened
If fopen( ) fails to open the file, a NULL is returned and
assigned to the pointer to the let of the assignment operator
Opening a File and Checking It
#include <stdio.h>
//example of declaring and assigning a file pointer
//then checking it
int main (void)
{
FILE *read_ptr ;
read_ptr = fopen("student_1.dat", "r");
if (read_ptr == NULL)
printf("\n\nstudent_1.dat was not properly opened.\n");
else
printf("\n\nstudent_1.dat is opened in the read mode.\n");
return (0) ;
}
Reading a File: Single Field/Single Record
•
fscanf is used like scanf for files… in stdio.h… then fclose
#include <stdio.h> //3.c
int main (void)
{
FILE *read_ptr ;
char last_name [15];
read_ptr = fopen("student_1.dat", "r");
if (read_ptr == NULL)
printf("\n\n student_1.dat was not properly opened.\n\n");
else
{
printf("\n\n student_1.dat is opened in the read mode.\n\n");
fscanf(read_ptr , "%s" , last_name);
printf("%s \n\n" , last_name);
fclose(read_ptr);
}
return (0) ;
}
Reading a File: Single Field/Multiple Records
•
feof is used to check for a file’s EOF marker
#include <stdio.h> //4.c
int main (void)
{
FILE *read_ptr ;
char last_name [15];
read_ptr = fopen("student_2.dat", "r");
if (read_ptr == NULL)
printf("\n\nstudent_2.dat was not properly opened.\n");
else
{
printf("\n\nstudent_2.dat is opened in the read mode.\n\n");
fscanf (read_ptr, "%s", last_name );
while ( !feof (read_ptr) )
{
printf ("%s \n", last_name);
fscanf (read_ptr , "%s", last_name );
}
fclose(read_ptr);
}
return (0) ;
}
Reading a File: Multiple Fields and Records
#include <stdio.h> //5.c
int main (void)
{
FILE *read_ptr ;
char last_name [15];
char major [15];
read_ptr = fopen("student_3.dat", "r");
if (read_ptr == NULL)
printf("\n\nstudent_3.dat was not properly opened.\n");
else
{
printf("\n\nstudent_3.dat is opened in the read mode.\n\n");
fscanf (read_ptr, "%s %s" , last_name , major ) ;
while ( !feof (read_ptr) )
{
printf ("%s %s \n", last_name, major);
fscanf (read_ptr , "%s %s", last_name , major);
}
fclose(read_ptr);
}
return (0) ;
}
Writing a File: Use fprintf and fclose
#include <stdio.h> //6.c
int main (void)
{
FILE *write_ptr ;
char last_name [15];
char major [15];
write_ptr = fopen("student_3.dat", "w"); // need "w" for mode
if (write_ptr == NULL)
printf("\n\nstudent_3.dat was not properly opened.\n");
else
{
printf("\n\nEnter the last name and major: ");
scanf ("%s %s", last_name , major);
fprintf (write_ptr, "%s %s \n", last_name, major);
}
fclose (write_ptr);
return (0);
}
Appending a File: Use fprintf and fclose
#include <stdio.h> //7.c
int main (void)
{
FILE *append_ptr ;
char last_name [15];
char major [15];
append_ptr = fopen("student_3.dat", "a"); //need "a" for mode
if (append_ptr == NULL)
printf("\n\nstudent_3.dat was not properly opened.\n");
else
{
printf("\n\nEnter the last name and major: ");
scanf ("%s %s", last_name , major);
fprintf (append_ptr, "%s %s \n", last_name, major);
}
fclose (append_ptr);
return (0) ;
}
Writing an Array to a File
#include <stdio.h> //8.c
int main(void)
{
FILE *scores_ptr;
int score_array[10] = { 97, 65, 72, 84, 79, 81, 91, 93, 67, 73 };
int x = 0 ;
scores_ptr = fopen("test_scores.dat" , "w");
if(scores_ptr == NULL)
printf("\n\ntest_scores.dat was not properly opened.\n");
else
{
for(x = 0 ; x < 10 ; x++ )
{
fprintf(scores_ptr , "%d\n" , score_array[x]);
}
fclose(scores_ptr);
printf("All ten exam scores saved to disk.\n\n\n");
}
return(0);
}
Reading an Array From a File
#include <stdio.h> //9.c
int main(void)
{
FILE *scores_ptr ;
int score_array[10] ;
int x = 0;
scores_ptr = fopen("test_scores.dat" , "r");
if(scores_ptr == NULL)
printf("\n\ntest_scores.dat was not properly opened.\n");
else
{
for(x = 0 ; x < 10 ; x++ )
{
fscanf(scores_ptr ,"%d" , &score_array[x]);
}
fclose(scores_ptr);
for(x = 0 ; x < 10 ; x++ )
printf("Exam #%d score is %d \n", x + 1, score_array[x]);
}
return(0);
}
#include <stdio.h> //10.c
int main(void)
{
FILE *scores_ptr;
int score_array[10] [3];
int x = 0 ;
scores_ptr = fopen("test_scores_2.dat" , "r");
if(scores_ptr == NULL)
printf("\n\ntest_scores_2.dat was not properly opened.\n");
else
{
for(x = 0 ; x < 10 ; x++ )
{
fscanf(scores_ptr ,"%d %d", &score_array[x] [0], &score_array[x] [1]) ;
score_array[x] [2] = score_array[x] [0] + score_array[x] [1] ;
}
fclose(scores_ptr);
for(x = 0 ; x < 10 ; x++ )
printf("Student #%d scores and total: \t %d \t %d \t %d\n\n\n",
x + 1, score_array[x] [0] , score_array[x] [1] , score_array[x] [2] );
}
return(0);
}