• No results found

A R OUNDING F UNCTION

In document C++ Basics (Page 106-116)

Programmer-Defined Functions

A R OUNDING F UNCTION

The table of predefined functions (Display 3.2) does not include any function for rounding a number. The functions ceil and floor are almost, but not quite, rounding functions. The func-tion ceil always returns the next-highest whole number (or its argument if it happens to be a whole number). So, ceil(2.1) returns 3.0, not 2.0. The function floor always returns the nearest whole number less than (or equal to) the argument. So, floor(2.9) returns 2.0, not

108 Function Basics

3.0. Fortunately, it is easy to define a function that does true rounding. The function is defined in Display 3.6. The function round rounds its argument to the nearest integer. For example, round(2.3) returns 2, and round(2.6) returns 3.

To see that round works correctly, let’s look at some examples. Consider round(2.4). The value returned is the following (converted to an int value):

floor(2.4 + 0.5)

which is floor(2.9), or 2.0. In fact, for any number that is greater than or equal to 2.0 and strictly less than 2.5, that number plus 0.5 will be less than 3.0, and so floor applied to that number plus 0.5 will return 2.0. Thus, round applied to any number that is greater than or equal to 2.0 and strictly less than 2.5 will return 2. (Since the function declaration for round specifies that the type for the value returned is int, we have type cast the computed value to the type int.)

Now consider numbers greater than or equal to 2.5; for example, 2.6. The value returned by the call round(2.6) is the following (converted to an int value):

floor(2.6 + 0.5)

which is floor(3.1), or 3.0. In fact, for any number that is greater than 2.5 and less than or equal to 3.0, that number plus 0.5 will be greater than 3.0. Thus, round called with any num-ber that is greater than 2.5 and less than or equal to 3.0 will return 3.

Thus, round works correctly for all arguments between 2.0 and 3.0. Clearly, there is nothing special about arguments between 2.0 and 3.0. A similar argument applies to all nonnegative numbers. So, round works correctly for all nonnegative arguments.

round

Display 3.6 The Function round (part 1 of 2) 1 #include <iostream>

2 #include <cmath>

3 using namespace std;

4 int round(double number);

5 //Assumes number >= 0.

6 //Returns number rounded to the nearest integer.

7 int main( ) 8 {

9 double doubleValue;

10 char ans;

11 do 12 {

13 cout << "Enter a double value: ";

14 cin >> doubleValue;

Testing program for the function round

Self-Test Exercises

7. What is the output produced by the following program?

#include <iostream>

using namespace std;

char mystery(int firstParameter, int secondParameter);

int main( ) {

cout << mystery(10, 9) << "ow\n";

return 0;

}

char mystery(int firstParameter, int secondParameter) {

if (firstParameter >= secondParameter) return ’W’;

else

return ’H’;

}

Display 3.6 The Function round (part 2 of 2)

15 cout << "Rounded that number is " << round(doubleValue) << endl;

16 cout << "Again? (y/n): ";

17 cin >> ans;

18 }while (ans == ’y’ || ans == ’Y’);

19 cout << "End of testing.\n";

20 return 0;

21 }

22 //Uses cmath:

23 int round(double number) 24 {

25 return static_cast<int>(floor(number + 0.5));

26 }

SAMPLE DIALOGUE

Enter a double value: 9.6 Rounded, that number is 10 Again? (y/n): y

Enter a double value: 2.49 Rounded, that number is 2 Again? (y/n): n

End of testing.

110 Function Basics

Self-Test Exercises

8. Write a function declaration (function prototype) and a function definition for a function that takes three arguments, all of type int, and that returns the sum of its three arguments.

9. Write a function declaration and a function definition for a function that takes one argu-ment of type double. The function returns the character value ’P’ if its argument is posi-tive and returns ’N’ if its argument is zero or negative.

10. Can a function definition appear inside the body of another function definition?

11. List the similarities and differences between how you invoke (call) a predefined (that is, library) function and a user-defined function.

FUNCTIONS THAT RETURN A BOOLEAN VALUE

The returned type for a function can be the type bool. A call to such a function returns one of the values true or false and can be used anywhere that a Boolean expression is allowed. For example, it can be used in a Boolean expression to control an if-else

statement or to control a loop statement. This can often make a program easier to read.

By means of a function declaration, you can associate a complex Boolean expression with a meaningful name. For example, the statement

if (((rate >= 10) && (rate < 20)) || (rate == 0)) {

...

}

can be made to read

if (appropriate(rate)) {

...

}

provided that the following function has been defined:

bool appropriate(int rate) {

return (((rate >= 10) && (rate < 20)) || (rate == 0));

}

12. Write a function definition for a function called inOrder that takes three arguments of type int. The function returns true if the three arguments are in ascending order; other-wise, it returns false. For example, inOrder(1, 2, 3) and inOrder(1, 2, 2) both return true, whereas inOrder(1, 3, 2) returns false.

