Top-Down Design with Functions and Classes Chapter 3 3.1 Building Programs from Existing Information – Reuse of existing programs – Develop program in stages – Compile along the way – Keep it small – Comments to describe actions 2 3.1 Building Programs from Existing Information Try not to start from scratch (if possible) Use any kind of information you get Use solutions of other problems (if possible) Adhere to the software development phases Build comments from the designed algorithm and its refinements // BAD: multiply kms by MILE_TO_KM and store // result in miles // GOOD: convert from kilometers to miles miles = MILE_TO_KM * kms; 3 3.1 Building Programs from Existing Information Example: Area of and Circumference of a Circle - Problem: Get the radius of the circle and compute the area and circumference - Analysis: Constant PI = 3.14 Inputs: float radius Output: float area, float circumference Formulas: area is PI*radius*radius circumference = 2*PI*radius 4 3.1 Building Programs from Existing Information Design – Get the radius of the circle – Compute the area of the circle • Assign PI * radius * radius to area – Compute the circumference of the circle • Assign 2 * PI * radius to circumference – Display the area and the circumference 5 3.1 Building Programs from Existing Information Implementation (1. Draft) // compute area and circumference int main() { const float PI = 3.14; float radius; // input: radius of the circle float area; // output: are of the circle float circumference; // output circumference of the circle // Get the radius // Compute the area of the circle // Assign PI * radius * radius to area // Compute the circumference of the circle // Assign 2 * PI * radius to circumference // Display area and circumference return 0; } 6 3.1 Building Programs from Existing Information Implementation (cont’d) – Finish the raw implementation of the previous step Test – Run the program using sample input data 7 3.1 Building Programs from Existing Information d2 Reuse of this program in order to solve another problem is possible Example: Weight of a Batch of Washers – Problem: Your company ask to compute the weight for produced washers – Analysis: A washer resembles a small donut. We need the rim area, the thickness, and the density of the material used. The last two quantities are inputs. • Problem Constant: PI = 3.14 • Inputs: float holeDiameter // diameter of the hole (d1) float edgeDiameter // diameter of outer edge (d2) // Assumption: edgeDiameter >= holeDiameter !!! float thickness // washer thickness float density // material density (needed for weight) float quatity // number f washers d1 8 3.1 Building Programs from Existing Information • Output: float weight // weight of batch of washers • Variables: – float holeRadius, edgeRadius, rimArea, unitWeight • Formulas: – – – – area of circle = PI*radius*radius (see previous problem) Radius of circle = diameter / 2 Rim area = area of outer circle – area of hole Unit weight = rim area * thickness * density 9 Implementation: Washers.cpp // File: washers.cpp // Computes the weight of a batch of flat // washers. #include <iostream> using namespace std; int main() { const float PI = 3.14159; float holeDiameter; // input - 10 Washers.cpp float float float float float float float float float edgeDiameter; thickness; density; quantity; weight; holeRadius; edgeRadius; rimArea; unitWeight; // // // // // // // // // input - diameter input - thickness input - density input - number output - weight radius of hole radius of outer edge area of rim weight of 1 washer 11 Washers.cpp cout << "Inner diameter in centimeters: "; cin >> holeDiameter; cout << "Outer diameter in centimeters: "; cin >> edgeDiameter; // check for edgeDiameter >= holeDiameter // is not yet made cout << "Thickness in centimeters: "; cin >> thickness; cout << "Material density in grams per cubic centimeter: "; cin >> density; cout << "Quantity in batch: "; cin >> quantity; 12 Washers.cpp // Compute the rim area. holeRadius = holeDiameter / 2.0; edgeRadius = edgeDiameter / 2.0; rimArea = PI * edgeRadius * edgeRadius PI * holeRadius * holeRadius; // Compute the weight of a flat washer. unitWeight = rimArea * thickness * density; // Compute the weight the batch of washers weight = unitWeight * quantity; 13 Washers.cpp // Display the weight cout << "The expected weight of the batch is " << weight; cout << " grams." << endl; return 0; } 14 Washers.cpp Program Output Inner Diameter in centimeters: 1.2 Outer Diameter in centimeters: 2.4 Thickness in centimeters: 0.1 Material density in grams per cubic centimeter: 7.87 Quantity in batch: 1000 The expected weight of the batch is 2670.23 grams 15 3.2 Library Functions – Goal of Structured Programming • Error free code – Reusability • Don’t reinvent the wheel – C ++ provides collection of functions – Organized in Libraries 16 3.2 Library Functions Examples – – – – – abs(x): absolute value ceil(x) and floor(x) cos(x), sin(x), tan(x) log(x), log10(x), exp(x) pow(x, y) <cstdlib> <cmath> <cmath> <cmath> <cmath> 17 C++ Math Library – Functions in the Math library • sqrt cos sin pow – Function use in Assignments y = sqrt (x); sqrt is function name x is function argument – Activated by a “function call” – Result of execution is assigned to variable y 18 C++ Math Library (cont) Function sqrt as a “black box” X is 16.0 Square root computation Result is 4.0 19 C++ Library Functions – We can effectively utilize existing functions by learning to read function prototypes with the preconditions and postconditions. – Example prototype (or signature) double sqrt(double x) // PRE: x >= 0.0 // POST: Returns the square root of x. 20 Preconditions and Postconditions – Comments that represents a contract between the implementor of a function and the user (client) of that function. – We'll look at two such comments: • Precondition: What the function requires. • Postcondition: What the function will do if the precondition is met. 21 Preconditions and Postconditions – The preconditions are the circumstances that must be true before the function can successfully fulfill the promised postconditions. – Example (Precondition abbreviates to PRE: double sqrt(double x); // PRE: x >= 0 // POST: Returns square root of argument X 22 SquareRoot.cpp // File: squareRoot.cpp // Performs three square root computations #include <cmath> #include <iostream> using namespace std; // sqrt function // i/o functions int main() { float first; float second; float answer; 23 SquareRoot.cpp // Get first number and display its square root. cout << "Enter the first number: "; cin >> first; answer = sqrt(first); cout << "The square root of the first number is " << answer << endl; // Get second number and display its square root. cout << "Enter the second number: "; cin >> second; answer = sqrt(second); cout << "The square root of the second number is " << answer << endl; 24 SquareRoot.cpp // Display the square root of the sum of first // and second. answer = sqrt(first + second); cout << "The square root of the sum of both numbers is " << answer << endl; return 0; } 25 SquareRoot.cpp Program Output Enter the first number: 9 The square root of the first number is 3 Enter the second number: 16 The square root of the second number is 4 The square root of the sum of both numbers is 5 26 Examples Roots of a quadratic equation log10(xy) Floor(76.97) Ceil(105.04) Sqrt(floor(fabs(-19.9))) 27 3.3 Top-Down Design and Structure Charts Original Problem Draw a Circle Detailed subproblem s Draw a figure Level 0 Draw a Triangle Draw intersecting lines Draw intersecting lines Draw a base Level 1 Level 2 28 3.4 Functions without Arguments – Functions are used in Top-Down Design – main() is just a function • called by OS – C++ program is a collection of Functions • top level function is called the main() • lower level functions – User Defined or Libraries – Example StkFigMn.cpp 29 StickFigure.cpp // File: stickFigure.cpp // Draws a stick figure #include <iostream> using namespace std; // Functions used ... void void void void drawCircle(); // Draws a circle drawTriangle(); // Draws a triangle drawIntersect(); // Draws intersecting lines drawBase(); // Draws a horizontal line 30 StickFigure.cpp int main() { // Draw a circle. drawCircle(); // Draw a triangle. drawTriangle(); // Draw intersecting lines. drawIntersect(); return 0; } 31 Function Calls – We can call a function and get results without knowing the implementation of that function. • pow(x, y) returns x to the yth power. – For now, we need not know exactly how a function is implemented. – However, we do need to know how to use the function. 32 Function Calls – This general form of a function call: function-name ( optional argument-list ); – Example function call: drawCircle (); – The function name is drawCircle – No arguments to this function 33 Function Prototype – This general form of a function prototype: type function-name ( optional argument-list ); – Example function prototype: void skipThree (); – Type • int - float - char – Name – ( ); – Descriptive comment 34 Function Definition – General form of a function definition: type function-name ( optional argument-list ) { local-declarations - function body executable-statements } – Example function definition: void drawTriangle () 35 Function Definition void drawTriangle () function header { function body // Draw a triangle. drawIntersect (); drawBase (); } 36 StickFigure.cpp // Draws a circle void drawCircle() { cout << " * " << endl; cout << " * *" << endl; cout << " * * " << endl; } // end drawCircle 37 StickFigure.cpp void drawCircleChar(char symbol) { cout << " " << symbol << " " << endl; cout << " " << symbol << " " << symbol << endl; cout << " " << symbol << " " << symbol << endl; } // Draws a triangle void drawTriangle() { drawIntersect(); drawBase(); } 38 StickFigure.cpp // Draws intersecting lines void drawIntersect() { cout << " / \\ " << endl; cout << " / \\ " << endl; cout << " / \\" << endl; } // draws a horizontal line void drawBase() { cout << " -------" << endl; } 39 Order of Execution int main() { drawCircle(); drawTriangle(); drawIntersect(); return 0; } void drawCircle() { cout << “ * “ << endl; cout << “ * * “ << endl; cout << “ * * “ << endl; } 40 Function Advantages – – – – – Program team on large project Simplify tasks Each Function is a separate unit Top-down approach Procedural abstraction • Main as collection of functions refined step by step – Information hiding • We need not know how a function is implemented – Reuse (drawTriangle) 41 Abstraction – Recall: Abstraction (here procedural) • Refers to the act of ignoring details to concentrate on essentials. • Allows us to use complicated things with little effort (CD players, automobiles, computers). 42 3.5 Functions with Input Arguments – Functions used like building blocks – Build systems one functions at a time • Stereo Components – Use function return values and arguments to communicate between functions – Example: • rimArea = findArea(edgeRadius) + findArea(holeRadius) 43 Function Call Form: fname (actual arg list); Example: scale (3.0, z); 44 Function Return Functions must return a value unless declared as void Form: return expression; Example: return x * y; 45 Function Definition Form: type fname (formal arg list) { function body } Example: float scale(float x, int n) { float scaleFactor; scaleFactor = pow(10, n); return (x * scaleFactor); } 46 Function Prototype Form: type fname (formal arg type list); Example: float scale (float x, int n); 47 TestScale.cpp // File testScale.cpp // Tests function scale. #include <iostream> #include <cmath> using namespace std; // Function prototype float scale(float, int); int main() { 48 TestScale.cpp float num1; int num2; // Get values for num1 and num2 cout << "Enter a real number: "; cin >> num1; cout << "Enter an integer: "; cin >> num2; // Call scale and display result. cout << "Result of call to function scale is " << scale(num1, num2) << endl; return 0; } 49 TestScale.cpp float scale(float x, int n) { float scaleFactor; scaleFactor = pow(10, n); return (x * scaleFactor); } This program acts as driver for testing the scale function Unit test before integration test !! 50 Argument / Parameter List Correspondence – Functions can have more than 1 arg – Correspondence between Actual & Formal arguments Function call scale (3.0, z); Actual Argument Formal Argument 3.0 x z n 51 Argument / Parameter List Correspondence float scale(float x, int n) { float scaleFactor; scaleFactor = pow(10, n); return (x * scaleFactor); } 52 Argument / Parameter List Correspondence Function call scale (x + 2.0, y); Actual Argument x + 2.0 y Formal Argument x y 53 Argument / Parameter List Correspondence Function call scale (y, x); Actual Argument y x Formal Argument x y Watch for type matches in formal and actual arguments 54 Key Points The substitution of the value of an actual argument in a function call for its corresponding formal argument is strictly positional. That is, the value of the first actual argument is substituted for the first formal argument; the second and so on 55 Key Points The names of these corresponding pairs of arguments are no consequence in the substitution process. The names may be different, or they may be the same. The substituted value is used in place of the formal argument at each point where that argument appears in the called function. 56 Key Points Positional correspondence Type consistent is key because of positional correspondence – Argument types – Return types 57 Key Points Type of a value returned by a called function must be consistent with the type expected by the caller as identified in the prototype Type of an actual argument in a function call must be consistent with the type of its corresponding formal argument 58 3.6 Scope of Names Scope of a name: Region of a program where the name is visible and can be referenced Variable declared in a function has a local scope within the function Same for variables declared in the main Variable declared before main is global scope – Call anywhere in program Functions declared globally 59 Scope of Names void foo1(int a1, float b1); void foo2(int a2, float b2); const int CONST = 100; int main() { int localMain; … } void foo1(int a1, float b1) { float local1= 12.98; … } void foo2(int a2, float b2) { int local2= 10; … } Main CONST a1 b1 a2 b2 local1 local2 localMain main foo1 foo2 yes no no no no no no yes yes yes yes foo1 foo2 yes yes yes no no yes no no yes yes yes yes no no yes yes no yes no yes yes yes 60 3.7 Extending C++ through Classes – Discuss two classes • String class part of compiler • Money class is a user defined class – #include <string> – #include “money.h” 61 String Class Declaring string objects Reading & Displaying strings Assignment & Concatenation Operator Overloading Dot Notation Member Functions Object Assignments 62 Declaring string Objects A number of ways to declare string firstName, lastName; string wholeName; string greeting = “Hello “; 63 Reading & Displaying string Objects Use extraction operator >> & the stream cin for input – cin >> firstName; Use insertion operator << & the stream cout for output – cout << greeting << wholeName << endl; 64 Reading & Displaying string Objects getline (cin, lastName, ‘\n’); reads all characters typed in from the keyboard up to the new line into the string object 65 StringOperations.cpp // FILE: StringOperations.cpp // ILLUSTRATES STRING OPERATIONS #include <iostream> #include <string> using namespace std; int main () { string firstName, lastName; string wholeName; string greeting = "Hello "; cout << "Enter your first name: "; cin >> firstName; 66 StringOperations.cpp cout << "Enter your last name: "; cin >> lastName; // Join names in whole name wholeName = firstName + " " + lastName; // Display results cout << greeting << wholeName << '!' << endl; cout << "You have " << (wholeName.length () - 1) << " letters in your name." << endl; 67 StringOperations.cpp // Display initials cout << "Your initials are " << (firstName.at(0)) << (lastName.at(0)) << endl; return 0; } 68 StringOperations.cpp Program output Enter your first name: Caryn Enter your last name: Jackson Hello Caryn Jackson! You have 12 letters in your name. Your initials are CJ 69 Assignment Stores the first and last name wholeName = firstName + “ “ + lastName; Concatenation ‘+’ joins the two objects together “ “ for string values not ‘ ‘ 70 Operator Overloading ‘+’ normally means addition but with strings it means concatenation The ‘+’ can take on many meanings – Operator Overloading: performing different operations depending on the used data type. – C++ can have multi meanings to 1 operator – >> & << are overloaded operators – * / - == = all can be overloaded 71 Dot Notation Dot notation used to call an objects member functions int len = wholeName.length(); – Applies member function length to string object wholeName – Function returns the objects length Examples of other member functions: – “first last”.find(“first”) 0 – “first last”.find(“last”) 6 – “first last”.insert(0, “Mr. “) “Mr. first last” – “Mr. first last”.replace(9, 1, “ middle “) “Mr. first middle last” – “Mr. first middle last”.erase(10, 7) “Mr. first last” – myTitle.assign(“Mr. first last”, 0, 3) myTitle = “Mr.” 72 Money Class Process money objects Two attributes – dollars – cents Why do this ?? Why not float ?? 73 Money Class Allocate a money object – money creditLimit = 5000.00; Assignments – taxAmount = salePrice * taxPercent/100.0; – finalCost = salePrice + taxAmount; 74 MoneyDemo.cpp // FILE: MoneyDemo.cpp // ILLUSTRATES MONEY OPERATIONS #include <iostream> #include "money.h" using namespace std; int main () { // Local declarations const float taxPercent = 6.25; money creditLimit = 5000.00; 75 MoneyDemo.cpp money salePrice; money taxAmount; money finalCost; cout << "Enter item price: "; cin >> salePrice; // Compute tax amount taxAmount = salePrice * taxPercent / 100.0; // Compute final cost finalCost = salePrice + taxAmount; 76 MoneyDemo.cpp // Display cout cout cout cout sales receipt << "Sales receipt" << endl; << "Price " << salePrice << endl; << "Tax " << taxAmount << endl; << "Paid " << finalCost << endl << endl; // Compute new credit limit cout << "Your initial credit limit is " << creditLimit << endl; creditLimit = creditLimit - finalCost; cout << "Your new credit limit is " << creditLimit << endl; return 0; } 77 MoneyDemo.cpp Program output Enter item price: 345.77 Sales Receipt Price $345.77 Tax $21.61 Paid $367.38 Your initial credit limit is $5,000.00 Your new credit limit is $4,632.62 78 Header and Implementation Files Header file (.h) – File containing information that C++ needs to compile a program that accesses a user-defined class Implementation file (.cpp) – File containing the C++ code for the operators of a user defined class 79 Another Example: Complex numbers Want to work with complex numbers? C++ does not support them directly Solution: – Define a class “Complex” – Overload operators: +, -, *, and so on so that complex algebra works. 80 Complex numbers Addition (pair notation) (a, b) + (c, d) = (a+c, b+d) Multiplication: (a, b) * (c, d) = (a*c – b*d, a*d + b*c) Program piece: int main () { Complex z, z1, z2; … z =z1*z2; z1 = z1 + z2; … } 81 3.8 Common Programming Errors – Semicolon in Function Prototype (Declaration) – Inconsistencies in Number of Arguments • Too few arguments in a call • Too many arguments in a call – Argument Mismatch • Correct position (formal & actual params) 82 Common Programming Errors – Function Prototype & Definition Mismatches • Both are the same except for the ; – Return Statements • “Return value expected” • “Function should return value” – Missing Object Name in Call to Member Function – Missing #include – Type Mismatches 83