Download presentation
Presentation is loading. Please wait.
Published byBasil Douglas Weaver Modified over 9 years ago
2
Chapter 5 Functions for All Subtasks Goals: To explore the use of void functions To explore the use of void functions To distinguish between call-by-reference and call-by-value To distinguish between call-by-reference and call-by-value To examine how functions can be nested To examine how functions can be nested To introduce testing via stubs and drivers To introduce testing via stubs and drivers To gain some familiarity with the Visual C++ debugger To gain some familiarity with the Visual C++ debugger
3
Chapter 5CS 140Page 2 void Functions When a function returns no value, then it is a void function. void outputResults(int high, int low, int mean) { cout << “High Value: ” << high << endl; cout << “Low Value: ” << low << endl; cout << “Mean Value: ” << mean << endl; return; } 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! Most Common Use For void Functions: Pure Output.
4
Chapter 5CS 140Page 3 Calling void Functions When calling a void function, no return value is expected. 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; } void Function Call Non- void Function Call Non- void Function Call void Function Call Non- void Function Call
5
Chapter 5CS 140Page 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.
6
Chapter 5CS 140Page 5 #include 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.
7
Chapter 5CS 140Page 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.
8
Chapter 5CS 140Page 7 What’s Happening In Memory? mainbegins RAM main x y z main calls retrieveThreeNumbers RAM main retrieveThreeNumbers firstNbr secondNbr thirdNbr Data Heap Keeps track of variables in use. The same memory is being used, but with different variable names! Run-Time Stack Keeps track of function calls; the function that is on top of the stack is the active function.
9
Chapter 5CS 140Page 8 What’s Happening In Memory? (Part 2) return to main from retrieveThreeNumbers RAM main x y z main calls reorderThreeNumbers return to main from reorderThreeNumbers RAM main x y z RAM main reorderThreeNumbers nbrA nbrC temp nbrB
10
Chapter 5CS 140Page 9 RAM What’s Happening In Memory? (Part 3) main calls outputThreeNumbers return to main from outputThreeNumbers RAM main outputThreeNumbers middlesmallest largest The parameters are passed by value, so they do not share memory with main ’s variables! RAM main x y z main ends
11
Chapter 5CS 140Page 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 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 = 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; }
12
Chapter 5CS 140Page 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.
13
Chapter 5CS 140Page 12 Nested Functions Just like main, any function may contain a call to another function within its body. #include 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); }
14
Chapter 5CS 140Page 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); return false; } 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
15
Chapter 5CS 140Page 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
16
Chapter 5CS 140Page 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.
17
Chapter 5CS 140Page 16 #include 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.
18
Chapter 5CS 140Page 17 #include 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; } A Driver Function The main function below is not the desired main function. It was designed to test the calculateDayOfYear function!
19
Chapter 5CS 140Page 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!
20
Chapter 5CS 140Page 19 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. #include 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; } In this program, only three input values were supposed to be accepted. What went wrong?
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.