1 / 52

Problem Solving with C++ The Object of Programming

Problem Solving with C++ The Object of Programming. Chapter 4 Functions for All Subtasks. 4 Functions for All Subtasks. We stated the principle of top-down-design, where you repeatedly divide the program’s task into smaller, more manageable subtasks.

mandy
Télécharger la présentation

Problem Solving with C++ The Object of Programming

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. Problem Solving with C++ The Object of Programming Chapter 4 Functions for All Subtasks

  2. 4 Functions for All Subtasks • We stated the principle of top-down-design, where you repeatedly divide the program’s task into smaller, more manageable subtasks. • In Chapter 3 we saw how to write functions that return one value. • Here we show how to design functions that perform other kinds of subtasks.

  3. 4.1 void-Functions • A subtask may produce one or many values • We will see that such functions ordinarily return no values at all. We will present a mechanism for multiple values to be sent back to the caller. • Such a function is called a void-Function. The essential point is demonstrated here: void Print( double value) { using namespace std; cout << value << endl; } 3

  4. Definition of void-Functions • A C++ void function is defined similarly to functions that return a value. The next slide has an example. • There are two differences between value returning functions and void-functions. • void type replaces the more familiar return type such as int or double. • There is no “return expression; “ statement, though a return; with no expression is allowed. • A call to a void function is an executable statement, rather than being part of an expression. 4

  5. // Example of void function void show_results(double f_degrees, double c_degrees) { using namespace std; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(1); cout << f_degrees << “ degrees Fahrenheit is equavalent to\n” << c_degrees << “ degrees Celsius\n”; } 5

  6. Syntax for a void-Function Definition void-Function Prototype void Function_Name(Parameter_List); void-Function Definition void Function_Name(Parameter_List) Function header { Declaration_1; You may intermix declarations Declaration_2; and executable statements. . . . Declaration_Last; Executable_1; Executables may or may not Executable_2; include one or more return; . . . statements. Executable_Last; } 6

  7. return-Statements in void-Functions • In C++ both void functions and value-returning functions can have return statements. • In value-returning functions the return must have an argument. In void-functions, the return must NOT have an argument. • There is an implicit (compiler generated) return statement at the final closing brace of a void function. This does not mean you neverneed a return; in a void-function. 7

  8. ex1 (1 of 4) //Program to convert a Fahrenheit temperature to a Celsius temperature. #include <iostream> void initialize_screen( ); //Separates current output from the output //of the previously run program. double celsius(double fahrenheit); //Converts a Fahrenheit temperature to a Celsius temperature. void show_results(double f_degrees, double c_degrees); //Displays output. Assumes that c_degrees //Celsius is equivalent to f_degrees Fahrenheit. int main( ) { using namespace std; double f_temperature, c_temperature; initialize_screen( ); 8

  9. ex1 (2 of 4) cout << "I will convert a Fahrenheit temperature" << " to Celsius.\n" << "Enter a temperature in Fahrenheit: "; cin >> f_temperature; c_temperature = celsius(f_temperature); show_results(f_temperature, c_temperature); return 0; } 9

  10. ex1 (3 of 4) //Definition uses iostream: void initialize_screen( ) { using namespace std; cout << endl; return; The return is optional. } double celsius(double fahrenheit) { return ((5.0/9.0)*(fahrenheit - 32)); } 10

  11. ex1 (4 of 4) //Definition uses iostream: void show_results(double f_degrees, double c_degrees) { using namespace std; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(1); cout << f_degrees << " degrees Fahrenheit is equivalent to\n" << c_degrees << " degrees Celsius.\n"; return; The return is optional. } 11

  12. 4.2 Call-by-Reference ParametersA first view of Call-by-reference • The call-by-value mechanism we have used until now is not adequate to certain tasks. • Input subtasks should be carried out with a function call. This is not adequate for more than one return value. We need another mechanism. • With a Call-by-Value parameter, the corresponding argument is only read for its value. The argument can be variable, but this is not necessary. The parameter is initialized with the value of the value-parameter. • With Call-by-Reference, the corresponding argument must be variable, and the behavior of the function is as if the variable were substituted for the parameter. 12

  13. A first view of Call-by-reference • To make a parameter a call-by-reference, parameter, an ampersand ( & ) is placed between the type name and the variable name in the function header and in any prototypes that are to declare this function in other places. a call-by-reference parameter Example: void GetInput( double & f_variable) { using namespace std; cout << “Enter a Fahrenheit, I will return Celsius\n”; cin >> f_variable;} 13

  14. ex2 Call by Reference parameters (1 of 4) //Program to convert a Fahrenheit temperature to a Celsius temperature. #include <iostream> void initialize_screen( ); //Separates current output from the output //of the previously run program. double celsius(double fahrenheit); //Converts a Fahrenheit temperature to a Celsius temperature. void show_results(double f_degrees, double c_degrees); //Displays output. Assumes that c_degrees //Celsius is equivalent to f_degrees Fahrenheit. void GetInput( double & f_variable); // Inputs a value and assigns it to f_variable 14

  15. ex2 Call by Reference parameters (2 of 4) int main( ) { using namespace std; double f_temperature, c_temperature; initialize_screen( ); GetInput(f_temperature); c_temperature = celsius(f_temperature); show_results(f_temperature, c_temperature); return 0; } //Definition uses iostream: void initialize_screen( ) { using namespace std; cout << endl; return; } 15

  16. ex2 Call by Reference parameters (3 of 4) double celsius(double fahrenheit) { return ((5.0/9.0)*(fahrenheit - 32)); } //Definition uses iostream: void show_results(double f_degrees, double c_degrees) { using namespace std; cout.setf(ios::fixed); cout.setf(ios::showpoint); cout.precision(1); cout << f_degrees << " degrees Fahrenheit is equivalent to\n" << c_degrees << " degrees Celsius.\n"; return; } 16

  17. ex2 Call by Reference parameters (4 of 4) void GetInput( double & f_variable) { using namespace std; cout << "Enter a Fahrenheit, I will return Celsius\n"; cin >> f_variable; } 17

  18. ex3 Call by Reference parameters (1 of 2) //Program to demonstrate call-by-reference parameters. #include <iostream> void get_numbers(int& input1, int& input2); //Reads two integers from the keyboard. void swap_values(int& variable1, int& variable2); //Interchanges the values of variable1 and variable2. void show_results(int output1, int output2); //Shows the values of variable1 and variable2, in that order. int main( ) { int first_num, second_num; get_numbers(first_num, second_num); swap_values(first_num, second_num); show_results(first_num, second_num); return 0; } 18

  19. ex3 Call by Reference parameters (2 of 2) //Uses iostream: void get_numbers(int& input1, int& input2) { using namespace std; cout << "Enter two integers: "; cin >> input1 >> input2; } void swap_values(int& variable1, int& variable2) { int temp; temp = variable1; variable1 = variable2; variable2 = temp; } //Uses iostream: void show_results(int output1, int output2) { using namespace std; cout << "In reverse order the numbers are: " << output1 << " " << output2 << endl; } 19

  20. Call-by-Reference in Detail • The remark that a call-by-reference parameter has the argument variable copied into the parameter was a “gloss”. • Gloss: noun. An explanation that is not quite right, but is close, and above all, is believable. Used to teach concepts when the pure truth would get in the way. • The whole truth is - it is the address of the argument is used in place of the parameter, and the address is used to fetch values from the argument as well as to write to the argument. 20

  21. Parameters and Arguments (1 of 2) If you keep these points in mind, you can handle all the parameter passing language. 1. The formal parameters for a function are listed in the function prototype and function definition header. A formal parameter is a place holder that is filled at the time the function is called. 2. Arguments appear in a comma separated list in the call to the function, and are used to fill in the corresponding formal parameters. When the function is called, the arguments are ‘plugged in’ for the formal parameters. 3. The terms call-by-value and call-by-reference refer to the mechanism that is used in the “plugging in” process. 21

  22. Parameters and Arguments (2 of 2) In the call-by-value method, the arguments are read, and the parameters are initialized using a copy of the value of the argument. In the call-by-reference method, the argument must be a variable. The behavior is exactly as if the argument were substituted for the parameter. Then if the code assigns the parameter, it is the argument that is changed. The mechanism is to pass the address of the argument and then the parameter mechanism knows where the argument is so when the parameter is written, the argument is where the writing is done. 22

  23. Mixed Parameter Lists It is entirely feasible to have value parameters (call-by-value parameter) mixed in with reference parameters (call-by-reference parameters). (We tend to use short cuts in the language.) Example: void good_stuff(int& par1, int par2, double & par3); Call: good_stuff( arg1, 17, arg3); Here 17 is permissible because par2 is a value parameter. This code may (but by no means must) change arg1 and arg3. 23

  24. PITFALL: Inadvertent Local Variables Omitting an ampersand (&) when you intend a reference parameter is a mistake that bites twice. First it makes you code run incorrectly, the compiler probably won’t catch it, and it is very difficult to find because it looks right. See ex4 (following) 24

  25. ex4 Inadvertent local variables //Inadvertent local variables. Shows what happens when you omit & //Program to demonstrate call-by-reference parameters. #include <iostream> void get_numbers(int& input1, int& input2); //Reads two integers from the keyboard. Forgot the & here void swap_values(int variable1, int variable2); //Interchanges the values of variable1 and variable2. void show_results(int output1, int output2); //Shows the values of variable1 and variable2, in that order. int main( ) { using namespace std; int first_num, second_num; get_numbers(first_num, second_num); swap_values(first_num, second_num); show_results(first_num, second_num); return 0; } 25

  26. ex4 Inadvertent local variables (2 of 2) void swap_values(int variable1, int variable2) { int temp; temp = variable1; Forgot the & here, which variable1 = variable2; Makes these inadvertent local variables variable2 = temp; } //Uses iostream: void get_numbers(int& input1, int& input2) { using namespace std; cout << "Enter two integers: "; cin >> input1 >> input2; } //Uses iostream: void show_results(int output1, int output2) { using namespace std; cout << "In reverse order the numbers are: " << output1 << " " << output2 << endl; } 26

  27. 4.3 Using Procedural AbstractionFunctions calling functions • A function may call another function. • The situation is exactly the same as if the first call had been in the main function. • ex5 (next) swaps the values of two variables if the values are out of order.

  28. ex5 Function Calling Another Function (1 of 3) //Program to demonstrate a function calling another function. #include <iostream> void get_input(int& input1, int& input2); //Reads two integers from the keyboard. void swap_values(int& variable1, int& variable2); //Interchanges the values of variable1 and variable2. void order(int& n1, int& n2); //Orders the numbers in the variables n1 and n2 //so that after the function call n1 <= n2. void give_results(int output1, int output2); //Outputs the values in output1 and output2. //Assumes that output1 <= output2 int main( ) { int first_num, second_num; get_input(first_num, second_num); order(first_num, second_num); give_results(first_num, second_num); return 0; } 28

  29. ex5 Function Calling Another Function (2 of 3) //Uses iostream: void get_input(int& input1, int& input2) { using namespace std; cout << "Enter two integers: "; cin >> input1 >> input2; } void swap_values(int& variable1, int& variable2) { int temp; temp = variable1; variable1 = variable2; variable2 = temp; } 29

  30. ex5 Function Calling Another Function (3 of 3) void order(int& n1, int& n2) { if (n1 > n2) swap_values(n1, n2); } //Uses iostream: void give_results(int output1, int output2) { using namespace std; cout << "In increasing order the numbers are: " << output1 << " " << output2 << endl; } 30

  31. Preconditions and Postconditions • The Prototype comment should be broken into a precondition and a postcondition. • The precondition is what is required to be true when the function is called. • The postcondition describes the effect of calling the function, including any returned value and any effect on reference parameters.

  32. Preconditions and Postconditions Example Pre - and Post-conditions. // square root function, sqrt // Prototype: double sqrt( double arg); // Pre: arg >= 0; // Post: returned value squared == arg If the Precondition is satisfied the function promises to put the Postcondition true. If the precondition is not satisfied, the function’s behavior is not constrained in any way.

  33. Case Study Let’s consider the following problem (it’s Programming Project 1 from the text): Write a program that converts from twenty-four hour notation to twelve-hour notation. For example, it should convert 14:25 to 2:45 PM. The input is given as two integers. There should be at least three functions, one for input, one to do the conversion, and one for output. Record the AM/PM information as a value of type char, ‘A’ for AM and ‘P’ for PM. Thus the function for doing the conversions will have a call-by-reference formal parameter of type char to record whether it is AM or PM. (The function will have other parameters as well.) Include a loop that lets the user repeat this computation for new input values again and again until the user says he or she wants to end the program.

  34. ex6 (1 of 5) // Converts from 24 hour time to 12 hour time #include <iostream> void introduction(); //Postcondition: Description of program printed on screen void getInput(int& hours, int& minutes); //Precondition: User is ready to enter values correctly //Postcondition: The value of hours has been set to the number of //hours in the 24 hour time. This value is between 0 and 23, //inclusive.The value of minutes has been set to the number of //minutes in the 24 hour time. This value is between 0 and 59, //inclusive. void convertTo12HourTime( int hours24, int& hours12, char& AMPM); //Precondition: hours24 represent a legal 24 hour time (0-23). //Postcondition: The value of hours12 has been set to the legal //12 hour time (1-12). AMPM stores 'A' for AM times, 'P' for PM times. void giveOutput( int hours, int minutes, char AMPM); //Precondition: hours, minutes represent a legal 12 hour time. //AMPM stores 'A' for AM times, 'P' for PM times. //Postcondition: the 12 hour time is printed to the screen. 34

  35. ex6 (2 of 5) int main( ) { using namespace std; char tryAgain, myAMPM; int my24Hours, myMinutes, my12Hours; introduction(); do { getInput(my24Hours, myMinutes); convertTo12HourTime(my24Hours, my12Hours, myAMPM); giveOutput(my12Hours, myMinutes, myAMPM); cout << "Do you want to do it again?\n"; cin >> tryAgain; } while (tryAgain == 'Y' || tryAgain == 'y'); return 0; } // uses iostream void introduction() { using namespace std; cout << "This program lets a user input a 24 hour time\n" << "and it outputs the equivalent 12 hour time\n\n"; } 35

  36. ex6 (3 of 5) // uses iostream void getInput(int& hours, int& minutes) { using namespace std; cout << "Enter the hours and the minutes for a legal " << "24 hour time: "; cin >> hours >> minutes; while (hours < 0 || hours > 23) { cout << "The hours must between 0 and 23, inclusive: "; cin >> hours; } while (minutes < 0 || minutes > 59) { cout << "The minutes must between 0 and 59, inclusive: "; cin >> minutes; } } 36

  37. ex6 (4 of 5) void convertTo12HourTime( int hours24, int& hours12, char& AMPM) { if (hours24 == 0) { hours12 = 12; AMPM = 'A'; return; } if (hours24 == 12) { hours12 = 12; AMPM = 'P'; return; } if (hours24 < 12) { hours12 = hours24; AMPM = 'A'; return; } if (hours24 > 12) { hours12 = hours24 - 12; AMPM = 'P'; return; } } 37

  38. ex6 (5 of 5) void giveOutput( int hours, int minutes, char AMPM) { using namespace std; cout << hours << ":"; if (minutes < 10) cout << "0"; cout << minutes; if (AMPM == 'A') cout << "AM\n"; else cout << "PM\n"; } 38

  39. 4.4 Testing and Debugging FunctionsStubs and Drivers • Every function should be designed coded and tested as a separate unit from the rest of the program. • Every function should be tested in a program in which every other function in that program has already been completely tested and debugged. • This is catch 22. You need a framework to develop and test, but the framework must be debugged as well.

  40. Stubs and Drivers • Every function should be designed coded and tested as a separate unit from the rest of the program. • This is the essence of the top-down design strategy. • How do you test a function? By writing a simple, short program called a driver that calls the function. The driver should be simple enough that we can confirm its correctness by inspection.

  41. Stubs and Drivers • How do you test a program that needs a function, before you have written the function? • By writing a simple, short program called a stub that provides the the program with the same prototype, and provides enough data to the caller so the caller can be tested. The stub should be simple enough that we can confirm its correctness by inspection.

  42. Stubs and Drivers • How do you test a program using stubs when the program needs several functions? • Here we write stubs for all the functions, then write the real functions, putting them into the program one at a time. This way the complete program and already written code continues to be tested, while the new functions are written and tested until the final program is produced.

  43. ex7.cpp Driver Program (1 of 3) //Driver program for the function convertTo12HourTime #include <iostream> void convertTo12HourTime( int hours24, int& hours12, char& AMPM); //Precondition: hours24 represent a legal 24 hour time (0-23). //Postcondition: The value of hours12 has been set to the legal //12 hour time (1-12). AMPM stores 'A' for AM times, 'P' for PM times. int main( ) { using namespace std; char AMPM; int oldhour, newhour; char ans; 43

  44. ex7.cpp Driver Program (2 of 3) do { cout << "Enter a number between 0 and 23: "; cin >> oldhour; convertTo12HourTime(oldhour, newhour, AMPM); cout << "12 hour 'hour' is " << newhour << endl; cout << "AM or PM is " << AMPM << endl; cout << "Test again?" << " (Type y for yes or n for no): "; cin >> ans; cout << endl; } while (ans == 'y' || ans == 'Y'); return 0; } 44

  45. void convertTo12HourTime( int hours24, int& hours12, char& AMPM) { if (hours24 == 0) { hours12 = 12; AMPM = 'A'; return; } if (hours24 == 12) { hours12 = 12; AMPM = 'P'; return; } if (hours24 < 12) { hours12 = hours24; AMPM = 'A'; return; } if (hours24 > 12) { hours12 = hours24 - 12; AMPM = 'P'; return; } } 45

  46. Fundmental Rule for Testing Functions • Every function should be tested in a program in which every other function in that program has already been completely tested and debugged.

  47. ex8.cpp Program that uses a Stub (part 1 of 4) // Converts from 24 hour time to 12 hour time #include <iostream> void introduction(); //Postcondition: Description of program printed on screen void getInput(int& hours, int& minutes); //Precondition: User is ready to enter values correctly //Postcondition: The value of hours has been set to the number of //hours in the 24 hour time. This value is between 0 and 23, //inclusive.The value of minutes has been set to the number of //minutes in the 24 hour time. This value is between 0 and 59, //inclusive. void convertTo12HourTime( int hours24, int& hours12, char& AMPM); //Precondition: hours24 represent a legal 24 hour time (0-23). //Postcondition: The value of hours12 has been set to the legal //12 hour time (1-12). AMPM stores 'A' for AM times, 'P' for PM times. void giveOutput( int hours, int minutes, char AMPM); //Precondition: hours, minutes represent a legal 12 hour time. //AMPM stores 'A' for AM times, 'P' for PM times. //Postcondition: the 12 hour time is printed to the screen. 47

  48. ex8.cpp Program that uses a Stub (part 2 of 4) int main( ) { using namespace std; char tryAgain, myAMPM; int my24Hours, myMinutes, my12Hours; introduction(); do { getInput(my24Hours, myMinutes); convertTo12HourTime(my24Hours, my12Hours, myAMPM); giveOutput(my12Hours, myMinutes, myAMPM); cout << "Do you want to do it again?\n"; cin >> tryAgain; } while (tryAgain == 'Y' || tryAgain == 'y'); return 0; } // uses iostream void introduction() { using namespace std; cout << "This program lets a user input a 24 hour time\n" << "and it outputs the equivalent 12 hour time\n\n"; } 48

  49. ex8.cpp Program that uses a Stub (part 3 of 4) // uses iostream void getInput(int& hours, int& minutes) { using namespace std; cout << "Enter the hours and the minutes for a legal " << "24 hour time: "; cin >> hours >> minutes; while (hours < 0 || hours > 23) { cout << "The hours must between 0 and 23, inclusive: "; cin >> hours; } while (minutes < 0 || minutes > 59) { cout << "The minutes must between 0 and 59, inclusive: "; cin >> minutes; } } 49

  50. ex8.cpp Program that uses a Stub (part 4 of 4) // This is only a stub void convertTo12HourTime( int hours24, int& hours12, char& AMPM) { hours12 = 12; AMPM = 'A'; // It's always midnight! } void giveOutput( int hours, int minutes, char AMPM) { using namespace std; cout << hours << ":"; if (minutes < 10) cout << "0"; cout << minutes; if (AMPM == 'A') cout << "AM\n"; else cout << "PM\n"; } 50

More Related