ICOM 4015 Advanced Programming Lecture 2 Procedural Abstraction
ICOM 4015 Advanced Programming Lecture 2 Procedural Abstraction Reading: LNN Chapter 4, 14 Prof. Bienvenido Velez FALL 2001 ICOM 4015 - Lecture 2 1
Procedural Abstraction Topics • Topic 1 – Functions as abstract contracts – Parameter passing – Scoping • Topic 2 – Functional arguments • Topic 3 – Top-down modular design – Stepwise refinement • Topic 4 – Recursive functions – Recursion vs. Iteration • Topic 5 – Further procedural abstraction – Function overloading and templates FALL 2001 ICOM 4015 - Lecture 2 2
Procedural Abstraction I Outline • Functions as abstract contracts • Value/Reference parameters • Procedural Abstraction Defined • Scope Rules FALL 2001 ICOM 4015 - Lecture 2 3
Example 0 Finding the roots of ax 2 +bx + c #include <cmath> // // // roots(a, b, c, r 1, r 2) - returns the number of real roots of ax^2 + bx + c. If two roots exists they are returned is r 1 and r 2. If only one root exists, it is returned in r 1. Otherwise the value of r 1 and r 2 is undetermined. WHAT? int roots(float a, float b, float c, float& r 1, float& r 2) { float d = b * b - 4. 0 * a * c; if (d < 0) { formal parameters return 0; } r 1 = (-b + sqrt(d)) / (2. 0 * a); if (d == 0) { HOW? return 1; } r 2 = (-b - sqrt(d)) / (2. 0 * a); return 2; } roots. cc definitions int roots(float a, float b, float c, float& r 1, float& r 2); roots. h declarations FALL 2001 ICOM 4015 - Lecture 2 4
Procedural Abstraction • A function should accomplish ONE well defined and easy to remember task • A function establishes a contract between callers and implementers • The implementer may select any implementation that satisfies the contract. • The contract should specify WHAT task the function accomplishes, NOT HOW it accomplishes it “HOW” is hidden or abstracted out, hence the name procedural abstraction FALL 2001 ICOM 4015 - Lecture 2 5
Scope Rules & Parameter Passing Mechanisms #include <iostream> Global in Module // Forward definitions int f(int& x); // Global definitions static int x = 0; int y = 0; Global int main() { for (int i=0; i < 5; i++) int arg = x; int r = f(x); cout << " f(" << arg << cout << " Glob x=" << x cout << " Glob y=" << y } } int f(int& x) { int y=0; static int z=0; y++; z+=2; x = y + z; cout << " Loc x=" << x; cout << " Loc y=" << y; cout << " Loc z=" << z; return z; } { ") -> " << r; << endl; [bvelez@amadeus] ~ >> scope 1 Loc x=3 Loc y=1 Loc z=2 f(0) -> 2 Loc x=5 Loc y=1 Loc z=4 f(3) -> 4 Loc x=7 Loc y=1 Loc z=6 f(5) -> 6 Loc x=9 Loc y=1 Loc z=8 f(7) -> 8 Loc x=11 Loc y=1 Loc z=10 f(9) -> [bvelez@amadeus] ~ >> FALL 2001 Local to For Loop Local to Block Local to Function Glob x=3 Glob y=0 Glob x=5 Glob y=0 Glob x=7 Glob y=0 Glob x=9 Glob y=0 10 Glob x=11 Glob y=0 ICOM 4015 - Lecture 2 6
Diagramas de Bloques x: y: main: for: i: arg: r: f: x: y: z: FALL 2001 ICOM 4015 - Lecture 2 7
Procedural Abstraction I Summary of Concepts • Value parameters – changes remain local to function. Function works with a copy of the argument. • Reference parameters – changes propagate to argument. Function works with original argument. • Procedural abstraction – a function establishes a contract with its callers on what it accomplishes, hiding how it accomplishes it. FALL 2001 ICOM 4015 - Lecture 2 8
Procedural Abstraction I - Scoping Summary of Concepts II • Definition: Scope of a declaration – region of code where declaration is active • Scope rules allow better control over the namespace • Local namespaces (e. g. functions, blocks) independent of each other • Local declarations take precedence over global declarations FALL 2001 ICOM 4015 - Lecture 2 9
Procedural Abstraction II Outline • Procedural arguments FALL 2001 ICOM 4015 - Lecture 2 10
Integration Without Procedural Arguments #include <iostream> // Forward definitions double integrate. Sqr(double a, double b, double n); double integrate. Cube(double a, double b, double n); int main() { cout << "Integral of x^2 in [0, 1] = " << integrate. Sqr(0. 0, 10000) << endl; cout << "Integral of x^3 in [0, 1] = " << integrate. Cube(0. 0, 10000) << endl; } double integrate. Sqr(double a, double b, double n) { double delta = (b-a) / double(n); double sum = 0. 0; for (int i=0; i<n; i++) { float x = a + delta * i; sum += x * delta; } return sum; } double integrate. Cube(double a, double b, double n) { double delta = (b-a) / double(n); double sum = 0. 0; for (int i=0; i<n; i++) { float x = a + delta * i; sum += x * x * delta; } return sum; } [bvelez@amadeus] ~/icom 4015/lec 05 >> example 2 Integral of x^2 in [0, 1] = 0. 333283 Integral of x^3 in [0, 1] = 0. 24995 [bvelez@amadeus] ~/icom 4015/lec 05 >> FALL 2001 ICOM 4015 - Lecture 2 11
Example 3 Integration With Procedural Arguments #include <iostream> // Forward definitions double integrate(double a, double b, double n, double f(double x)); double cube(double x); double sqr(double x); int main() { cout << "Integral of x^2 in [0, 1] = " << integrate(0. 0, 10000, sqr) << endl; cout << "Integral of x^3 in [0, 1] = " << integrate(0. 0, 10000, cube) << endl; } double integrate(double a, double b, double n, double f(double x)) { double delta = (b-a) / double(n); double sum = 0. 0; for (int i=0; i<n; i++) { sum += f(a + delta * i) * delta; } return sum; } double cube(double x) { return x * x; } double sqr(double x) { return x * x; } [bvelez@amadeus] ~/icom 4015/lec 05 >> example 2 Integral of x^2 in [0, 1] = 0. 333283 Integral of x^3 in [0, 1] = 0. 24995 FALL 2001 ICOM 4015 - Lecture 2 [bvelez@amadeus] ~/icom 4015/lec 05 >> 12
Procedural Abstraction II Functional Arguments Summary of Concepts • Functional arguments – Allow abstraction over processes and functions FALL 2001 ICOM 4015 - Lecture 2 13
Procedural Abstraction III Outline • Top-down stepwise refinement FALL 2001 ICOM 4015 - Lecture 2 14
Step 0 - Outline // // // top-down. cc Computes weighted average score of grades. Grades include two assignments two midterm exams and one final exam. All grades are input from standard input, but the weights of each type of grade are hard coded. // C header files extern "C" { } // Standard C++ header files #include <iostream> // My own C++ header files // Macro definitions // Forward definitions of auxiliary functions // Global declarations // Main function int main() { // Read assignment grades // Read exam grades // Read final exam grade // Calculate average // Print report return 0; } // Auxiliary functions FALL 2001 ICOM 4015 - Lecture 2 15
Step 1 – Code + Stubs int main() { float assignment 1, assignment 2; float exam 1, exam 2; float final. Exam; read. Assignment. Grades(assignment 1, assignment 2); read. Exam. Grades(exam 1, exam 2); read. Final. Grade(final. Exam); float avg; avg = calculate. Average(assignment 1, assignment 2, exam 1, exam 2, final. Exam); print. Report(assignment 1, assignment 2, exam 1, exam 2, final. Exam, avg); return 0; } // Auxiliary functions void read. Assignment. Grades(float& assignment 1, float& assignment 2) {} void read. Exam. Grades(float& ex 1, float& ex 2) {} void read. Final. Grade(float& final) {} float calculate. Average(float assignment 1, float assignment 2, float exam 1, float exam 2, float final. Exam) {} void print. Report(float assignment 1, float assignment 2, float exam 1, float exam 2, float final. Exam, float average) {} FALL 2001 ICOM 4015 - Lecture 2 16
Step 2 - Refine // Auxiliary functions void read. Assignment. Grades(float& assignment 1, float& assignment 2) { // Read a float in [0, 100] into assignment 1 // Read a float in [0, 100] into assignment 2 } void read. Exam. Grades(float& ex 1, float& ex 2) { // Read a float in [0, 100] into ex 1 // Read a float in [0, 100] into ex 2 } void read. Final. Grade(float& final) { // Read a float in [0, 100] into final } float calculate. Average(float assignment 1, float assignment 2, float exam 1, float exam 2, float final. Exam) { // Calculate assignments average // Calculate exams average // Calculate weighted average } void print. Report(float assignment 1, float assignment 2, float exam 1, float exam 2, float final. Exam, float average) { // print assignment grades // print exam grades // print final exam grades // print weighted average } FALL 2001 ICOM 4015 - Lecture 2 17
Top-down stepwise refinement cycle outline refine code + stubs FALL 2001 ICOM 4015 - Lecture 2 18
Procedural Abstraction III Top-down design – Stepwise Refinement Summary of Concepts • Top-Down design / stepwise refinement – A cyclic development technique – Each cycle adds a level of detail to the code – We have a functioning (although incomplete) program after every iteration of the process FALL 2001 ICOM 4015 - Lecture 2 19
Procedural Abstraction IV Outline • Recursive Functions – Activation records, call stacks – Expressiveness of recursion vs. iteration – Efficiency concerns • function call overhead • duplication of work • process complexity FALL 2001 ICOM 4015 - Lecture 2 20
Example 0 Factorials // factorials. cc // Implements recursive and interative versions of algorithms for // computing the factorial (N!) of a number. // Standard C++ header files #include <iostream> // Forward definitions of auxiliary functions long rec. Factorial(long n); long iter. Factorial(long n); int main() { long number; while(true) { cout << "Please enter a positive number (or negative to end): "; cin >> number; if (number < 0) return 0; cout << "Recursive: " << number << "! = " << rec. Factorial(number) << endl; cout << "Iterative: " << number << "! = " << iter. Factorial(number) << endl; } } long rec. Factorial(long n) { if (n==0) { return 1; } else { return (n * rec. Factorial(n - 1)); } } [bvelez@amadeus] ~/icom 4015/lec 07 >>factorials Please enter a positive number (or negative to end): Recursive: 3! = 6 long iter. Factorial(long n) Iterative: 3! = 6 { Please enter a positive number (or negative to end): long product = 1; for (long i=1; i<=n; i++) {Recursive: 4! = 24 Iterative: 4! = 24 product *= i; Please enter a positive number (or negative to end): } Recursive: 5! = 120 return product; Iterative: 5! = 120 } Please enter a positive number (or negative to end): Recursive: 6! = 720 Iterative: 6! = 720 FALL 2001 ICOM 4015 - Lecture 2 21 Please enter a positive number (or negative to end): [bvelez@amadeus] ~/icom 4015/lec 07 >>fibonacci 3 4 5 6 -1
Example 1 Fibonacci Numbers // fibonacci. cc // Iterative and recursive algorithms for computing Fibonacci numbers. . . // Auxiliary Functions long rec. Fibonacci(long n) { if (n==0) { return 0; } else if (n==1) { return 1; } else { return (rec. Fibonacci(n-1) + rec. Fibonacci(n-2)); } } long iter. Fibonacci(long n) { if (n==0) { return 0; } else if (n==1) { return 1; } long F 0 = 0; long F 1 = 1; long FN; for (long i=1; i<n; i++) { FN = F 0 + F 1; F 0 = F 1; F 1 = FN; } return FN; } FALL [bvelez@amadeus] ~/icom 4015/lec 07 >>fibonacci Please enter a positive number (or negative to Recursive: F(3) = 2 Iterative: F(3) = 2 Please enter a positive number (or negative to Recursive: F(4) = 3 Iterative: F(4) = 3 Please enter a positive number (or negative to 2001 ICOM 4015 - Lecture 2 Recursive: F(8) = 21 Iterative: F(8) = 21 Please enter a positive number (or negative to end): 3 end): 4 end): 8 end): 22
Example 1 Fibonacci Numbers // fibonacci. cc // Iterative and recursive algorithms for computing Fibonacci numbers // Standard C++ header files #include <iostream> // Forward definitions of auxiliary functions long rec. Fibonacci(long n); long iter. Fibonacci(long n); int main() { long number; while(true) { cout << "Please enter a positive number (or negative to end): "; cin >> number; if (number < 0) return 0; cout << "Recursive: F(" << number << ") = " << rec. Fibonacci(number) << endl; cout << "Iterative: F(" << number << ") = " << iter. Fibonacci(number) << endl; } } … …. . . FALL 2001 ICOM 4015 - Lecture 2 23
Procedural Abstraction IV Iteration vs. Recursion Summary of Concepts • Recursion is as expressive as iteration • Iteration can yield faster code – less duplication of work – less function call overhead • Recursion can yield cleaner code – may rely on a “smart” optimizing compiler to minimize call overhead FALL 2001 ICOM 4015 - Lecture 2 24
Procedural Abstraction V Outline • Further procedural abstraction – Function overloading – Function templates FALL 2001 ICOM 4015 - Lecture 2 25
Function Overloading SQR Function Family int. Sqr (int x) { return x * x } long. Sqr(long x) { return x * x; } Without overloading float. Sqr(float x) { return x * x } int sqr (int x) { return x * x } long sqr(long x) { return x * x; } With overloading float sqr(float x) { return x * x } FALL 2001 ICOM 4015 - Lecture 2 26
Function Templates SQR Function Family int sqr (int x) { return x * x } long sqr(long x) { return x * x; } With overloading float sqr(float x) { return x * x } template <class T> T sqr (T x) { return x * x } FALL 2001 With templates ICOM 4015 - Lecture 2 27
SQR’aring different types // Standard C++ header files #include <iostream> #include <iomanip> // Forward definitions of local auxiliary functions template <class T> T sqr(T x); // Main function int main() { cout << " i" << " sqr(i)" << " sqr(float(i))" << " sqr(double(i))" << endl; for (int i=0; i<10; i++) { cout << setw(16) << i << setw(16) << sqr(i) << setw(16) << sqr(float(i)) << setw(16) << sqr(double(i)) << endl; } } // Local auxiliary functions template <class T> T sqr(T x) { return x * x; } Templates can reduce code duplication dramatically FALL 2001 ICOM 4015 - Lecture 2 28
Output [bvelez@amadeus] ~/icom 4015/lec 09 >>sqr i sqr(i) sqr(float(i)) 0 0 0 1 1 1 2 4 4 3 9 9 4 16 16 5 25 25 6 36 36 7 49 49 8 64 64 9 81 81 [bvelez@amadeus] ~/icom 4015/lec 09 >> FALL 2001 ICOM 4015 - Lecture 2 sqr(double(i)) 0 1 4 9 16 25 36 49 64 81 29
Anatomy of a Function Template T is a type parameter template <class T> function Inside this function T represents any type Templates are C++’s implementation of Parametric Polymorphism FALL 2001 ICOM 4015 - Lecture 2 30
Example 2 // Standard C++ header files #include <iostream> #include <iomanip> // Forward definitions of local auxiliary functions template <class T> void swap(T& a, T& b); template <class T> void do. Swap(T a, T b); // Main function int main() { cout << "***** do. Swap(1, 0)" << endl; do. Swap(1, 0); cout << endl << "***** do. Swap(1. 0/3. 0, 2. 0/3. 0)" << endl; do. Swap(1. 0/3. 0, 2. 0/3. 0); cout << endl << "***** do. Swap(true, false)" << endl; do. Swap("hello", "world"); } // Local auxiliary functions template <class T> void do. Swap(T a, T b) { T x = a; T y = b; cout << "x = " << x << " y = " << y << endl; swap(x, y); cout << "swap(x, y)" << endl; cout << "x = " << x << " y = " << y << endl; } template <class T> void swap(T& a, T& b) { T temp = a; a = b; b = 2001 temp; FALL ICOM 4015 - Lecture 2 } Variable declaration of type T 31
Example 2 Output [bvelez@amadeus] ~/icom 4015/lec 09 >>swap ***** do. Swap(1, 0) x = 1 y = 0 swap(x, y) x = 0 y = 1 swap(x, y) x = 1 y = 0 ***** do. Swap(1. 0/3. 0, 2. 0/3. 0) x = 0. 333333 y = 0. 666667 swap(x, y) x = 0. 666667 y = 0. 333333 swap(x, y) x = 0. 333333 y = 0. 666667 ***** do. Swap(true, false) x = hello y = world swap(x, y) x = world y = hello swap(x, y) x = hello y = world FALL 2001 ICOM 4015 - Lecture 2 32
Procedural Abstraction V Function Overloading Summary of Concepts • Related functions can be grouped under a common name • Overloaded functions may have different return types, but must have different parameters. • The importance of overloading will become clearer when we get into classes and object-oriented programming FALL 2001 ICOM 4015 - Lecture 2 33
Procedural Abstraction V Function Templates Summary of Concepts • Programmer declares one function parameterized over some type T • Compiler instantiates potentially many functions for all the different argument types provided among all function calls • Instances must be well typed, that is, all objects should only be used according to their types. FALL 2001 ICOM 4015 - Lecture 2 34
- Slides: 34