1 / 19

Chapter 5 Functions for All Subtasks

Chapter 5 Functions 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.

cybele
Download Presentation

Chapter 5 Functions for All Subtasks

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 5Functions 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

  2. 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; } Most Common Use For void Functions: Pure Output. CS 140

  3. 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

  4. Call-by-Reference Parameters When a function isn’t supposed to generate any values, it can be made a void function. When a function is supposed to generate 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 generate 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

  5. #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); } 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; } 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

  6. 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

  7. 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

  8. 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 return tomain from reorderThreeNumbers main calls reorderThreeNumbers CS 140

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

  10. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // 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; } // 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

  11. // 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 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; } 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

  12. NestedFunctions Just like main, any function may contain a call to another function within its body. #include <iostream> #include <iomanip> #include <cmath> #include <string> 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(string 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); } CS 140

  13. 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

  14. 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(string 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

  15. 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

  16. #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

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

  18. 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

  19. #include <iostream> using namespace std; void main() { int i; int value; cout << "Enter three values:" << endl; while (i < 3) { cin >> value; i++; cout << "You entered " << value << endl; } return; } Debugging in Visual C++ 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++ has a debugger that allows a programmer to step through the program and determine what’s wrong. In this program, only three input values were supposed to be accepted. What went wrong? CS 140

More Related