1 / 50

Chapter 3 Procedural Abstraction and Functions That Return a Value

Chapter 3 Procedural Abstraction and Functions That Return a Value. Goals:. To examine the advantages of top-down design. To survey the available C++ library functions. To define the typecasting functions that have been set up. To explore the use of programmer-defined functions.

randi
Download Presentation

Chapter 3 Procedural Abstraction and Functions That Return a Value

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Chapter 3Procedural Abstraction and Functions That Return a Value Goals: • To examine the advantages of top-down design • To survey the available C++ library functions • To define the typecasting functions that have been set up • To explore the use of programmer-defined functions • To distinguish between constants, global & local variables • To introduce the concept of function overloading

  2. Top-Down Design One of the most effective ways to design a program is by means of top-down design. Break the large task into smaller subtasks Break the large subtasks into even smaller subtasks Stop when coding each subtask is straightforward CS 140

  3. Library Functions Note that a number of predefined functions exist in C++ libraries that a programmer can access via include directives. math.h Computes common mathematical functions limits.h Tests integer type properties And many more! time.h Converts time and date formats CS 140

  4. #include<iostream> #include<iomanip> #include<math.h> using namespacestd; voidmain() { doublenumber; cout << "SIMPLE ARITHMETIC CALCULATOR" << endl; cout << "(Does a mess o'math to a user-specified value)" << endl << endl; cout << "Enter the number you\'re using: "; cin >> number; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(5); cout << endl << endl << "ARITHMETIC RESULTS:" << endl << endl; cout << "NUMBER: " << setw(10) << number << endl; cout << "NUMBER SQUARED: " << setw(10) << pow(number,2) << endl; cout << "NUMBER CUBED: " << setw(10) << pow(number,3) << endl; if(number >= 0.0) cout << "SQUARE ROOT OF NUMBER: " << setw(10) << sqrt(number) << endl; if(number > 0.0) { cout << "NATURAL LOG OF NUMBER: " << setw(10) << log(number) << endl; cout << "LOG (BASE 2) OF NUMBER: " << setw(10) << log(number) / log(2.0) << endl; } cout << "SINE OF NUMBER: " << setw(10) << sin(number) << endl; cout << "COSINE OF NUMBER: " << setw(10) << cos(number) << endl; cout << "FLOOR OF NUMBER: " << setw(10) << floor(number) << endl; cout << "CEILING OF NUMBER: " << setw(10) << ceil(number) << endl; cout << "ABSOLUTE VALUE OF NUMBER: " << setw(10) << fabs(number) << endl; cout << endl << endl; return; } CS 140

  5. Typecasting #include <iostream> using namespace std; void main() { int nbr1, nbr2, nbr3, nbr4, nbr5; double mean; cout << "Enter five integers: "; cin >> nbr1 >> nbr2 >> nbr3 >> nbr4 >> nbr5; mean = (nbr1 + nbr2 + nbr3 + nbr4 + nbr5) / 5; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(2); cout << "\nThe average is: " << mean << ”\n\n"; return; } With so many different numerical types in C++, it is sometimes useful to convert from one type to another. C++ provides built-in functions to perform this sort of typecasting. #include <iostream> using namespace std; void main() { int nbr1, nbr2, nbr3, nbr4, nbr5; double mean; cout << "Enter five integers: "; cin >> nbr1 >> nbr2 >> nbr3 >> nbr4 >> nbr5; mean = double(nbr1 + nbr2 + nbr3 + nbr4 + nbr5) / 5; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(2); cout << "\nThe average is: " << mean << ”\n\n"; return; } CS 140

  6. main function • query user for year • query user for month • query user for day • calculate day-of-year • output day-of-year Example: Compute today’s day of the year. Programmer-Defined Functions In addition to using predefined library functions, a programmer can implement a top-down design by means of programmer-defined functions. • retrieveYear function • query user for year • ensure year is in 1950-2050 • return year • retrieveMonth function • query user for month • ensure month is in 1-12 • return month • retrieveDay function • query user for day • ensure day is in proper range for month/year • return day • calculateDayOfYear function • cycle through months, adding # of days to DOY • add this month’s # of days to DOY • return DOY CS 140

  7. /////////////////////////////////////////// // This program queries the user for the // // current date and then calculates and // // outputs the current day of the year. // /////////////////////////////////////////// #include <iostream> using namespace std; int retrieveYear(); int retrieveMonth(); int retrieveDay(int mo, int yr); int calculateDayOfYear(int theDay, int theMonth, int theYear); // The main function serves a supervisory capacity, // // calling the other functions to interact with the // // user and to do the day-of-year calculations. It // // then outputs the result. // void main() { int day, month, year, dayOfYear; year = retrieveYear(); month = retrieveMonth(); day = retrieveDay(month, year); dayOfYear = calculateDayOfYear(day, month, year); cout << "It\'s day #" << dayOfYear << " of the year " << year << endl << endl; return; } Function Prototypes Before examining the main function, the compiler needs to know the format of every function in the program, including the name of the function, the type of value that it will return, and the types of the parameters that are being sent to it. Function Calls Just like the predefined library function calls, calls to the programmer-defined functions can be sent values as parameters to help the function do its job, and can return a single value to be used by the calling function (in this case, main). CS 140

  8. // The retrieveYear function queries the user for the current year and verifies that the user's // // response is legitimate (i.e., in the range between 1950 and 2050). The user is forced to // // respond repeatedly until the answer is legitimate. That legitimate year is returned. // int retrieveYear() { int thisYear; cout << "Enter the current year: "; cin >> thisYear; while ((thisYear < 1950) || (thisYear > 2050)) { cout << "Sorry! This program can only handle years in the 1950-2050 range." << endl; cout << "Enter a year in the proper range: "; cin >> thisYear; } return thisYear; } // The retrieveMonth function queries the user for the current month and verifies that the // // user's response is legitimate (i.e., in the range between 1 and 12). The user is forced // // to respond repeatedly until the answer is legitimate. That legitimate month is returned. // int retrieveMonth() { int thisMonth; cout << "Enter the current month: "; cin >> thisMonth; while ((thisMonth < 1) || (thisMonth > 12)) { cout << "Sorry! This program can only handle months in the 1-12 range." << endl; cout << "Enter a month in the proper range: "; cin >> thisMonth; } return thisMonth; } Function Heading This line is identical to the prototype, except for the semicolon at the end of the prototype. Return Statement Returns the value to be used by the calling function (i.e., main). Local Variable Can only be used by this function. Not even main knows about this variable! CS 140

  9. // The retrieveDay function queries the user for the // // current day and verifies that the user's response is // // legitimate (i.e., in the proper range for the para- // // meterized month and year). The user is forced to // // respond repeatedly until the answer is legitimate. // // That legitimate day is returned. // int retrieveDay(int mo, int yr) { int today; int lastDay; if (mo == 2) { if (yr % 4 == 0) lastDay = 29; else lastDay = 28; } else if ((mo == 4) || (mo ==6) || (mo == 9) || (mo == 11)) lastDay = 30; else lastDay = 31; cout << "Enter the current day: "; cin >> today; while ((today < 1) || (today > lastDay)) { cout << "Sorry! This program can only handle days " << "in the 1-" << lastDay << " range." << endl; cout << "Enter a day in the proper range: "; cin >> today; } return today; } Parameter List These are copies of the variables in the calling function (in this case, main). Changes to their values will have no effect on the original variables! (That’s why it’s a good idea to give them new names – it decreases confusion when reading the code!) CS 140

  10. Function Comment It’s always a good idea to precede each function with a descriptive comment. If the programmer revisits this program at a later date, or if another programmer needs to adjust the code, such documentation can be priceless! // The calculateDayOfYear function uses the para- // // meterized day, month, and year to calculate the // // corresponding day of the year, which it returns. // int calculateDayOfYear(int theDay, int theMonth, int theYear) { int daysSoFar = 0; int cyclingMonth = 1; while (cyclingMonth < theMonth) { if (cyclingMonth == 2) { if (theYear % 4 == 0) daysSoFar += 29; else daysSoFar += 28; } else if ((cyclingMonth == 4) || (cyclingMonth == 6) || (cyclingMonth == 9) || (cyclingMonth == 11)) daysSoFar += 30; else daysSoFar += 31; cyclingMonth++; } daysSoFar += theDay; return daysSoFar; } And what happens when you run this program? CS 140

  11. main function • print a header • print the countdown Another Example - A Digital Numerics Countdown • printHeader function • output a simple header • printTimedDigits function • cycle through the digits from 9 down to 0 • output the digital numeric for each digit when a second elapses • sound a beeping alarm with each digit Notice that main is not the only function capable of calling other functions! • printDigitalNumeric function • output the top three characters of the digital numeric • output the middle three characters of the digital numeric • output the bottom three characters of the digital numeric • printTopLine function • based upon the number being represented, print the three-character sequence representing its top line • printMiddleLine function • based upon the number being represented, print the three-character sequence representing its middle line • printBottomLine function • based upon the number being represented, print the three-character sequence representing its bottom line CS 140

  12. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This program illustrates what the ten numerical digits from nine down // // to zero would look like if displayed using horizontal and vertical // // bars, similar to what the digital display of a clock uses. To simplify // // the computations, a little Boolean algebra is utilized. One-second // // intervals elapse between consecutive numerical digit displays. // ///////////////////////////////////////////////////////////////////////////// #include <iostream> #include <time.h> using namespace std; void printHeader(); void printTimedDigits(); void printDigitalNumeric(int number); void printTopLine(int number); void printMiddleLine(int number); void printBottomLine(int number); const char BLANK = ' ', HORIZONTAL_BAR = '_', VERTICAL_BAR = '|'; Void Functions If a function is not going to return a value, then it should be made a void function. Global Constants By being defined outside any function, these values may be used by any function defined below their declaration. CS 140

  13. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The main function coordinates the use of the other routines, // // specifically, the routines to output a header and to output // // the numerical digits in a timed fashion. // ////////////////////////////////////////////////////////////////// void main() { printHeader(); printTimedDigits(); return; } //////////////////////////////////////////////////////////// // The printHeader function outputs a small header which // // concisely informs the user what this program is doing. // //////////////////////////////////////////////////////////// void printHeader() { cout << "\"TIMED DISPLAY OF DIGITAL NUMERICS\"" << endl; return; } Void Function Calls Since the functions return no values, their function calls require no assignment statements. CS 140

  14. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The printTimed Digits function cycles through the numerical // // digits from 9 down to 0, outputting them one at a time, in // // one-second intervals, in a digital format. // ///////////////////////////////////////////////////////////////// void printTimedDigits() { int i = 9; // Iterative loop variable for indexing digit. long int initTime; // System time at beginning of timed process. long int currTime; // Current system time. long int elapsedTime; // Number of seconds since process began. time(&initTime); while (i >= 0) { time(&currTime); elapsedTime = currTime - initTime; while (elapsedTime < 10-i) { time(&currTime); elapsedTime = currTime - initTime; } cout << '\a'; printDigitalNumeric(i); i--; } cout << "\a\a\a" << endl; return; } Function Call This function calls another function within the program, just like main can do. CS 140

  15. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The printDigitalNumeric function generates three lines of // // output to show the vertical and horizontal bars which would // // comprise a digital display of the input parameter number. // ///////////////////////////////////////////////////////////////// void printDigitalNumeric(int number) { printTopLine(number); printMiddleLine(number); printBottomLine(number); return; } //////////////////////////////////////////////////////////// // The printTopLine function determines which characters // // should be placed in the uppermost line of the 3x3 grid // // used to "digitally" represent the parameter number. // //////////////////////////////////////////////////////////// void printTopLine(int number) { if ((number == 1) || (number == 4)) cout << BLANK << BLANK << BLANK << endl; else cout << BLANK << HORIZONTAL_BAR << BLANK << endl; return; } Function Calls This function calls three functions within the program. CS 140

  16. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The printMiddleLine function determines which characters // // should be placed in the center line of the 3x3 grid used // // to "digitally" represent the parameter number. // ////////////////////////////////////////////////////////////// void printMiddleLine(int number) { if ((number == 1) || (number == 2) || (number == 3) || (number == 7)) cout << BLANK; else cout << VERTICAL_BAR; if ((number == 0) || (number == 1) || (number == 7)) cout << BLANK; else cout << HORIZONTAL_BAR; if ((number == 5) || (number == 6)) cout << BLANK; else cout << VERTICAL_BAR; cout << endl; return; } CS 140

  17. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The printBottomLine function determines which characters // // should be placed in the bottom line of the 3x3 grid used // // to "digitally" represent the parameter number. // ////////////////////////////////////////////////////////////// void printBottomLine(int number) { if ((number == 0) || (number == 2) || (number == 6) || (number == 8)) cout << VERTICAL_BAR; else cout << BLANK; if ((number == 1) || (number == 4) || (number == 7)) cout << BLANK; else cout << HORIZONTAL_BAR; if (number == 2) cout << BLANK; else cout << VERTICAL_BAR; cout << endl; return; } CS 140

  18. CS 140

  19. main printHeader printTimedDigits printDigitalNumeric printTopLine printBottomLine printMiddleLine Information Hiding One of the principles behind top-down design is the concept of information hiding, in which the programmer makes functions “aware” of data or methods on a “need-to-know” basis. Which functions need to know the contents of the header? Which functions need to know how the middle line for a zero digit is output? Which functions need to know which digit is being handled currently? CS 140

  20. Procedural Abstraction One means of bringing about information hiding is procedural abstraction, in which the programmer makes the details of how a function operates “abstract” from the rest of the program. Thus, for example, we’re unaware of how the sqrt function in math.h does its job. All that concerns us is that the job gets done. Advantages: * Modifiability * Debuggability * Reusability * Readability CS 140

  21. main main main generate polygons draw polygons generate polygons draw polygons generate polygons compute curved surfaces draw polygons generate torus generate torus generate torus shade polygon blend polygons blend polygons generate cube generate cube generate cube draw pixels compute reflect compute reflect generate teapot generate teapot generate teapot draw pixels draw pixels generate sphere generate sphere generate sphere generate cone generate cone generate cone Computer Graphics Example CS 140

  22. #include <iostream> using namespace std; int i; void echo(); void main() { i = 0; while (i <= 9) { i++; cout << i << "(main) "; echo(); } return; } void echo() { i++; cout << i << "(echo)\n"; return; } Global Variables While it’s possible to declare a global variable that is accessible throughout the program’s functions, such variables damage information hiding and limit readability, modifiability, debuggability, etc. CS 140

  23. #include <iostream> using namespace std; void echo(); void main() { int i; i = 0; while (i <= 9) { i++; cout << i << "(main) "; echo(); } return; } void echo() { int i; i++; cout << i << "(echo)\n"; return; } Local Variables Local variables are declared inside a particular function and can only be accessed within that function. CS 140

  24. #include <iostream> using namespace std; void echo(int i); void main() { int i; i = 0; while (i <= 9) { i++; cout << i << "(main) "; echo(i); } return; } void echo(int i) { i++; cout << i << "(echo)\n"; return; } Function Parameters Function parameters are basically local variables that have been initialized with the value of the corresponding argument in the calling function. CS 140

  25. #include <iostream> #include <math.h> using namespacestd; double roundoff(double nbr, int digits); int roundoff(int value, int factor); void main() { double x = 425.709256; int i = 425; int n = 3; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(10); cout << "Rounding off " << x << "\n with integer " << n << ": "; cout << roundoff(x, n) << endl << endl; cout << "Rounding off " << i << "\n with integer " << n << ": "; cout << roundoff(i, n) << endl << endl; return; } // Round off the parameterized number // // to the parameterized decimal place. // double roundoff(double nbr, int digits) { int expandedNbr; expandedNbr = int(nbr * pow(10, digits)); return (double(expandedNbr) / pow(10, digits)); } // Round off the parameterized value to the next // // lower multiple of the parameterized factor. // int roundoff(int value, int factor) { return (value - value % factor); } Function Overloading It’s possible to have more than one function with the same name, as long as the compiler can distinguish between them (via the returned type and/or parameter types). CS 140

  26. Chapter 4Functions for All Subtasks Goals: • To explore the use of void functions • To distinguish between call-by-reference and call-by-value • To examine how functions can be nested • To introduce testing via stubs and drivers • To gain some familiarity with the Visual C++ debugger

  27. void Functions When a function returns no value, then it is a void function. void printHeader() { cout << “RUDIMENTARY INTEGER LIST ANALYSIS AND SUMMARY” << endl << endl; cout << “Enter a list of positive integers, ending with -1.” << endl; cout << “Afterwards, the maximum, minimum, and mean will be displayed.\n\n”; return; } No Returned Value! void outputResults(int high, int low, int mean) { cout << “High Value: ” << high << endl; cout << “Low Value: ” << low << endl; cout << “Mean Value: ” << mean << endl; return; } The Most Common Use For void Functions Is Pure Output. CS 140

  28. void main() { int value; int max = -1; int min = INT_MAX; int total = 0; int count = 0; printHeader(); cout << “Enter value: ”; cin >> value; while (value >= 0) { max = higher(value, max); min = lower(value, min); total += value; count++; cout << “Enter value: ”; cin >> value; } outputResults(max, min, average(total, count)); return; } Callingvoid Functions void Function Call When calling a void function, no return value is expected. Non-void Function Call Non-void Function Call Non-void Function Call void Function Call CS 140

  29. Call-by-Reference Parameters When a function isn’t supposed to return any values, it can be made a void function. When a function is supposed to return a single value, it can be made a non-void function, using the same type as the value being returned. When a function is supposed to produce multiple values that are needed in the calling function, then the two functions are allowed to share the same memory by means of call-by-reference parameters. CS 140

  30. #include <iostream> using namespace std; void retrieveThreeNumbers(int &firstNbr, int &secondNbr, int &thirdNbr); void reorderThreeNumbers(int &nbrA, int &nbrB, int &nbrC); void outputThreeNumbers(int smallest, int middle, int largest); void main() { int x, y, z; retrieveThreeNumbers(x, y, z); reorderThreeNumbers(x, y, z); outputThreeNumbers(x, y, z); return; } void retrieveThreeNumbers(int &firstNbr, int &secondNbr, int &thirdNbr) { cout << "Enter three integers." << endl; cout << "First integer: "; cin >> firstNbr; cout << "Second integer: "; cin >> secondNbr; cout << "Third integer: "; cin >> thirdNbr; return; } Note that the ampersand (&) in front of the variable name signifies that the parameter is being passed by reference instead of by value. In other words, the function will not make a copy of the value being passed, but will, in fact, be using the original memory. The three parameters here are supposed to obtain new values in this function, and those three values are needed in the calling function. Therefore, all three values are passed by reference, and any changes made to them in this function automatically affect x, y, and z in main. CS 140

  31. void reorderThreeNumbers(int &nbrA, int &nbrB, int &nbrC) { int temp; if ((nbrB <= nbrA) && (nbrB <= nbrC)) { temp = nbrA; nbrA = nbrB; nbrB = temp; } else if ((nbrC <= nbrA) && (nbrC <= nbrB)) { temp = nbrA; nbrA = nbrC; nbrC = temp; } if (nbrC <= nbrB) { temp = nbrB; nbrB = nbrC; nbrC = temp; } return; } void outputThreeNumbers(int smallest, int middle, int largest) { cout << endl << endl; cout << "The smallest number is: " << smallest << endl; cout << "The middle number is: " << middle << endl; cout << "The largest number is: " << largest << endl; cout << endl << endl; return; } This function reorders the three values so they’ll be in numerical order when this function ends. Thus, the function might change the values of the three parameters, so the parameters are passed by reference. The last function will not alter any of the values of the incoming parameters, so they’re passed by value. CS 140

  32. Data Heap Keeps track of variables in use. RAM RAM y x z thirdNbr Run-Time Stack Keeps track of function calls; the function that is on top of the stack is the active function. secondNbr firstNbr retrieveThreeNumbers main main What’s Happening In Memory? main begins main calls retrieveThreeNumbers The same memory is being used, but with different variable names! CS 140

  33. RAM RAM RAM y y x x z z temp nbrC nbrA nbrB reorderThreeNumbers main main main What’s Happening In Memory? (Part 2) return tomain from retrieveThreeNumbers main calls reorderThreeNumbers return tomain from reorderThreeNumbers CS 140

  34. RAM RAM RAM largest y x z middle smallest outputThreeNumbers main main What’s Happening In Memory? (Part 3) return tomain from outputThreeNumbers main ends main calls outputThreeNumbers The parameters are passed by value, so they do not share memory with main’s variables! CS 140

  35. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // This program computes the value to which a power series // // converges, and the number of iterations required before // // the series can be said to converge. // ///////////////////////////////////////////////////////////// #include <iostream> using namespace std; double queryUserForValue(); void computeSeries(double x, double &sum, int &nbrLoops); void outputResults(double result, int iterations); // The main function coordinates the retrieval of the value // // to be used in the power series, the calculation of the // // series limit, and the output of the results. // void main() { double number, convergentValue; int nbrIterations; number = queryUserForValue(); computeSeries(number, convergentValue, nbrIterations); outputResults(convergentValue, nbrIterations); return; } CS 140

  36. // This function queries the user for the power series // // generator value, which must be strictly between 0 and 1. // double queryUserForValue() { double nbr; cout << "Enter the number to be tested: "; cin >> nbr; while ((nbr <= 0.0) || (nbr >= 1.0)) { cout << "The number must be greater than 0 and less than 1." << endl << "Enter the number to be tested: "; cin >> nbr; } return nbr; } CS 140

  37. // This function repeatedly adds the next power of the generator // // value to the series expansion, until two consecutive sums are // // equal, at which time the series is considered to converge. // void computeSeries(double x, double &sum, int &nbrLoops) { double powerOfX, previousSum = 0.0; nbrLoops = 0; sum = x; powerOfX = x; while (previousSum < sum) { nbrLoops++; previousSum = sum; powerOfX *= x; sum += powerOfX; } return; } This function has three parameters. The first parameter is the value entered by the user, which won’t be changed in this function, so it’s passed by value. The second and third parameters are values being calculated in this function; they’re needed in the calling function, so they’re passed by reference. CS 140

  38. // This function outputs the power series final value, as // // well as the number of iterations required to obtain it. // void outputResults(double result, int iterations) { cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(8); cout << "The series converges to " << result << " in " << iterations << " iterations." << endl << endl; return; } CS 140

  39. NestedFunctions Just like main, any function may contain a call to another function within its body. #include <iostream> #include <iomanip> #include <math.h> using namespace std; double queryUserForValue(); bool testValueBounds(double value); void outputWarning(double value); void generateResults(double val, double &sinVal, double &cosVal, double &logVal); void outputResults(double val, double sinVal, double cosVal, double logVal); void outputOneResult(char resultName[], double value, double result); void main() { double userValue; double sine, cosine, logarithm; userValue = queryUserForValue(); generateResults(userValue, sine, cosine, logarithm); outputResults(userValue, sine, cosine, logarithm); return; } CS 140

  40. double queryUserForValue() { double nbr; cout << "Enter the number to be tested: "; cin >> nbr; while (!testValueBounds(nbr)) cin >> nbr; return nbr; } bool testValueBounds(double value) { if (value <= 0.0) { outputWarning(value); returnfalse; } return true; } void outputWarning(double value) { cout << "BAD VALUE: " << value << endl; cout << "(Only positive values are allowed!)" << endl << endl; return; } queryUserForValue calls testValueBounds testValueBounds calls outputWarning CS 140

  41. void generateResults(double val, double &sinVal, double &cosVal, double &logVal) { double valAsRadians = val * 3.1415926535 / 180; sinVal = sin(valAsRadians); cosVal = cos(valAsRadians); logVal = log(val); return; } void outputResults(double val, double sinVal, double cosVal, double logVal) { cout << endl << endl << "The Mathematical Results:" << endl << endl; outputOneResult("Sine", val, sinVal); outputOneResult("Cosine", val, cosVal); outputOneResult("Logarithm", val, logVal); cout << endl << endl; return; } void outputOneResult(char resultName[], double value, double result) { cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(5); cout << setw(9) << resultName << " of " << value << " = " << setw(10) << result << endl; return; } outputResults calls outputOneResult CS 140

  42. Testing Functions When writing a program, it’s a good idea to test individual functions as they’re written, rather than waiting until the entire program is complete. Testing A Calling Function Testing A Called Function When testing a calling function before the called function is written, write a "stub" function to act in place of the called function! When testing a called function before the calling function is written, write a "driver" function to act in place of the calling function! CS 140

  43. #include <iostream> using namespace std; double queryUserForValue(); void computeSeries(double x, double &sum, int &nbrLoops); void outputResults(double result, int iterations); void main() { double number, convergentValue; int nbrIterations; number = queryUserForValue(); computeSeries(number, convergentValue, nbrIterations); outputResults(convergentValue, nbrIterations); } double queryUserForValue() { return 0.00; } void computeSeries(double x, double &sum, int &nbrLoops) { sum = 1.234567899; nbrLoops = 999; } void outputResults(double result, int iterations) { cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(8); cout << "The series converges to " << result << endl << " in " << iterations << " iterations." << endl << endl; } Stub Functions To test whether the main function and the outputResults function are working correctly, the other functions are temporarily written as stubs. When the output is satisfactory, the programmer can proceed to write the real functions. CS 140

  44. A Driver Function The main function below is not the desiredmain function. It was designed to test the calculateDayOfYear function! #include <iostream> using namespace std; int calculateDayOfYear(int theDay, int theMonth, int theYear); void main() { cout << 1 << '/' << 1 << '/' << 2005 << ": DAY #" << calculateDayOfYear(1, 1, 2005) << " (Should be 1)" << endl; cout << 2 << '/' << 28 << '/' << 2005 << ": DAY #" << calculateDayOfYear(28, 2, 2005) << " (Should be 59)" << endl; cout << 2 << '/' << 28 << '/' << 2004 << ": DAY #" << calculateDayOfYear(28, 2, 2004) << " (Should be 59)" << endl; cout << 2 << '/' << 29 << '/' << 2004 << ": DAY #" << calculateDayOfYear(29, 2, 2004) << " (Should be 60)" << endl; cout << 7 << '/' << 4 << '/' << 2005 << ": DAY #" << calculateDayOfYear(4, 7, 2005) << " (Should be 185)" << endl; cout << 12 << '/' << 31 << '/' << 2005 << ": DAY #" << calculateDayOfYear(31, 12, 2005) << " (Should be 365)" << endl; cout << 12 << '/' << 31 << '/' << 2004 << ": DAY #" << calculateDayOfYear(31, 12, 2004) << " (Should be 366)" << endl << endl; return; } CS 140

  45. int calculateDayOfYear(int theDay, int theMonth, int theYear) { int daysSoFar = 0; int cyclingMonth = 1; while (cyclingMonth < theMonth) { if (cyclingMonth == 2) { if (theYear % 4 == 0) daysSoFar += 29; else daysSoFar += 28; } else if ((cyclingMonth == 4) || (cyclingMonth == 6) || (cyclingMonth == 9) || (cyclingMonth == 11)) daysSoFar += 30; else daysSoFar += 31; cyclingMonth++; } daysSoFar += theDay; return daysSoFar; } The results of the test are favorable, with every program-calculated value identical to the corresponding programmer-calculated value. Thus, the calculateDayOfYear function seems to work and the rest of the real program can be written! CS 140

  46. Debugging in Visual C++ .NET #include <iostream> using namespace std; void main() { int value; cout << "Enter a non-zero value: "; cin >> value; while (value = 0) { cout << "No, enter a NON-ZERO value: "; cin >> value; } cout << "You entered the non-zero value " << value << endl; } When a program compiles but does not produce the expected results, the problem isn’t syntax but semantics, i.e., the logic of the program is faulty. Visual C++ .NET has a debugger that allows a programmer to step through the program and determine what’s wrong. This program’s supposed to keep asking for a value until a non-zero value is entered. What went wrong? CS 140

  47. Setting Up The Debugger Set a “breakpoint” where you want the program to stop. Starting at the breakpoint, you’ll be able to step through the program as it executes each line of code. CS 140

  48. Starting The Debugger CS 140

  49. Using The Debugger CS 140

  50. Stepping Through The Program Notice that the program got past the loop without going inside it. So entering zero for value doesn’t cause the loop to be entered! Why is that…? CS 140

More Related