13. Write a function definition for a function called even that takes one argument of type int and returns a bool value. The function returns true if its one argument is an even num-ber; otherwise, it returns false.

14. Write a function definition for a function isDigit that takes one argument of type char and returns a bool value. The function returns true if the argument is a decimal digit; oth-erwise, it returns false.

DEFINING void FUNCTIONS

In C++ a void function is defined in a way similar to that of functions that return a value. For example, the following is a void function that outputs the result of a calcula-tion that converts a temperature expressed in degrees Fahrenheit to a temperature expressed in degrees Celsius. The actual calculation would be done elsewhere in the program. This void function implements only the subtask for outputting the results of the calculation.

void showResults(double fDegrees, double cDegrees) {

cout.setf(ios::fixed);

cout.setf(ios::showpoint);

cout.precision(1);

cout << fDegrees

<< " degrees Fahrenheit is equivalent to\n"

<< cDegrees << " degrees Celsius.\n";

}

As the above function definition illustrates, there are only two differences between a function definition for a void function and for a function that returns a value. One difference is that we use the keyword void where we would normally specify the type of the value to be returned. This tells the compiler that this function will not return any value. The name void is used as a way of saying “no value is returned by this func-tion.” The second difference is that a void function definition does not require a

return statement. The function execution ends when the last statement in the func-tion body is executed.

A void function call is an executable statement. For example, the above function

showResults might be called as follows:

showResults(32.5, 0.3);

If the above statement were executed in a program, it would cause the following to appear on the screen:

32.5 degrees Fahrenheit is equivalent to 0.3 degrees Celsius.

void function definition

void function call

112 Function Basics

Notice that the function call ends with a semicolon, which tells the compiler that the function call is an executable statement.

When a void function is called, the arguments are substituted for the formal param-eters, and the statements in the function body are executed. For example, a call to the

void function showResults, which we gave earlier in this section, will cause some out-put to be written to the screen. One way to think of a call to a void function is to imag-ine that the body of the function definition is copied into the program in place of the function call. When the function is called, the arguments are substituted for the formal parameters, and then it is just as if the body of the function were lines in the program.

(Chapter 4 describes the process of substituting arguments for formal parameters in detail. Until then, we will use only simple examples that should be clear enough with-out a formal description of the substitution process.)

It is perfectly legal, and sometimes useful, to have a function with no arguments. In that case there simply are no formal parameters listed in the function declaration and no arguments are used when the function is called. For example, the void function

initializeScreen, defined below, simply sends a newline command to the screen:

void initializeScreen( ) {

cout << endl;

}

If your program includes the following call to this function as its first executable state-ment, then the output from the previously run program will be separated from the out-put for your program:

initializeScreen( );

Be sure to notice that even when there are no parameters to a function, you still must include the parentheses in the function declaration and in a call to the function.

Placement of the function declaration (function prototype) and the function defini-tion is the same for void functions as what we described for functions that return a value.

return STATEMENTS IN void FUNCTIONS

Both void functions and functions that return a value can have return statements. In the case of a function that returns a value, the return statement specifies the value returned. In the case of a void function, the return statement does not include any expression for a value returned. A return statement in a void function simply ends the function call. Every function that returns a value must end by executing a return state-ment. However, a void function need not contain a return statement. If it does not contain a return statement, it will end after executing the code in the function body. It is as if there were an implicit return statement just before the final closing brace, }, at the end of the function body.

functions with

The fact that there is an implicit return statement before the final closing brace in a function body does not mean that you never need a return statement in a void func-tion. For example, the function definition in Display 3.7 might be used as part of a res-taurant-management program. That function outputs instructions for dividing a given amount of ice cream among the people at a table. If there are no people at the table (that is, if number equals 0), then the return statement within the if statement termi-nates the function call and avoids a division by zero. If number is not 0, then the func-tion call ends when the last cout statement is executed at the end of the function body.

PRECONDITIONS AND POSTCONDITIONS

One good way to write a function declaration comment is to break it down into two kinds of information called the precondition and the postcondition. The precondition states what is assumed to be true when the function is called. The function should not be used and cannot be expected to perform correctly unless the precondition holds. The postcondition describes the effect of the function call; that is, the postcondition tells what will be true after the function is executed in a situation in which the precondition holds. For a function that returns a value, the postcondition will describe the value FUNCTION DECLARATION (FUNCTION PROTOTYPE)

A function declaration (function prototype) tells you all you need to know to write a call to the function. A function declaration (or the full function definition) must appear in your code prior to a call to the function. Function declarations are normally placed before the main part of your program.

SYNTAX

Type_Returned_Or_void FunctionName(Parameter_List);

where the Parameter_List is a comma-separated list of parameters:

