1 / 67

CHAPTER 5 User-Defined Functions

CHAPTER 5 User-Defined Functions. Single-Result Functions Void Functions Nested Functions Overloaded Functions Name Scoping Recursive Functions. CHAPTER 5 – User-Defined Functions. 49. SINGLE-RESULT FUNCTIONS. //////////////////////////////////////////////////////

misu
Download Presentation

CHAPTER 5 User-Defined Functions

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 5 User-Defined Functions • Single-Result Functions • Void Functions • Nested Functions • Overloaded Functions • Name Scoping • Recursive Functions CHAPTER 5 – User-Defined Functions 49

  2. SINGLE-RESULT FUNCTIONS ////////////////////////////////////////////////////// // This program retrieves dimensional box data from // // a user-specified input file and determines the // // maximum volume and the maximum surface area for // // all boxes with dimensions listed in the file. // ////////////////////////////////////////////////////// #include <iostream> #include <fstream> #include <string> using namespace std; double volume(double length, double width, double height); doublesurfaceArea(double length, double width, double height); // The main function queries the user for the input // // file name, opens the file, coordinates the retrieval // // of the dimensional data, and outputs the resulting // // maxima for volumes and surface areas. // void main() { string boxDataFileName; ifstreamboxDataFile; double dim1, dim2, dim3; doublelargestVolume = -1.0; doublelargestSurfaceArea = -1.0; doublenewVolume; doublenewSurfaceArea; Note that two functions are defined (via prototypes) prior to the main function. Each function accepts several values (parameters) for use within the function. Each function has a declared type (in this case, double), meaning that it will return a value of this type to the location in the code where the function was called. CHAPTER 5 – User-Defined Functions 50

  3. cout << "EXTREME BOX CALCULATOR" << endl << "----------------------" << endl; cout << "Enter the name of the file" << endl << "containing box dimension data: "; cin >> boxDataFileName; boxDataFile.open(boxDataFileName.c_str()); while (boxDataFile.fail()) { cout << endl << "NO FILE WITH THAT NAME LOCATED." << endl << "PLEASE TRY AGAIN WITH AN EXISTING FILE.” << endl << endl; cout << "Enter the name of the file" << endl << "containing box dimension data: "; cin >> boxDataFileName; boxDataFile.open(boxDataFileName.c_str()); } boxDataFile >> dim1; while (!boxDataFile.eof()) { boxDataFile >> dim2 >> dim3; newVolume = volume(dim1, dim2, dim3); if (newVolume > largestVolume) largestVolume = newVolume; newSurfaceArea = surfaceArea(dim1, dim2, dim3); if (newSurfaceArea > largestSurfaceArea) largestSurfaceArea = newSurfaceArea; boxDataFile >> dim1; } if ((newVolume < 0.0) || (newSurfaceArea < 0.0)) cout << endl << "NO LEGITIMATE BOX DIMENSIONS FOUND IN FILE"; else cout << endl << "Largest Box Volume: " << int(largestVolume) << " cubic units" << endl << "Largest Box Surface Area: " << int(largestSurfaceArea) << " square units"; cout << endl << endl; return; } The volume function is called, with the values of the three variables dim1, dim2, and dim3 transmitted as arguments, as well as the assumption that the function will return a value of type double. Similarly, the surfaceArea function is called. CHAPTER 5 – User-Defined Functions 51

  4. // The volume function calculates and returns the volume of the // // box with the parameterized dimensions. It returns an invalid // // value if any dimension is determined to be invalid. // double volume(double length, double width, double height) { if ((length >= 0.0) && (width >= 0.0) && (height >= 0.0)) return (length * width * height); else return -1.0; } // The surfaceArea function calculates and returns the surface // // of the box with the parameterized dimensions. It returns an // // invalid value if any dimension is determined to be invalid. // doublesurfaceArea(double length, double width, double height) { doublefrontArea = length * height; doublesideArea = width * height; doubletopArea = length * width; if ((length >= 0.0) && (width >= 0.0) && (height >= 0.0)) return (2 * frontArea + 2 * sideArea + 2 * topArea); else return -1.0; } The function header is identical to the prototype (except for the semicolon at the end of the prototype). Since the functions are defined with type double they must return a value of that type (unlike the void main function). 30.7 45.9 20.4 82.6 17.1 10.6 66.2 80.1 17.4 28.7 67 3 39.6 75.2 18.0 43.3 13.9 18.2 90.2 46.8 23.4 19.4 91.7 62.8 4.7 28.6 12.7 87.4 33.2 56.7 33.1 17.8 78.1 81.7 22.6 33.9 77.1 45.9 25.8 15.7 66.2 62.1 60.0 29.5 50.3 39.1 Note that the parameters are treated as variables inside the function, and that the functions may have their own “local” variables as well. CHAPTER 5 – User-Defined Functions 52

  5. VOID FUNCTIONS When a function is not set up to return a single result, it is declared as a void function. ////////////////////////////////////////////// // 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; doublequeryUserForValue(); voidcomputeSeries(double x, double &sum, int &nbrLoops); voidoutputResults(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; intnbrIterations; number = queryUserForValue(); computeSeries(number, convergentValue, nbrIterations); outputResults(convergentValue, nbrIterations); } Any parameter with an ampersand (&) preceding its name is being “passed by reference”, meaning that the calling function and the called function are actually sharing that variable’s memory. Parameters without ampersands preceding their names are “passed by value”, meaning that a copy of the calling function’s value is placed in a new variable in the called function. CHAPTER 5 – User-Defined Functions 53

  6. // This function queries the user for the // // power series generator value, which must // // be strictly between 0 and 1. // doublequeryUserForValue() { doublenbr; 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; } returnnbr; } // 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. // voidcomputeSeries(double x, double &sum, int &nbrLoops) { doublepowerOfX, previousSum = 0.0; nbrLoops = 0; sum = x; powerOfX = x; while (previousSum < sum) { nbrLoops++; previousSum = sum; powerOfX *= x; sum += powerOfX; } } This function has one value that won’t be altered (x) and two that will (sum and nbrLoops). The first is passed by value while the other two are passed by reference. CHAPTER 5 – User-Defined Functions 54

  7. // This function outputs the power series // // final value, as well as the number of // // iterations required to obtain it. // voidoutputResults(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; } To format floating-point output, the setf (using fixed for non-scientific notation and showpoint to always show the decimal point) and precision output functions are available. CHAPTER 5 – User-Defined Functions 55

  8. NESTED FUNCTIONS The main function is not the only function that can call other functions. Any function can be set up to do so! //////////////////////////////////////////////////////////////// // This program queries the user for the coefficients of a // // cubic polynomial and then uses ASCII characters to graph // // the polynomial in a user-specified range of the x-y plane. // //////////////////////////////////////////////////////////////// #include <iostream> #include <cmath> using namespace std; voidqueryUserForCoefficients(double &coeff3, double &coeff2, double &coeff1, double &coeff0); doublequeryUserForCoefficient(int exponent); voidqueryUserForRange(charaxisLabel, int &rangeMin, int &rangeMax); voidgraphCubic(intxMin, intxMax, intyMin, intyMax, double coeff3, double coeff2, double coeff1, double coeff0); voidoutputLabel(double coeff3, double coeff2, double coeff1, double coeff0); voidoutputCubicTerm(double coeff3); voidoutputQuadraticTerm(double coeff3, double coeff2); voidoutputLinearTerm(double coeff3, double coeff2, double coeff1); voidoutputConstantTerm(double coeff3, double coeff2, double coeff1, double coeff0); voidoutputStrip(intyVal, intxMin, intxMax, double coeff3, double coeff2, double coeff1, double coeff0); boolclosePoint(intxVal, intyVal, double coeff3, double coeff2, double coeff1, double coeff0); CHAPTER 5 – User-Defined Functions 56

  9. // The main function supervises querying the user for the // // cubic's coefficients and the range to be used within the // // x-y plane, as well as the actual graphing of the cubic. // void main() { doublecubicCoeff, quadraticCoeff, linearCoeff, constantCoeff; intminXValue, maxXValue, minYValue, maxYValue; queryUserForCoefficients(cubicCoeff, quadraticCoeff, linearCoeff, constantCoeff); queryUserForRange('x', minXValue, maxXValue); queryUserForRange('y', minYValue, maxYValue); graphCubic(minXValue, maxXValue, minYValue, maxYValue, cubicCoeff, quadraticCoeff, linearCoeff, constantCoeff); return; } // This function queries the user for four values that will be used // // as polynomial coefficients for the cubic that is being graphed. // voidqueryUserForCoefficients(double &coeff3, double &coeff2, double &coeff1, double &coeff0) { coeff3 = queryUserForCoefficient(3); coeff2 = queryUserForCoefficient(2); coeff1 = queryUserForCoefficient(1); coeff0 = queryUserForCoefficient(0); cout << endl; return; } CHAPTER 5 – User-Defined Functions 57

  10. // This function queries the user for the coefficient of the term // // of the cubic polynomial that has the parameterized exponent. // doublequeryUserForCoefficient(int exponent) { doublecoeff; cout << "Enter the coefficient of the "; switch (exponent) { case 3: { cout << "cubic"; break; } case 2: { cout << "quadratic"; break; } case 1: { cout << "linear"; break; } default: { cout << "constant"; break; } } cout << " term of the polynomial: "; switch (exponent) { case 3: { cout << " "; break; } case 1: { cout << " "; break; } case 0: { cout << " "; break; } } cin >> coeff; returncoeff; } CHAPTER 5 – User-Defined Functions 58

  11. // This function queries the user for the minimum and maximum // // values for the specified axis. These values will be used // // to limit the range of the graphing of the cubic polynomial. // voidqueryUserForRange(charaxisLabel, int &rangeMin, int &rangeMax) { cout << "Enter the range of " << axisLabel << "-values to be used in the graph." << endl; cout << "Minimum " << axisLabel << "-value: "; cin >> rangeMin; cout << "Maximum " << axisLabel << "-value: "; cin >> rangeMax; cout << endl; while (rangeMin >= rangeMax) { cout << "INAPPROPRIATE RANGE --- MAXIMUM MUST BE GREATER THAN MINIMUM." << endl; cout << "Enter the range of " << axisLabel << "-values to be used in the graph." << endl; cout << "Minimum " << axisLabel << "-value: "; cin >> rangeMin; cout << "Maximum " << axisLabel << "-value: "; cin >> rangeMax; cout << endl; } return; } CHAPTER 5 – User-Defined Functions 59

  12. // This function uses ASCII characters to graph the cubic polynomial // // with the parameterized coefficients within the parameterized range. // // Where appropriate, characters representing the axes will be output. // voidgraphCubic(intxMin, intxMax, intyMin, intyMax, double coeff3, double coeff2, double coeff1, double coeff0) { intyVal = yMax; outputLabel(coeff3, coeff2, coeff1, coeff0); while (yVal >= yMin) { outputStrip(yVal, xMin, xMax, coeff3, coeff2, coeff1, coeff0); yVal--; } cout << endl << endl; return; } // This function outputs the label identifying the // // precise cubic polynomial that is being graphed. // voidoutputLabel(double coeff3, double coeff2, double coeff1, double coeff0) { cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(3); cout << endl << "GRAPH OF f(x) = "; outputCubicTerm(coeff3); outputQuadraticTerm(coeff3, coeff2); outputLinearTerm(coeff3, coeff2, coeff1); outputConstantTerm(coeff3, coeff2, coeff1, coeff0); cout << endl << endl; return; } CHAPTER 5 – User-Defined Functions 60

  13. // This function outputs the cubic term of the polynomial // // being graphed, with special cases for cubic coefficient // // values of 0 (no output), 1 (no displayed coefficient), // // or -1 (a negative sign, but no displayed coefficient). // voidoutputCubicTerm(double coeff3) { if (coeff3 != 0.0) { if (coeff3 == -1.0) cout << '-'; else if (coeff3 != 1.0) cout << coeff3; cout << "x^3"; } return; } // This function outputs the quadratic term of the polynomial // // being graphed, with special cases for quadratic coefficient // // values of 0 (no output), 1 (no displayed coefficient), or // // -1 (a negative sign, but no displayed coefficient). // voidoutputQuadraticTerm(double coeff3, double coeff2) { if (coeff2 != 0.0) { if (coeff3 != 0.0) { if (coeff2 < 0.0) { cout << " - "; coeff2 *= -1; } else cout << " + "; } if (coeff2 != 1.0) cout << coeff2; cout << "x^2"; } return; } CHAPTER 5 – User-Defined Functions 61

  14. // This function outputs the linear term of the polynomial // // being graphed, with special cases for linear coefficient // // values of 0 (no output), 1 (no displayed coefficient), // // or -1 (a negative sign, but no displayed coefficient). // voidoutputLinearTerm(double coeff3, double coeff2, double coeff1) { if (coeff1 != 0.0) { if ((coeff3 != 0.0) || (coeff2 != 0.0)) { if (coeff1 < 0.0) { cout << " - "; coeff1 *= -1; } else cout << " + "; } if (coeff1 != 1.0) cout << coeff1; cout << "x"; } return; } CHAPTER 5 – User-Defined Functions 62

  15. // This function outputs the constant term of the polynomial // // being graphed, with special cases for constant coefficient // // values of 0 (no output, unless there are no other terms in // // the polynomial) or nonzero (output the constant, prefaced // // with the appropriate mathematical operator if there are // // other terms in the polynomial). // voidoutputConstantTerm(double coeff3, double coeff2, double coeff1, double coeff0) { if (coeff0 == 0.0) { if ((coeff3 == 0) && (coeff2 == 0) && (coeff1 == 0)) cout << coeff0; } else { if ((coeff3 != 0.0) || (coeff2 != 0.0) || (coeff1 != 0.0)) { if (coeff0 < 0.0) cout << " - " << (-1 * coeff0); else cout << " + " << coeff0; } else cout << coeff0; } return; } CHAPTER 5 – User-Defined Functions 63

  16. // This function outputs the horizontal strip of characters // // representing the graph at a particular y-value, with a // // asterisks used to represent the graph itself, vertical // // bars, dashes, and plus signs used to represent the axes, // // and blanks used for all empty space. // voidoutputStrip(intyVal, intxMin, intxMax, double coeff3, double coeff2, double coeff1, double coeff0) { intxVal = xMin; while (xVal <= xMax) { if (closePoint(xVal, yVal, coeff3, coeff2, coeff1, coeff0)) cout << '*'; else if ((xVal == 0) && (yVal == 0)) cout << '+'; else if (xVal == 0) cout << '|'; else if (yVal == 0) cout << '-'; else cout << ' '; xVal++; } cout << endl; return; } // This function evaluates the cubic polynomial with // // the parameterized coefficients at the parameterized // // x-value, and determines whether the resulting y-value // // (after round-off) equals the parameterized y-value. // boolclosePoint(intxVal, intyVal, double coeff3, double coeff2, double coeff1, double coeff0) { doubleactualY = coeff3 * pow(double(xVal), 3) + coeff2 * pow(double(xVal), 2) + coeff1 * xVal + coeff0; return (int(actualY) == yVal); } CHAPTER 5 – User-Defined Functions 64

  17. CHAPTER 5 – User-Defined Functions 65

  18. OVERLOADED FUNCTIONS A program may have multiple functions with the same name, as long as the compiler can distinguish between them and determine which one is actually being called. This is normally accomplished by using different parameter lists (either by using a different number of parameters or different parameter types). /////////////////////////////////////////////////////////////////// // This program demonstrates overloaded functions be utilizing // // two versions of the dot product function, one taking vectors // // of double coordinates and the other taking vectors of integer // // coordinates. // /////////////////////////////////////////////////////////////////// #include <iostream> using namespace std; boolisInt(double value); doubledotProduct(double x1, double y1, double x2, double y2); intdotProduct(int x1, int y1, int x2, int y2); charaskForMore(); boolanswerIsYes(charltr); boolanswerIsNo(charltr); CHAPTER 5 – User-Defined Functions 66

  19. // The main function coordinates the user queries // // and the output of dot product results. // void main() { doublefirstX, firstY, secondX, secondY; charyOrN = 'y'; while ( answerIsYes(yOrN) ) { cout << "Enter the coordinates for the first vector: "; cin >> firstX >> firstY; cout << "Enter the coordinates for the second vector: "; cin >> secondX >> secondY; if ( isInt(firstX) && isInt(firstY) && isInt(secondX) && isInt(secondY) ) cout << dotProduct( int(firstX), int(firstY), int(secondX), int(secondY) ); else cout << dotProduct( firstX, firstY, secondX, secondY ); cout << endl << endl; yOrN = askForMore(); } return; } // Returns a boolean flag indicating whether the // // parameterized double value has no fractional component. // boolisInt(double value) { return ( value - int(value) == 0.0 ); } CHAPTER 5 – User-Defined Functions 67

  20. // Returns the dot product of two vectors of double values. // doubledotProduct(double x1, double y1, double x2, double y2) { return (x1 * x2 + y1 * y2); } // Returns the dot product of two vectors of integer values. // intdotProduct(int x1, int y1, int x2, int y2) { return (x1 * x2 + y1 * y2); } // Queries the user for whether more dot product calculations are needed, // // compelling the user to respond with an appropriate character. // charaskForMore() { char letter; cout << "Would you like to take another dot product? (Y or N) "; cin >> letter; while ( (!answerIsYes(letter)) && (!answerIsNo(letter)) ) { cout << "You must respond with the letter Y or the letter N!" << endl; cout << "Would you like to take another dot product? (Y or N) "; cin >> letter; } return letter; } CHAPTER 5 – User-Defined Functions 68

  21. // Returns a boolean flag indicating whether the parameterized // // character is the first letter of the word "yes". // boolanswerIsYes(charltr) { return ( (ltr == 'y') || (ltr == 'Y') ); } // Returns a boolean flag indicating whether the parameterized // // character is the first letter of the word "no". // boolanswerIsNo(charltr) { return ( (ltr == 'n') || (ltr == 'N') ); } CHAPTER 5 – User-Defined Functions 69

  22. NAME SCOPING Variable names are “local” to the function in which they are declared. ///////////////////////////////////////////////////////// // This program reads date information from a specific // // text file, determining the percentage of dates in // // that file that utilize each of the twelve months. // ///////////////////////////////////////////////////////// #include <iostream> #include <fstream> using namespace std; intcountData(); intcountData(int month); // The main function supervises // // the retrieval of the date // // information and formats the // // program's output. // void main() { int month; int total; int count; double percent; total = countData(); cout << " DATE FILE DATA ANALYSIS" << endl << " -----------------------" << endl; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(4); for (month = 1; month <= 12; month++) { count = countData(month); percent = 100.0 * count / total; if (percent < 10.0) cout << " "; else if (percent < 100.0) cout << " "; cout << percent << "% of the dates are " << "from month #" << month << endl; } cout << endl << endl; return; } Thus, the same variable names may be used independently in separate functions. CHAPTER 5 – User-Defined Functions 70

  23. 9 17 1929 11 22 1930 4 4 1934 2 27 1936 7 4 1936 8 3 1938 2 16 1940 10 16 1941 5 4 1943 7 11 1944 2 20 1945 1 27 1946 6 30 1947 4 11 1948 8 29 1949 11 19 1950 12 3 1952 5 13 1953 10 31 1956 9 12 1957 12 25 1958 1 12 1961 6 10 1962 6 12 1962 3 20 1965 11 5 1967 8 2 1969 12 9 1972 1 30 1974 7 17 1976 12 12 1978 2 20 1980 3 27 1982 3 12 1984 11 7 1985 5 14 1986 9 22 1986 12 3 1986 5 12 1987 2 1 1988 5 16 1988 8 27 1990 7 20 1991 12 28 1993 8 21 1994 2 10 1996 9 13 1997 Like main, both functions have local variables names count and month. // This function opens the date data file and counts // // the total number of dates contained therein. // intcountData() { int count = 0; int month, day, year; ifstreamdateFile; dateFile.open("dates.txt"); dateFile >> month; while ( !dateFile.eof() ) { dateFile >> day >> year; count++; dateFile >> month; } dateFile.close(); return count; } // This function opens the date data file and counts // // the total number of dates contained therein that // // utilize the parameterized month. // intcountData(int month) { int count = 0; intthisMonth, day, year; ifstreamdateFile; dateFile.open("dates.txt"); dateFile >> thisMonth; while ( !dateFile.eof() ) { dateFile >> day >> year; if (thisMonth == month) count++; dateFile >> thisMonth } dateFile.close(); return count; } The values of each function’s versions of count and month are completely independent of each other! CHAPTER 5 – User-Defined Functions 71

  24. RECURSIVE FUNCTIONS ////////////////////////////////////////////////////// // This program repeatedly asks the user for // // non-negative integer values and then recursively // // converts them into hexadecimal (base 16). // ////////////////////////////////////////////////////// #include<iostream> using namespace std; intretrieveValue(); voidconvertToHexadecimal(int value); charhexDigit(int digit); boolqueryForMore(); // The main function supervises the retrieval of data from // the user, the conversion of that data to hexadecimal, // and the determination of when the user is finished. void main() { intuserValue; boolstillActive = true; while (stillActive) { userValue = retrieveValue(); cout << "HEXADECIMAL FORM OF " << userValue << " IS "; convertToHexadecimal(userValue); cout << endl << endl; stillActive = queryForMore(); } return; } Not only are functions able to call other functions, they can also call themselves. CHAPTER 5 – User-Defined Functions 72

  25. Essentially, recursive functions take a divide-and-conquer approach. // This function queries the user until supplied // with a non-negative integer value. intretrieveValue() { intintegerValue; cout << "Please enter a non-negative integer: "; cin >> integerValue; while (integerValue < 0) { cout << endl << "Try again, The value must be non-negative: "; cin >> integerValue; } cout << endl; returnintegerValue; } // This function repeatedly divides the parameterized value by 16, // recursively converting the quotient into hexadecimal, followed // by outputting the remainder (an integer between 0 and 15) into // a single hexadecimal digit, which is output to the screen. voidconvertToHexadecimal(int value) { if (value < 16) cout << hexDigit(value); else { convertToHexadecimal(value / 16); cout << hexDigit(value % 16); } } The large task being attempted is completed by breaking it down into a smaller version of itself. This approach is continued until the task gets small enough to resolve without breaking it down any further. CHAPTER 5 – User-Defined Functions 73

  26. // This function converts the parameterized integer value (assumed // to between 0 and 15) into the corresponding hexadecimal digit. // The hexadecimal digit is returned as a character value. charhexDigit(int digit) { switch (digit) { case 10: { return'A'; break; } case 11: { return'B'; break; } case 12: { return'C'; break; } case 13: { return'D'; break; } case 14: { return'E'; break; } case 15: { return'F'; break; } default: { returnchar(digit + int('0')); break; } } } // This function queries the user about additional input // until an appropriate character is entered, boolqueryForMore() { charqueryResponse; cout << "Would you like to convert another integer? (Y or N) "; cin >> queryResponse; while ( (queryResponse != 'y') && (queryResponse != 'Y') && (queryResponse != 'n') && (queryResponse != 'N') ) { cout << "You must enter Y for Yes or N for No." << endl << endl << "Would you like to convert another integer? (Y or N) "; cin >> queryResponse; } cout << endl; return ( (queryResponse == 'y') || (queryResponse == 'Y') ); } CHAPTER 5 – User-Defined Functions 74

  27. CHAPTER 6 Data Structures and Objects • Structures • Classes • Constructors • Accessors and Mutators • Overloaded Operators • Class Reuse CHAPTER 6 – Data Structures and Objects 75

  28. STRUCTURES /////////////////////////////////////////////// // This program queries the user for a // // chemical element and accesses an external // // file to retrieve data about that element. // /////////////////////////////////////////////// #include <iostream> #include <fstream> #include <string> using namespace std; struct Element { intAtomicNumber; string Name; string Symbol; string ChemicalSeries; int Level1Electrons; int Level2Electrons; int Level3Electrons; int Level4Electrons; int Level5Electrons; int Level6Electrons; int Level7Electrons; }; Element queryUserForElement(); Element searchByAtomicNumber(ifstream &file); Element searchByAtomicSymbol(ifstream &file); voidoutputElement(Element elt); Placing related variables into a single entity, a structure, may simplify the programming process by limiting how many parameters are needed for some functions. Once defined, the new structure may be used as a parameter for a function or as a function’s return type. CHAPTER 6 – Data Structures and Objects 76

  29. // The main function outputs a header and then supervises // the user query and the output of information about the // user-specified chemical element. void main() { Element elem; cout << "CHEMICAL ELEMENT DATA FINDER" << endl; cout << "----------------------------" << endl; elem = queryUserForElement(); outputElement(elem); cout << endl << endl; return; } // This function coordinates the user query by first // determining whether the user wants to find the // chemical element by specifying its atomic number // or by specifying its atomic symbol. Element queryUserForElement() { Element elmnt; charsearchChar; ifstreamElementFile; ElementFile.open("Elements.txt"); cout << "Enter # to search by atomic number," << endl << "anything else to search by atomic symbol: "; cin >> searchChar; if (searchChar == '#') elmnt = searchByAtomicNumber(ElementFile); else elmnt = searchByAtomicSymbol(ElementFile); ElementFile.close(); returnelmnt; } CHAPTER 6 – Data Structures and Objects 77

  30. // This function searches the parameterized input file for // a user-specified atomic number, returning the Element // that matches (or forcing the user to enter another // atomic number if the previous one was invalid). Element searchByAtomicNumber(ifstream &file) { intaNbr; int index; Element e; cout << "Enter the atomic number of the element being sought: "; cin >> aNbr; while ( (aNbr <= 0) || (aNbr > 118) ) { cout << "Atomic numbers are limited to the 1-118 range." << endl << "Please try again: "; cin >> aNbr; } for (index = 1; index <= aNbr; index++) { file >> e.AtomicNumber; file >> e.Name; file >> e.Symbol; file >> e.ChemicalSeries; file >> e.Level1Electrons; file >> e.Level2Electrons; file >> e.Level3Electrons; file >> e.Level4Electrons; file >> e.Level5Electrons; file >> e.Level6Electrons; file >> e.Level7Electrons; } return e; } CHAPTER 6 – Data Structures and Objects 78

  31. // This function searches the parameterized input file for // a user-specified atomic symbol, returning the Element // that matches (or forcing the user to enter another // atomic symbol if the previous one was invalid). Element searchByAtomicSymbol(ifstream &file) { boolfoundElement = false; intaNbr; string aSym; Element e; cout << "Enter the atomic symbol of the element being sought: "; cin >> aSym; do { aNbr = 0; while ( (aNbr < 118) && (!foundElement) ) { aNbr++; file >> e.AtomicNumber; file >> e.Name; file >> e.Symbol; file >> e.ChemicalSeries; file >> e.Level1Electrons; file >> e.Level2Electrons; file >> e.Level3Electrons; file >> e.Level4Electrons; file >> e.Level5Electrons; file >> e.Level6Electrons; file >> e.Level7Electrons; foundElement = (e.Symbol == aSym); } if (!foundElement) { cout << "The symbol you entered (" << aSym << ") is invalid." << endl << "Please try again: "; cin >> aSym; file.close(); file.open("Elements.txt"); } } while (!foundElement); return e; } CHAPTER 6 – Data Structures and Objects 79

  32. // This function outputs the data associated with the parameterized chemical element. voidoutputElement(Element elt) { cout << endl << "Information about the element " << elt.Name << ":" << endl; cout << " Atomic Number: " << elt.AtomicNumber << endl; cout << " Atomic Symbol: " << elt.Symbol << endl; cout<< " Chemical Series: " << elt.ChemicalSeries << endl; cout << "# Level 1 Electrons: " << elt.Level1Electrons << endl; if (elt.Level2Electrons > 0) { cout << "# Level 2 Electrons: " << elt.Level2Electrons << endl; if (elt.Level3Electrons > 0) { cout << "# Level 3 Electrons: " << elt.Level3Electrons << endl; if (elt.Level4Electrons > 0) { cout << "# Level 4 Electrons: " << elt.Level4Electrons << endl; if (elt.Level5Electrons > 0) { cout<< "# Level 5 Electrons: " << elt.Level5Electrons << endl; if (elt.Level6Electrons > 0) { cout << "# Level 6 Electrons: " << elt.Level6Electrons << endl; if (elt.Level7Electrons > 0) cout<< "# Level 7 Electrons: " << elt.Level7Electrons << endl; } } } } } return; } CHAPTER 6 – Data Structures and Objects 80

  33. 1 Hydrogen H Nonmetal 1 0 0 0 0 0 0 2 Helium He NobleGas 2 0 0 0 0 0 0 3 Lithium Li AlkaliMetal 2 1 0 0 0 0 0 4 Beryllium Be AlkalineEarthMetal 2 2 0 0 0 0 0 5 Boron B Metalloid 2 3 0 0 0 0 0 6 Carbon C Nonmetal 2 4 0 0 0 0 0 7 Nitrogen N Nonmetal 2 5 0 0 0 0 0 8 Oxygen O Nonmetal 2 6 0 0 0 0 0 9 Fluorine F Halogen 2 7 0 0 0 0 0 10 Neon Ne NobleGas 2 8 0 0 0 0 0 11 Sodium Na AlkaliMetal 2 8 1 0 0 0 0 12 Magnesium Mg AlkalineEarthMetal 2 8 2 0 0 0 0 13 Aluminium Al PoorMetal 2 8 3 0 0 0 0 14 Silicon Si Metalloid 2 8 4 0 0 0 0 15 Phosphorus P Nonmetal 2 8 5 0 0 0 0 16 Sulfur S Nonmetal 2 8 6 0 0 0 0 17 Chlorine Cl Halogen 2 8 7 0 0 0 0 18 Argon Ar NobleGas 2 8 8 0 0 0 0 19 Potassium K AlkaliMetal 2 8 8 1 0 0 0 20 Calcium Ca AlkalineEarthMetal 2 8 8 2 0 0 0 21 Scandium Sc TransitionMetal 2 8 9 2 0 0 0 22 Titanium Ti TransitionMetal 2 8 10 2 0 0 0 23 Vanadium V TransitionMetal 2 8 11 2 0 0 0 24 Chromium Cr TransitionMetal 2 8 13 1 0 0 0 25 Manganese Mn TransitionMetal 2 8 13 2 0 0 0 26 Iron Fe TransitionMetal 2 8 14 2 0 0 0 27 Cobalt Co TransitionMetal 2 8 15 2 0 0 0 28 Nickel Ni TransitionMetal 2 8 16 2 0 0 0 29 Copper Cu TransitionMetal 2 8 18 1 0 0 0 30 Zinc Zn TransitionMetal 2 8 18 2 0 0 0 31 Gallium Ga PoorMetal 2 8 18 3 0 0 0 32 Germanium Ge Metalloid 2 8 18 4 0 0 0 33 Arsenic As Metalloid 2 8 18 5 0 0 0 34 Selenium Se Nonmetal 2 8 18 6 0 0 0 35 Bromine Br Halogen 2 8 18 7 0 0 0 36 Krypton Kr NobleGas 2 8 18 8 0 0 0 37 Rubidium Rb AlkaliMetal 2 8 18 8 1 0 0 38 Strontium Sr AlkalineEarthMetal 2 8 18 8 2 0 0 39 Yttrium Y TransitionMetal 2 8 18 9 2 0 0 40 Zirconium Zr TransitionMetal 2 8 18 10 2 0 0 41 Niobium Nb TransitionMetal 2 8 18 12 1 0 0 42 Molybdenum Mo TransitionMetal 2 8 18 13 1 0 0 43 Technetium Tc TransitionMetal 2 8 18 14 1 0 0 44 Ruthenium Ru TransitionMetal 2 8 18 15 1 0 0 45 Rhodium Rh TransitionMetal 2 8 18 16 1 0 0 46 Palladium Pd TransitionMetal 2 8 18 18 0 0 0 47 Silver Ag TransitionMetal 2 8 18 18 1 0 0 48 Cadmium Cd TransitionMetal 2 8 18 18 2 0 0 49 Indium In PoorMetal 2 8 18 18 3 0 0 50 Tin Sn PoorMetal 2 8 18 18 4 0 0 51 Antimony Sb Metalloid 2 8 18 18 5 0 0 52 Tellurium Te Metalloid 2 8 18 18 6 0 0 53 Iodine I Halogen 2 8 18 18 7 0 0 54 Xenon Xe NobleGas 2 8 18 18 8 0 0 55 Caesium Cs AlkaliMetal 2 8 18 18 8 1 0 56 Barium Ba AlkalineEarthMetal 2 8 18 18 8 2 0 57 Lanthanum La Lanthanide 2 8 18 18 9 2 0 58 Cerium Ce Lanthanide 2 8 18 19 9 2 0 59 Praseodymium Pr Lanthanide 2 8 18 21 8 2 0 60 Neodymium Nd Lanthanide 2 8 18 22 8 2 0 61 Promethium Pm Lanthanide 2 8 18 23 8 2 0 62 Samarium Sm Lanthanide 2 8 18 24 8 2 0 63 Europium Eu Lanthanide 2 8 18 25 8 2 0 64 Gadolinium Gd Lanthanide 2 8 18 25 9 2 0 65 Terbium Tb Lanthanide 2 8 18 27 8 2 0 66 Dysprosium Dy Lanthanide 2 8 18 28 8 2 0 67 Holmium Ho Lanthanide 2 8 18 29 8 2 0 68 Erbium Er Lanthanide 2 8 18 30 8 2 0 69 Thulium Tm Lanthanide 2 8 18 31 8 2 0 70 Ytterbium Yb Lanthanide 2 8 18 32 8 2 0 71 Lutetium Lu Lanthanide 2 8 18 32 9 2 0 72 Hafnium Hf TransitionMetal 2 8 18 32 10 2 0 73 Tantalum Ta TransitionMetal 2 8 18 32 11 2 0 74 Tungsten W TransitionMetal 2 8 18 32 12 2 0 75 Rhenium Re TransitionMetal 2 8 18 32 13 2 0 76 Osmium Os TransitionMetal 2 8 18 32 14 2 0 77 Iridium Ir TransitionMetal 2 8 18 32 15 2 0 78 Platinum Pt TransitionMetal 2 8 18 32 17 1 0 79 Gold Au TransitionMetal 2 8 18 32 18 1 0 80 Mercury Hg TransitionMetal 2 8 18 32 18 2 0 81 Thallium Tl PoorMetal 2 8 18 32 18 3 0 82 Lead Pb PoorMetal 2 8 18 32 18 4 0 83 Bismuth Bi PoorMetal 2 8 18 32 18 5 0 84 Polonium Po Metalloid 2 8 18 32 18 6 0 85 Astatine At Halogen 2 8 18 32 18 7 0 86 Radon Rn NobleGas 2 8 18 32 18 8 0 87 Francium Fr AlkaliMetal 2 8 18 32 18 8 1 88 Radium Ra AlkalineEarthMetal 2 8 18 32 18 8 2 89 Actinium Ac Actinide 2 8 18 32 18 9 2 90 Thorium Th Actinide 2 8 18 32 18 10 2 91 Protactinium Pa Actinide 2 8 18 32 20 9 2 92 Uranium U Actinide 2 8 18 32 21 9 2 93 Neptunium Np Actinide 2 8 18 32 22 9 2 94 Plutonium Pu Actinide 2 8 18 32 24 8 2 95 Americium Am Actinide 2 8 18 32 25 8 2 96 Curium Cm Actinide 2 8 18 32 25 9 2 97 Berkelium Bk Actinide 2 8 18 32 27 8 2 98 Californium Cf Actinide 2 8 18 32 28 8 2 99 Einsteinium Es Actinide 2 8 18 32 29 8 2 100 Fermium Fm Actinide 2 8 18 32 30 8 2 101 Mendelevium Md Actinide 2 8 18 32 31 8 2 102 Nobelium No Actinide 2 8 18 32 32 8 2 103 Lawrencium Lr Actinide 2 8 18 32 32 9 2 104 Rutherfordium Rf TransitionMetal 2 8 18 32 32 10 2 105 Dubnium Db TransitionMetal 2 8 18 32 32 11 2 106 Seaborgium Sg TransitionMetal 2 8 18 32 32 12 2 107 Bohrium Bh TransitionMetal 2 8 18 32 32 13 2 108 Hassium Hs TransitionMetal 2 8 18 32 32 14 2 109 Meitnerium Mt TransitionMetal 2 8 18 32 32 15 2 110 Darmstadtium Ds TransitionMetal 2 8 18 32 32 16 2 111 Roentgenium Rg TransitionMetal 2 8 18 32 32 17 2 112 Ununbium Uub TransitionMetal 2 8 18 32 32 18 2 113 Ununtrium Uut PoorMetal 2 8 18 32 32 18 3 114 Ununquadium Uuq PoorMetal 2 8 18 32 32 18 4 115 Ununpentium Uup PoorMetal 2 8 18 32 32 18 5 116 Ununhexium Uuh PoorMetal 2 8 18 32 32 18 6 117 Ununseptium Uus Halogen 2 8 18 32 32 18 7 118 Ununoctium Uuo NobleGas 2 8 18 32 32 18 8 CHAPTER 6 – Data Structures and Objects 81

  34. CLASSES Classes are used to implement the object-oriented programming feature of encapsulation, by which the details of how the data of the class is structured and how it operates are hidden from code outside of the class. Each class is a collection of members: • Data members are the data components of the class, usually marked as private to prevent direct access from outside of the class. • Constructors are the mechanism by which new variables of the type defined by the class can be declared, marked as public to allow access from outside of the class. • Accessors are the public mechanism by which code outside of the class is allowed to have indirect access to the data members. • Member functions are operations that are defined within the class, some of which may be public and some of which may be private. CHAPTER 6 – Data Structures and Objects 82

  35. ///////////////////////////////////////////////// // This program generates the data for circles // // and then draws them using ASCII characters. // ///////////////////////////////////////////////// #include <iostream> #include <cmath> using namespace std; const double PI = 3.1416; const intPADDING = 3; const intASCII_ZERO_VALUE = 48; class Circle { public: // Constructor Circle(); // Member functions voidsetCoordinates(int x, int y); voidsetRadius(int r); voidsetASCIICharacter(charch); doublecomputeArea(); doublecomputePerimeter(); voiddisplayCircleAttributes(); voiddrawCircle(); // Accessor functions intgetXCoord() const; intgetYCoord() const; intgetRadius() const; chargetASCIICharacter() const; private: // Data members intxCoord; intyCoord; int radius; charasciiCharacter; }; // This default constructor sets up the // // data members with default values. // Circle::Circle() { xCoord = yCoord = radius = 0; asciiCharacter = ' '; } // Assign the x- and y- coordinates of the // // circle's center with parameterized values. // voidCircle::setCoordinates(int x, int y) { xCoord = x; yCoord = y; return; } // Assign the radius of the circle // // the parameterized value. // void Circle::setRadius(int r) { radius = r; return; } CHAPTER 6 – Data Structures and Objects 83

  36. // Assign the fill character of the // // circle the parameterized value. // void Circle::setASCIICharacter(charch) { asciiCharacter = ch; return; } // Compute and return the area of the circle. // double Circle::computeArea() { return PI * radius * radius; } // Compute and return the perimeter of the circle. // double Circle::computePerimeter() { return 2 * PI * radius; } // Output the circle's data member values, as // // well as the area and perimeter of the Circle. // void Circle::displayCircleAttributes() { cout.setf(ios::fixed); cout.precision(4); cout << "Center's x-coordinate: " << xCoord << endl; cout << "Center's y-coordinate: " << yCoord << endl; cout << "Circle's radius: " << radius << endl; cout << "Circle's area: " << computeArea() << endl; cout << "Circle's perimeter: " << computePerimeter() << endl; cout << "Circle's fill character: " << asciiCharacter << endl; } Notice the use of the class name followed by the scope resolution operator (::) just before the name of the member function. This is needed whenever the definition of the member function is outside of the declaration of the class. CHAPTER 6 – Data Structures and Objects 84

  37. // Output the Circle, using its ASCII character to draw it, // // as well as vertical and horizontal symbols to draw the // // coordinate axes, and an 'X' at the center of the circle. // void Circle::drawCircle() { const intPADDING = 4; const double HEIGHT_WIDTH_RATIO = 1.5; int x, y; intlowerX = (xCoord - radius < -PADDING) ? (xCoord - radius-PADDING) : -PADDING; intupperX = (xCoord + radius > PADDING) ? (xCoord + radius+PADDING) : PADDING; intlowerY = (yCoord - radius < -PADDING) ? (yCoord - radius-PADDING) : -PADDING; intupperY = (yCoord + radius > PADDING) ? (yCoord + radius+PADDING) : PADDING; for (y = upperY; y >= lowerY; y--) { for (x = int(HEIGHT_WIDTH_RATIO*lowerX); x <= int(HEIGHT_WIDTH_RATIO*upperX); x++) { if ((x == xCoord) && (y == yCoord)) cout << 'X'; else if (pow((x - xCoord) / HEIGHT_WIDTH_RATIO, 2) + pow(double(y - yCoord), 2) <= pow(double(radius), 2)) cout << asciiCharacter; else if ((x == 0) && (y == 0)) cout << '+'; else if (x == 0) cout << '|'; else if (y == 0) cout << '-'; else cout << ' '; } cout << endl; } } Notice the use of the conditional operators (? :) when setting the upper and lower values. CHAPTER 6 – Data Structures and Objects 85

  38. // Access and return the Circle's x-coordinate value. // int Circle::getXCoord() const { returnxCoord; } // Access and return the Circle's y-coordinate value. // int Circle::getYCoord() const { returnyCoord; } // Access and return the value of the Circle's radius. // int Circle::getRadius() const { return radius; } // Access and return the value of the Circle's ASCII fill character. // char Circle::getASCIICharacter() const { returnasciiCharacter; } The const modifier may be used to guarantee that the accessor is not allowed to alter the values of any of the data members in the class. CHAPTER 6 – Data Structures and Objects 86

  39. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // The main function serves as a driver to display a variety of // // circles with a variety of sizes, positions, and characters. // ////////////////////////////////////////////////////////////////// void main() { Circle circ; charYorN; int count = 1; intpositionX = 4; intpositionY = 2; cout << "Ready for the first circle? (Enter Y or N) "; cin >> YorN; while ((YorN == 'y') || (YorN == 'Y')) { circ.setASCIICharacter(char(ASCII_ZERO_VALUE + count)); circ.setRadius(count + 3); circ.setCoordinates(positionX,positionY); circ.displayCircleAttributes(); circ.drawCircle(); cout << "Ready for another circle? (Enter Y or N) "; cin >> YorN; count++; positionX = (positionX + 11) % 13; positionY = (positionY + 13) % 11; } return; } CHAPTER 6 – Data Structures and Objects 87

  40. CHAPTER 6 – Data Structures and Objects 88

  41. ENCAPSULATION To better hide the details of a class from the rest of the program, and to facilitate the reuse of the class in other programs, the entire class can be encapsulated into a separate header file. /////////////////////////////////////////////////////////////////////////////////////////////// // This header file contains the full definition of the Quadratic class, including // // constructors (default, initializing, and copy), accessors ("get" member functions for all // // data members), mutators("set" member functions for all data members), and other member // // functions (evaluation, root determination, derivative, and input and output operators). // /////////////////////////////////////////////////////////////////////////////////////////////// #ifndefQUADRATIC_H #include <iostream> #include <fstream> #include <cmath> using namespace std; // The class definition // class Quadratic { public: // Constructors Quadratic(); Quadratic(double quadratic, double linear, double constant); Quadratic(const Quadratic &quad); CHAPTER 6 – Data Structures and Objects 89

  42. // Accessors doublegetQuadratic() const; doublegetLinear() const; doublegetConstant() const; voidgetCoefficients(double &quadratic, double &linear, double &constant) const; // Mutators voidsetQuadratic(double quadratic); voidsetLinear(double linear); voidsetConstant(double constant); voidsetCoefficients(double quadratic, doublelinear, double constant); // Member Functions doubleevaluateAt(double x); boolgetRoots(double &x1, double &x2); Quadratic derivative(); friendostream& operator << (ostream &outputFile, const Quadratic &quad); friendistream& operator >> (istream &inputFile, Quadratic &quad); private: // Data Members doublequadraticCoefficient; doublelinearCoefficient; doubleconstantCoefficient; }; CHAPTER 6 – Data Structures and Objects 90

  43. CONSTRUCTORS // Default Constructor // // Sets all coefficients to zero initially. // Quadratic::Quadratic() { quadraticCoefficient = 0.0; linearCoefficient = 0.0; constantCoefficient = 0.0; return; } // Initializing Constructor // // Sets all coefficients to parameterized values. // Quadratic::Quadratic(double quadratic, double linear, double constant) { quadraticCoefficient = quadratic; linearCoefficient = linear; constantCoefficient = constant; return; } // Copy Constructor // // Sets all coefficients to the same values // // as the parameterized Quadratic. // Quadratic::Quadratic(const Quadratic &quad) { quadraticCoefficient = quad.quadraticCoefficient; linearCoefficient = quad.linearCoefficient; constantCoefficient = quad.constantCoefficient; return; } Classes use constructors to enable programs to create variables of the type defined by the class. The default constructor is called whenever a variable is declared of the type defined by the class. An initializing constructor allows variables to be declared with some of the data member values set. Copy constructors are used when passing variables by value to functions. CHAPTER 6 – Data Structures and Objects 91

  44. ACCESSORS // Quadratic Coefficient Accessor // double Quadratic::getQuadratic() const { returnquadraticCoefficient; } // Linear CorfficientAccessor // double Quadratic::getLinear() const { returnlinearCoefficient; } // Constant Coefficient Accessor // double Quadratic::getConstant() const { returnconstantCoefficient; } // All-Coefficient Accessor // void Quadratic::getCoefficients(double &quadratic, double &linear, double &constant) const { quadratic = quadraticCoefficient; linear = linearCoefficient; constant = constantCoefficient; } Accessor member functions provide programs with the ability to look up the current values of the data members. To ensure that these functions do not actually change the values of any of the data members, they are often defined to be constant functions. CHAPTER 6 – Data Structures and Objects 92

  45. MUTATORS // Quadratic Coefficient Mutator // void Quadratic::setQuadratic(double quadratic) { quadraticCoefficient = quadratic; } // Linear Coefficient Mutator // void Quadratic::setLinear(double linear) { linearCoefficient = linear; } // Constant Coefficient Mutator // void Quadratic::setConstant(double constant) { constantCoefficient = constant; } // All-Coefficient Mutator // voidQuadratic::setCoefficients(doublequadratic, doublelinear, double constant) { quadraticCoefficient = quadratic; linearCoefficient = linear; constantCoefficient = constant; } Mutator member functions provide programs with the ability to alter the current values of the data members. CHAPTER 6 – Data Structures and Objects 93

  46. MEMBER FUNCTIONS // Evaluation Member Function // // Returns the evaluation of the quadratic // // equation at the parameterized x-value. // double Quadratic::evaluateAt(double x) { returnquadraticCoefficient * x * x + linearCoefficient * x + constantCoefficient; } // Root Determination Member Function // // Obtains the roots of the quadratic equation, // // returning a boolean flag that indicates // // whether the root or roots are real. // bool Quadratic::getRoots(double &x1, double &x2) { doublediscriminant; // If the quadratic is actually a constant, set the return flag to false // if ( (quadraticCoefficient == 0) && (linearCoefficient == 0) ) return false; // If the quadratic is actually linear, the root is the solution to the linear equation. // else if (quadraticCoefficient == 0) { x1 = x2 = -constantCoefficient / linearCoefficient; return true; } CHAPTER 6 – Data Structures and Objects 94

  47. // If the quadratic is really a quadratic, use the quadratic // // formula to determine its roots, if they happen to be real values. // else { discriminant = linearCoefficient * linearCoefficient - 4 * quadraticCoefficient * constantCoefficient; if (discriminant < 0) return false; else { x1 = (-linearCoefficient – sqrt(discriminant)) / (2 * quadraticCoefficient); x2 = (-linearCoefficient + sqrt(discriminant)) / (2 * quadraticCoefficient); return true; } } } // Derivative Member Function // // Returns the first derivative of the Quadratic. // Quadratic Quadratic::derivative() { Quadratic derivQuad(0.0, 2 * quadraticCoefficient, linearCoefficient); returnderivQuad; } CHAPTER 6 – Data Structures and Objects 95

  48. OVERLOADED OPERATORS // Overloaded Output Operator // // Outputs the Quadratic in "ax^2 + bx + c" form, unless // // the quadratic coefficient is zero ("bx + c") or both // // the quadratic and linear coefficients are zero ("c"). // ostream& operator << (ostream &outputFile, const Quadratic &quad) { if (quad.quadraticCoefficient != 0.0) outputFile << quad.quadraticCoefficient << "x^2"; if (quad.linearCoefficient != 0.0) { if (quad.quadraticCoefficient == 0.0) outputFile << quad.linearCoefficient << "x"; else if (quad.linearCoefficient < 0.0) outputFile << " - " << -quad.linearCoefficient << "x"; else outputFile << " + " << quad.linearCoefficient << "x"; } if ( (quad.quadraticCoefficient == 0.0) && (quad.linearCoefficient == 0.0) ) outputFile << quad.constantCoefficient; else if (quad.constantCoefficient < 0.0) outputFile << " - " << -quad.constantCoefficient; else if (quad.constantCoefficient > 0.0) outputFile << " + " << quad.constantCoefficient; returnoutputFile; } Operators can be extended to apply to the new class by declaring them as “friends” and giving them access to the private members of the class. CHAPTER 6 – Data Structures and Objects 96

  49. // Overloaded Input Operator // // Inputs the three coefficients // // from the designated input file. // istream& operator >> (istream &inputFile, Quadratic &quad) { inputFile >> quad.quadraticCoefficient >> quad.linearCoefficient >> quad.constantCoefficient; returninputFile; } #define QUADRATIC_H #endif With the class fully defined, it may now be used inside an actual program, as long as the program file includes its header file in its preprocessing statements. CHAPTER 6 – Data Structures and Objects 97

  50. DRIVER PROGRAM ////////////////////////////////////////////////////////// // This driver program requests a Quadratic from the // // user and outputs its roots (if any), its derivative, // // and its minimum or maximum point (if any). // ////////////////////////////////////////////////////////// #include <iostream> #include "Quadratic.h" using namespace std; Quadratic requestQuadratic(); // The main function handles all program activity in the driver, // // except for the user query for the Quadratic's coefficients. // void main() { Quadratic quadro; Quadratic firstDerivative; double root1, root2; double maxmin1, maxmin2; cout << "Initial Quadratic: f(x) = " << quadro << endl << endl; quadro = requestQuadratic(); cout << endl << "Current Quadratic: f(x) = " << quadro << endl << endl; if ( quadro.getRoots(root1, root2) ) cout << " Roots: " << root1 << " and " << root2 << endl << endl; else cout << " No real roots to this quadratic." << endl << endl; CHAPTER 6 – Data Structures and Objects 98

More Related