Type_1 Formal_Parameter_1, Type_2 Formal_Parameter_2,...

..., Type_Last Formal_Parameter_Last

EXAMPLES

double totalWeight(int number, double weightOfOne);

//Returns the total weight of number items that //each weigh weightOfOne.

void showResults(double fDegrees, double cDegrees);

//Displays a message saying fDegrees Fahrenheit //is equivalent to cDegrees Celsius.

Do not forget this semicolon.

precondition

post-condition

114 Function Basics

Display 3.7 Use of return in a void Function 1 #include <iostream>

2 using namespace std;

3 void iceCreamDivision(int number, double totalWeight);

4 //Outputs instructions for dividing totalWeight ounces of ice cream among 5 //number customers. If number is 0, only an error message is output.

6 int main( ) 7 {

8 int number;

9 double totalWeight;

10 cout << "Enter the number of customers: ";

11 cin >> number;

12 cout << "Enter weight of ice cream to divide (in ounces): ";

13 cin >> totalWeight;

14 iceCreamDivision(number, totalWeight);

15 return 0;

16 }

17 void iceCreamDivision(int number, double totalWeight) 18 {

19 double portion;

20 if (number == 0) 21 {

22 cout << "Cannot divide among zero customers.\n";

23 return;

24 }

25 portion = totalWeight/number;

26 cout << "Each one receives "

27 << portion << " ounces of ice cream." << endl;

28 }

SAMPLE DIALOGUE

Enter the number of customers: 0

Enter weight of ice cream to divide (in ounces): 12 Cannot divide among zero customers.

If number is 0, then the function execution ends here.

returned by the function. For a function that changes the value of some argument vari-ables, the postcondition will describe all the changes made to the values of the arguments.

For example, the following is a function declaration with precondition and post-condition:

void showInterest(double balance, double rate);

//Precondition: balance is a nonnegative savings account balance.

//rate is the interest rate expressed as a percentage, such as 5 for 5%.

//Postcondition: The amount of interest on the given balance //at the given rate is shown on the screen.

You do not need to know the definition of the function showInterest in order to use this function. All that you need to know in order to use this function is given by the precondition and postcondition.

When the only postcondition is a description of the value returned, programmers usually omit the word Postcondition, as in the following example:

double celsius(double fahrenheit);

//Precondition: fahrenheit is a temperature in degrees Fahrenheit.

//Returns the equivalent temperature expressed in degrees Celsius.

Some programmers choose not to use the words precondition and postcondition in their function comments. However, whether you use the words or not, you should always think in terms of precondition and postcondition when designing a function and when deciding what to include in the function comment.

main IS A FUNCTION

As we already noted, the main part of a program is actually the definition of a function called main. When the program is run, the function main is automatically called; it, in turn, may call other functions. Although it may seem that the return statement in the

main part of a program should be optional, practically speaking it is not. The C++ stan-dard says that you can omit the return 0 statement in the main part of the program, but many compilers still require it and almost all compilers allow you to include it. For the sake of portability, you should include return 0 statement in the main function.

You should consider the main part of a program to be a function that returns a value of type int and thus requires a return statement. Treating the main part of your program as a function that returns an integer may sound strange, but that’s the tradition which many compilers enforce.

Although some compilers may allow you to get away with it, you should not include a call to main in your code. Only the system should call main, which it does when you run your program.

116 Function Basics

Self-Test Exercises

RECURSIVE FUNCTIONS

C++ does allow you to define recursive functions. Recursive functions are covered in Chapter 13. If you do not know what recursive functions are, there is no need to be concerned until you reach that chapter. If you want to read about recursive functions early, you can read Sections 13.1 and 13.2 of Chapter 13 after you complete Chapter 4.

Note that the main function should not be called recursively.

15. What is the output of the following program?

#include <iostream>

using namespace std;

void friendly( );

void shy(int audienceCount);

int main( ) {

friendly( );

shy(6);

cout << "One more time:\n";

shy(2);

friendly( );

cout << "End of program.\n";

return 0;

}

void friendly( ) {

cout << "Hello\n";

}

void shy(int audienceCount) {

if (audienceCount < 5) return;

cout << "Goodbye\n";

}

16. Suppose you omitted the return statement in the function definition for iceCreamDivi-sion in Display 3.7. What effect would it have on the program? Would the program com-pile? Would it run? Would the program behave any differently?

17. Write a definition for a void function that has three arguments of type int and that out-puts to the screen the product of these three arguments. Put the definition in a complete program that reads in three numbers and then calls this function.

18. Does your compiler allow void main( ) and int main( )? What warnings are issued if you have int main( ) and do not supply a return 0; statement? To find out, write sev-eral small test programs and perhaps ask your instructor or a local guru.

19. Give a precondition and a postcondition for the predefined function sqrt, which returns the square root of its argument.

In document C++ Basics (Page 106-116)