Chapter 9

Functions

Chapter Objectives

By the end of the chapter, readers will be able to:

images  Understand the concept of a function.

images  Understand the advantages and disadvantages of functions.

images  Develop programmer-defined functions.

images  Pass parameters by value and reference.

images  Return values from a function.

images  Understand the issues regarding variable scope.

images  Distinguish between formal and actual parameters.

images  Call functions and pass arguments.

images  Declare functions with default arguments.

images  Use various character functions.

images  Use and develop structure charts.

Introduction

In Chapter 6, we introduced some of the predefined mathematical functions available in C++. These functions became an important component in developing the more complicated program solutions required in the exercises. It was very convenient to just call the appropriate function with the proper information and get back the result without having to write the code for each of these mathematical functions.

This chapter focuses on developing the skills necessary to write your own functions—probably one of the most important aspects in programming. Very few programs are ever written without the extensive use of functions.

For many of you, the term function may have been introduced in the area of mathematics. For others, the idea of the programming concepts associated with functions may have been presented in terms of methods, subroutines, or even procedures. Regardless of what you call them, you will find functions powerful and extremely helpful in developing your programming skills.

9.1 What Are Functions?

Functions are a group of related statements that together perform a specific task or job. We have already used predefined functions, such as pow, sqrt, and abs. Because our programs required main, we have already written a function definition.

We also know some of the terminology associated with functions.

images  Function header: The start of the function.

images  Function call: The act of invoking the function.

images  Parameters: Variables that provide information to a function.

images  Return: A function sending back a value.

Another aspect of a function is that it allows us to treat its role in our programs as a black box. The concept of a black box implies that we can regard the function as a stand-alone unit. We supply, or pass in, values and it produces, or returns, a specific output to us. For example, a manufacturing plant takes in raw goods—sugar and food coloring—and creates jelly beans. We really don't need to understand the process; we can just enjoy what it produces. Figure 9.1.1 illustrates the black box philosophy.

images

Figure 9.1.1 Black box magic

Although there is a lot more to the concept of functions, the previous discussion should help get us started.

9.1.1 Advantages and Disadvantages of Functions

There are many advantages to using subroutines or functions. The first advantage is that the modularization of functions aids in the process of stepwise refinement. In Chapter 2 we discovered that stepwise refinement is the process of breaking a program into smaller, more manageable, and detailed pieces, each of which can then be designed, implemented, and tested. As you can probably see, partitioning your program into functions facilitates this process.

A second advantage is that by breaking our code into individual components, the program becomes easier both to maintain and for others to understand. Along the same lines, functions enable us to focus our debugging energies in one specific area, resulting in a shorter error-correction time.

Another distinct advantage is that once we have written a function, if we need to use that code again, all we have to do is call it. This code reuse is extremely important. In fact, it is what you did each time you called any of the predefined mathematical functions. The code was already developed and tested by somebody else, and all you had to do was call the function.

In the computer industry—as in many other industries—working in teams is crucial to the success of almost any project. Having multiple programmers concurrently writing key functions and then integrating those functions into a working and cohesive project is essential. Although there are other forms of modularization, which we will discover later in the text, they all build off the concept of functions.

So are there any disadvantages to using functions? Yes. Every time a function is called, there is a slight performance cost involved. When a function is called, the flow of the program is transferred to that function. When the function has completed its task, control returns to where the function was originally called. How does the computer know where to go back to? How does the computer maintain the state of all of the variables when the function was called? All of this information is saved prior to the flow of the program being transferred to the function and then restored when control is returned to the calling function.

Because of this overhead, it is important that you not write functions that are one or two lines long unless that function is going to be used repeatedly. If the function is short and is not going to be called again, the overhead would be detrimental to the performance of your program. While there is some cost associated with using functions, the expense is relatively minor when compared to the benefits they provide in saving the developer time in debugging, maintaining, and extending the code.

9.1.2 What about main?

Every program still needs to have main, but main will now take on a special role as the director. The main function will control the flow of the program but should do very little else. Remember, no matter how many functions are in your program, main will always be the entry point.

Your main function might have a conditional, a loop, and function calls, but that is about it. There should be a minimum of processing going on in main, which simply acts as a driver for the rest of your code. Because of its importance, we suggest you physically place main as the first function within your source code.

Section 9.1 Exercises

Please identify the best responses for each of the following questions:

1.  Which of the following terms is not another name for functions?

a. methods

b. subroutines

c. labels

d. procedures

2.  When you execute a C++ program, what function is executed first?

a. Main

b. main

c. return

d. void

3.  Which of the following is an advantage of using functions?

a. Facilitates code reuse.

b. Often makes debugging your program easier.

c. Aids in the process of stepwise refinement.

d. All of the above are advantages.

9.2 Function Components

There are three components to every function: declaration, definition, and call. So is this different from predefined functions? Nope! It's just that two of the components—the declaration and the definition—are hidden from you. The declaration exists in the header files, and the definition in the C++ library. The third component, the call, is provided by the programmer to invoke the function.

9.2.1 Function Declaration

As previously learned, all variables must be declared before they are used. Functions are no different. The programmer must provide the function declaration so that when the compiler encounters the function call, it can verify the existence of the function name and the required parameters. At this point, all function declarations should be placed above main, making them global. This provides each function within your program the ability to call any other function.

There are three parts to every function declaration, as shown in the following syntax diagram:

<return-type> <function-name> ( <parameter-list> );

The <return-type> specifies the data type of any value returned from the function. As you might suspect from this statement, a function is able to return a maximum of one value. The data type of the value returned and the return type of the function must match. If the function does not return a value, the return type of the function must be specified as void.

The <function-name> represents a valid identifier name. The name must adhere to the same naming rules for variables, as was discussed in Chapter 4. Although not a rule, some programmers feel that the function name should begin with a strong verb to signify what task the function will perform.

The <parameter-list> represents a comma-delimited list of the variables that will be passed to the function. If there are to be no parameters passed to the function, it is acceptable to place the void keyword in the parentheses or to leave the parentheses empty. Example 9.2.1 shows several function declarations.

images

Although all of the examples in Example 9.2.1 are legal, the last example is not as readable as it could be. It is acceptable in the parameter list to have only the data types of the parameters; however, if the names of the parameters are specified, it would give a more meaningful clue as to what the parameters are used for.

Within this text we make it a point to include the names of all the parameters when declaring functions because of the improved readability of the code. We would strongly urge you to follow a similar style.

9.2.2 Function Definition

The function definition is just what it sounds like; it defines what the function does. In your previous programs, all you did was define main. There are actually two parts to the function definition. The function definition starts with the function header. The function header will look exactly like the declaration except that it doesn't have a semicolon. Also, the names of all the parameters in the function header are required.

The other part of the function definition is the function body, which must be enclosed in curly braces. Just like the body of a loop, the body of a function defines what the function will do when it is invoked. Once the function has done its job, the flow of the program returns to where the function was invoked. A complete function definition is shown in Example 9.2.2.

images

One big difference from other statements we have seen is that the function definition must be placed outside of any other function. It is syntactically incorrect to define a function within another function.

STYLE NOTE Because of the declarations, it is legal to place your function definitions above or below main. We suggest that you physically place main as the first function definition in your source code file, since main is always the first function to execute.

Another term used by some programmers is signature. The signature refers to the function declaration or prototype minus the return type. A teammate might refer to FunctionA as having a different signature than FunctionB. This means that the two functions have different parameters as well as a different function name. We will have more to say about function signatures when we get into the subject of classes later in the text, but a signature basically includes the function name, and the type and number of parameters it takes.

Finally, as previously discussed, we strongly suggest that you take the time to carefully align the { } and indent the function body. You will find that it greatly improves both the readability and the maintainability of your code.

9.2.3 Function Call

The last piece of the function puzzle is the function call. The function call tells the function that it is time to do its job. The control of the program is transferred to the function definition, and the body of the function is executed. Although we have already said this, it is crucial for you to understand that when the function has finished its job, the flow or control of the program goes back to where it was called.

Before moving on, we need to make one additional comment about the call and return statements. If you return a value from a function, you must immediately assign that return value to a variable or in some other way use it in an expression. If you don't use or store the value that is returned, it will indeed be lost. Example 9.2.3 shows several function calls, including functions that return a value.

images

Notice that all of the function calls in Example 9.2.3 don't have data types associated with the parameters. It would be syntactically incorrect to do so. In the first statement in Example 9.2.3, we simply call the PrintInstructions function. No values are passed into the function, and nothing is returned.

In the second example, the value returned from the FindMaximum function is immediately printed. When the function was called, two values, or arguments, were passed. When the function exits, it returns a value back to the point where it was called, thus allowing the ability to display the value in the cout statement.

In Example 3, we assigned the value returned from the FindMaximum function to another variable. Remember, the return type must match, or be automatically converted to, the type of the variable used in the assignment.

Notice in the final example, however, that the called function would have again returned a value as required because of the function's signature. Unfortunately, this time we did not use the value once it was returned to us, so the value is lost forever. Rarely will we ignore a return value from a user-defined function. Doing so is one of the more common errors made by our beginning students.

Section 9.2 Exercises

Please identify the best response for each of the following questions:

1.  When used with functions, the term void means:

a. Nothing is returned from a function or passed to a function.

b. Anything can be passed to the function or returned from a function.

c. The function does not use cout within its body or action.

d. The function returns an integer value.

Please use the following prototype for the next three questions:

int CantTouchThis( double time, char code );

2.  Which of the following statements is the correct way to call the preceding function?

images

3.  What is the data type returned from the preceding function?

images

4.  How many parameters are passed into the preceding function?

none

one

two

three

Section 9.2 Learn by Doing Exercise

1.  Write a program that has a function, in addition to main, that displays your name. This function will return no values and will be passed no parameters.

9.3 Return

In all of the predefined mathematical functions we have used, when the function finished its calculations, it gave a value back so that it could be stored in a variable. In other words, the function returned a value. As we saw in both the function header and the declaration, a return type other than void specifies that the function will return a value.

So how does the function return a value? Well, you have been returning a value from a function from the very first program you wrote. In main, the last statement in all of our examples has been return 0;. This statement returns the numeric literal 0 to where main was called. Since main is called by the operating system, this is where the value is returned. Typically, a return value of 0 from main indicates normal termination of your program. A value other than 0 indicates that an error has occurred. Also notice that the return type of main is an int, which matches the data type of the value returned.

When a return statement is encountered, the execution of the function immediately stops and control returns to the point of the call. Any value specified in the return statement is returned at that point. If there are additional statements after the return statement, they will not be executed, as shown in Example 9.3.1. Take note, though: No errors or warnings will be generated from the compilation of this code.

images

Although it is legal to have multiple return statements in a function, such as in the action of an if statement, it is important to remember that all paths through the function must have a return statement. Executing Example 9.3.2 would generate the following warning: not all control paths return a value.

images

Even though multiple return statements are acceptable, you are still returning only one value per function execution. This is worth repeating: A function can return only one value.

There are a couple of issues concerning return statements you should avoid. While it is legal to have a return statement in the body of a loop, it is considered poor programming. The only way a loop should terminate is through its condition. Also, you can use a return statement without actually returning a value to immediately end the function. Both of these tactics are unacceptable in the courses we teach. There are better, more elegant, alternatives. Example 9.3.3 illustrates a function containing a simple loop construct and the proper approach to return a value.

images

Remember, it is not necessary to return a value from a function. Without a return statement, the function will end. The flow will then transfer back to where it was called from when the last statement in the body of the function has executed. You must remember that the signature of this type of function will have void as its return type.

STYLE NOTE Some programmers feel there should be only one entry point and one exit point in any function. It is our personal programming style to avoid multiple returns in a function.

Section 9.3 Exercises

1.  For each of the following code fragments, indicate if there are any errors. If there is an error, identify what type of error it is (syntactical, logical, runtime) and how you would fix it. If you are unsure or would like to see the proof, type it into your compiler and run it.

images

2.  Indicate whether each of the following statements is true or false:

a. A function can return more than one value.

b. It is legal for a function to contain more than one return statement.

c. Every function must contain a return statement.

d. The function main should return an int.

Section 9.3 Learn by Doing Exercise

1.  Write a program that has a function that prompts for three values. The function will then return the average of those values to main. The returned value will then be displayed to the screen.

9.4 Passing Parameters

All of the mathematical functions we learned in Chapter 6 required us to provide a value, or values, to the function. This is called passing a value or parameter. The calling function provides information for the called function to work with. The value to be sent to the function is placed within the function call's parentheses.

Example 9.4.1 shows how we pass the required two double values to the pow function. The first value passed into the pow function will be the contents of var_x, and the second value passed will be the contents of var_y. Note also how we assign the value returned from the pow function to var_z.

images

For every value in the call, there must be a corresponding value in the function header and declaration. The first parameter from the call is caught in the first parameter in the header. The second parameter in the call is caught in the second parameter, and so on. The data types of the parameters must all match. Notice that it is the order of the parameters that determines where the values go, not the name of the individual parameters. For example, you could call a function named foo and pass it the values a, b, and c. However, in the function header, you could catch those three ordered values as x, y, and z, respectively. While we don't usually alter the names to that extent, it is important that you know that it is indeed legal to do.

Example 9.4.2 calls the function CalculateBoxVolume from main and passes it three values: the contents of the variable length, the contents of the variable width, and the value 2, which represents the height.

images

What a function can do with the parameter depends on how the parameter is passed. Although there are several different modes in which we can pass parameters, this chapter focuses on passing by value and passing by reference.

9.4.1 Formal and Actual Parameters

Before discussing the modes of passing values, we need to present some terminology. The terms formal and actual parameters refer to the parameters in the function header and those in the call. Formal parameters are found in the function definition, and actual parameters appear in the function call. This terminology becomes very important when we start to encounter compilation errors that deal with functions. If you don't have matching data types for all the pieces of your functions, you will receive a compilation error or warning.

9.4.2 Scope

We have already discussed the concept of scope. Variables declared within curly braces are available only within that code block. Variables declared within functions—called local variables—are no different. Because the variables can only be seen within the scope of the function, you can use the same variable names within different functions without any problem.

Another thing to be aware of is that all formal parameters are treated as local variables. Therefore, all variables associated with the function, including all formal parameters, are destroyed when that function is finished.

images

Figure 9.4.1 Passing by value

9.4.3 Passing by Value

In passing by value, a copy of the value is made and passed to the function. The function, therefore, manipulates the copy and not the original. When the called function is done, the function's actual parameter—the variable in the call—retains its original value. Again, it is important to remember that a copy of the value is made. The diagram in Figure 9.4.1 demonstrates this process.

Notice in Figure 9.4.1 that the variables age and days are declared within the body of main. At that point, each variable is created in a specific location in memory. For our illustration, we assume the value of age is at address 1000 and the variable days is physically located at address 1004. When the function CalcDays is called, we pass it the contents, or value, of the variable age, in this case 20. In order to use this value and make it available within the CalcDays function itself, we catch the contents of the variable age declared in main and store the value in a new variable, again called age.

As you can see, this age variable has its own physical location at address 2000. When the function exits, any local variables, in this case age and days, will be destroyed. The bottom line is that these variables are physically stored in two distinct locations, each having only function scope. If you make a change to one of these formal parameters in the called function, it will not impact the values of the actual parameters in the calling function.

To further illustrate the syntax of passing by value, Example 9.4.3 contains several additional function declarations that have parameters passed in this manner.

images

9.4.4 Passing by Reference

Instead of passing a copy of the value, passing by reference passes an alias that directly references the variable. This means that any changes made to the formal parameter are reflected in the actual parameter when the function is done. To pass by reference, you must place an ampersand after the formal parameter's data type. Figure 9.4.2 shows the impact of passing by reference on variables.

images

Figure 9.4.2 Passing by reference

Notice in Figure 9.4.2, the age in CalcDays doesn't really contain a value but refers to the actual parameter in main. Therefore, any changes to the reference in CalcDays are reflected in main. Example 9.4.4 shows function declarations that indicate that its parameters are passed by reference.

images

In the first example, two variables are passed by reference. Changes made within this function to either of these two variables will be reflected in the calling function.

In the second example, variables a and b are both passed by value while average is passed into the function by reference. The EnterData function receives two values, both by reference.

Passing by reference should only be used if the original value needs to be changed. Use passing by value for all other occasions.

One final point needs to be made in relation to passing by value or reference: Regardless of how you decide to pass the arguments into the function, the call statement remains the same.

Section 9.4 Exercises

Please identify the best response for each of the following questions:

1.  In the following function, how many parameters will be passed into the function?

void SumThem( int a, int b, int c );

a. one

b. two

c. three

d. four

e. five

2.  In passing by ______________, a copy of the value is made and passed to the function.

a. void

b. const

c. reference

d. value

e. alias

3.  In passing by ____________, you pass an alias or reference to a variable instead of the value.

a. void

b. const

c. reference

d. value

e. r-value

4.  For each of the following code fragments, indicate if there are any errors. If there is an error, identify what type of error it is (syntactical, logical, runtime) and how you would fix it. If you are unsure or would like to see the proof, type it into your compiler and run it.

images

Section 9.4 Learn by Doing Exercise

1.  Write a program that asks for an employee's salary and years of service. Use the following functions to manipulate the information as described, as well as the included function signatures.

void GetInput( float & salary, int & years_service );

This function prompts for and reads the required salary and years of service.

void CalcRaise( float & salary, int years_service );

This function changes the salary depending on the years of service. If the employee has greater than 10 years of service, he or she will receive a 10% raise. Between 5 and 10 years, the raise is 5%. Everybody else will receive a 2% raise.

int CalcBonus( int years_service );

This function calculates and returns the employee's bonus for the year. An employee will receive $500 for every 2 years of service.

void PrintCalculations( int years_service, float salary, int bonus );

This function will display in a clear and professional manner all of the calculated information.

9.5 Default Arguments

Another powerful feature used with functions is called default arguments. A default argument is simply a value the programmer provides in the function declaration that will automatically be inserted if no value is provided in the function call.

There are two types of arguments or parameters: mandatory and default. Obviously, it is a requirement that all mandatory arguments be specified in the function call. As a result, all mandatory arguments must come before any default arguments in the parameter list.

Default arguments, however, are optionally specified. When omitting arguments in your call statement, you must omit the arguments from the right end of the parameter list. This would require you to have already specified the necessary default values in the function declaration.

When setting default arguments in your function declarations, remember that the defaults must be provided starting with the right-most variable(s) in your parameter list. The default values can continue from right to left, but once you stop providing specific default values, you cannot start providing them again.

The final thing to note when using default arguments is that you can only put the default values in the function declaration or prototype; you cannot include them in the function header.

Fortunately for you, all of this sounds much more confusing than it really is. Example 9.5.1 will quickly show you how easy default arguments are to use.

images

Section 9.5 Exercises

1.  In the following function prototype, how many default arguments exist?

void SumThem( int a, int b = 3, int c = 5 );

a.  one

b.  two

c.  three

d.  four

e.  five

2.  Using the following prototype, please indicate which of the call statements would be valid. If the statement is invalid, please state why.

images

3.  For each of the following, specify whether the function declaration is valid. If it is not valid, please indicate why.

images

Section 9.5 Learn by Doing Exercise

1.  Write a program that uses a function to read three values representing hours, minutes, and seconds. Pass these three values to another function that will display the time in an appropriate style. A fourth optional argument to the display function specifies whether to display the time in 24-hour notation, military time, or standard format. Both of these functions are to be called from main. Be sure to call the display function using three arguments as well as four arguments.

9.6 Putting It All Together

Now that all the fundamental aspects associated with functions have been covered, it will be extremely beneficial to review a more complete and comprehensive program. Example 9.6.1 incorporates many of the topics discussed in this chapter. Please take some time to carefully review the code listing and the output it generated. Make sure you fully understand each line of code, focusing especially on the sections associated with passing by value and passing by reference. To check your understanding of functions and the passing of parameters, try to determine the output of the program. Use the output provided with the example to validate your results.

After you have walked through the code in the text, we would strongly urge you to copy the code from the book's website and use the debugger to step into the various functions and watch the contents of the variables as the program executes.

images

images

Figure 9.7.1 Call stack window

9.7 Debugging—Call Stack

As they have become relevant, we have tried to introduce new debugging tools and techniques. Now that you are becoming more familiar with functions, it is important to be introduced to the Call Stack window. The Call Stack allows us to view where in the hierarchy of our function calls the current line of execution is located.

By default, the Call Stack window in Visual Studio is not displayed. To show this window, click on the Debug menu while debugging. The top menu option is the Windows option, which has a submenu containing the item Call Stack. This can also be accessed from the hot key Ctrl+Alt+C. Figure 9.7.1 shows the Call Stack window from the execution of Example 9.6.1.

Notice that the Call Stack window shows the name of the program with the currently executing function at the top. Also shown is the data type of each parameter as well as the value. You can also see from the window that Fun3 was called from Fun2, which was called from main. Typically, this is as far as we need to look at the contents of the window. As you can see, though, there are other functions that called main. These functions are responsible for displaying the console window as well as loading the program into memory.

9.8 More Predefined Functions

In Chapter 6 we discussed some of the predefined mathematical functions. Now that you are more familiar with functions, let's explore some additional ones. All of the functions in this section manipulate individual characters.

9.8.1 Character Case

There are two functions that allow us to change the case of a single character. Since you know about function signatures and declarations, it will be good practice to learn about these functions, starting with the following declarations:

images

As you can see, these functions are passed an integer by value and return an integer. But wait! We just said these were character functions—and besides, how can you change the case of a number? Don't forget about ASCII values. You can pass a character and catch it as an integer because this would be a widening conversion, no type casting is needed.

In order to use these two functions, you will need to include the header file <cctype>. Example 9.8.1 demonstrates the use of these functions.

images

Table 9.8.1 Some “is” functions

Function Description
isalnum Is the character alphanumeric? (A-Z, a-z, 0-9)
isalpha Is the character a letter? (A-Z, a-z)
iscntrl Is the character a control character? (ASCII values 0-31 and 127)
isdigit Is the character a digit? (0-9)
ispunct Is the character punctuation?
isspace Is the character whitespace? (ASCII values 9-13 and 32)

Because the toupper function returns the character stored in the variable again converted to uppercase, we only need to check the uppercase version of the character ‘Y’. If the actual parameter contains an uppercase letter or a character that is not a letter, no conversion will be performed. Therefore, the original character is returned. The tolower function is used in exactly the same manner.

Notice that a using statement was not used in Example 9.8.1. This is because the functions in this section are not contained within a namespace.

9.8.2 The “is” Functions

There is a group of functions that help us test characters to determine what classification the character fits into. For example, we can use one of these functions, ispunct, to determine if the character is punctuation. All of these functions have the following syntax:

int <is-function> ( int c );

Several of these functions are shown in Table 9.8.1. Just like toupper and tolower, to use the “is” functions, the <cctype> header file is required.

All of the functions in Table 9.8.1 return a nonzero value if the character meets the criteria and zero if the character fails to meet the criteria. Just like toupper and tolower, these functions are also C functions. Remember, C doesn't have a Boolean data type; therefore, 0 is always treated as false and nonzero as true. Example 9.8.2 shows a specific example of how to use these functions; however, the same technique can be applied to all of the “is” functions.

images

The second example in Example 9.8.2 demonstrates a shorthand version using the logical NOT operator, which is commonly encountered. Both methods are equally effective.

Section 9.8 Exercises

1.  The functions toupper, tolower, isalpha, and isdigit all work on:

a. a number

b. a character

c. any data type

d. void data types

2.  Which of the following functions would test the value in a specific variable to determine if it is either a number or a letter?

images

3.  What is the name of the header file you must include when using functions like toupper, tolower, isspace, or isdigit?

images

9.9 Structure Charts

Recall that in Chapter 2 the concept of a flowchart was introduced as a graphical approach for representing an algorithm. Another tool used to help us better visualize the organization of our solution or program is called a structure chart. Like a flowchart, a structure chart uses symbols and connectors, as we have previously seen. However, while a flowchart helps us outline the specific details associated with a solution, a structure chart takes a much higher-level approach, graphically showing the various tasks or functions needed as well as the relationship of these tasks to each other.

Structure charts work well in the area of procedural programming to represent functions and their relationships to each other. We have chosen to use them within the text as simply another tool to help in designing and visualizing programming solutions. Figure 9.9.1 illustrates the use of a structure chart to represent the organization of the program provided in Example 9.6.1.

images

Figure 9.9.1 Structure chart

Notice that the structure chart resembles a hierarchy chart and that it is organized from top to bottom and from left to right. In the structure chart shown in Figure 9.9.1, the functions PrintOutput, Fun1, and Fun2 are all called from main. Likewise, PrintOutput and Fun3 were called from Fun2. Fun3 also calls PrintOutput. We have chosen the symbol with the folded corner to represent a common function that is called from more than one place.

We suggest you draw your structure chart first, either by hand or by using tools such as Microsoft's Visio, Word, or PowerPoint. Notice that the only text appearing within the individual boxes is the exact name of your functions. Once you have given some thought to the overall organization of your program and drawn the structure chart, you can easily focus on the individual functions that you have identified. You can now break these individual functions into more detailed tasks or statements by writing the specific pseudocode for each respective function.

9.10 Problem Solving Applied

We will now begin to incorporate this new technique into our program development to help organize the required functions, demonstrating the use of the structure chart as an aid in developing our solution.

Since this section uses the previous chapter's Problem Solving Applied solution, please refer to Section 8.6 for problem specifications.

images

Figure 9.10.1 Structure chart

Now that the structure chart shown in Figure 9.10.1 has been created, use this diagram to help develop the pseudocode, as shown in the Design phase.

Design:

images

Like always, this pseudocode is now translated into C++ source code. Notice that we have added function descriptions in our pseudocode, which will be placed in the C++ source code as comments. These comments serve as documentation not only for you but for other programmers who may be involved in the modification or maintenance of your code.

C++ Source Code

images

images

9.11 C—The Differences

There are only a few differences between C++ and C in relation to the material presented in this chapter. A couple of these differences are minor, while one is major. One of the minor differences is that in C, there is a distinction between a function that specifies a void parameter list and one that has an empty parameter. A void parameter list specifies that no parameters will be passed to the function; an empty parameter list means that there are an indeterminate number of parameters. Example 9.11.1 illustrates both of these options.

images

The major difference is that passing by reference in C is done in an entirely different way. C accomplishes the same functionality as passing by reference by using something called passing by pointer. Because you can also pass by pointer in C++, we have devoted almost an entire chapter to passing by pointer and pointers in general. Please see Chapter 12 for more on passing by pointer.

Finally, it is important to note that using default arguments in the C programming language is not allowed.

9.12 SUMMARY

In this chapter, we explored the powerful concept and components associated with functions. Functions are simply a group of related statements that are assembled together to carry out a specific task. The numerous advantages that functions offer to programmers—including the ability to break a problem down into smaller, more manageable, and maintainable components—were also discussed. Code reuse is another huge advantage in using functions.

We followed up with a discussion of the three main components required in every function: the declaration, the definition, and the call. To help reinforce your understanding of these various components, we related programmer-defined functions to your existing background with predefined math functions, presented earlier in the text.

One of the additional strengths of functions is that they can both receive values and send results back to the place from which they were called. We explored two methods for sending data or values into a function: passing by value and passing by reference. In relation to passing by value, it was noted that the called function receives only a copy of the variable's contents. Since it has only a copy of the data, any changes made to the copy will have no impact on the actual parameter located in the function call. In discussing passing by reference, we noted how formal parameters that use the ampersand allow changing the contents of the original or actual parameter, making the modifications permanent.

We also discussed the value and functionality of the return statement, noting that when a return statement is executed, control immediately returns to the point of the call. We also stressed that a return can send only one value back to the calling function.

We also revisited the previously introduced topic of scope. Within this chapter, we expanded this concept to include local variables, and mentioned that all formal function parameters are indeed treated as local variables. As a result, upon exiting the function, all of the local variables are destroyed.

Finally, we provided a complete example to help reinforce the various concepts presented. Hopefully you are feeling very comfortable with functions and their overall usage. As you will soon see, they will act as a fundamental cornerstone to the programs developed in the remainder of the text.

9.13 Debugging Exercise

Download the following file from this book's website and run the program following the instructions noted in the code.

images

images

images

9.14 Programming Exercises

The following programming exercises are to be developed using all phases of the development method. Be sure to make use of good programming practices and style, such as constants, whitespace, indentation, naming conventions, and commenting. Make sure all input prompts are clear and descriptive and that your output is well formatted and looks professional. Although some of these exercises are from previous chapters, rewrite them so they now include appropriate function modularization.

1.  Write a program that draws a rectangle on the screen using ASCII characters. The program will prompt the user for the height and width, specified in characters, of the rectangle. Use the following ASCII values for the box characters: 218 upper left-hand corner, 217 lower right-hand corner, 196 top and bottom, 192 lower left-hand corner, 191 upper right-hand corner, and 179 left and right sides.

2.  Write a program that takes input from the user that represents a numerator and a denominator of a fraction. Then reduce the fraction to its lowest terms and display it to the screen. If appropriate, display the fraction as a mixed number (3 1/2).

To reduce a fraction to its lowest terms, divide both the numerator and the denominator by the greatest common divisor (GCD). The GCD can be calculated by using Euclid's algorithm. Euclid's algorithm states: Let m represent the numerator and n represent the denominator of a fraction. Divide m by n. Save the divisor in m and save the remainder in n. If n is 0, then stop: m contains the GCD. Otherwise, repeat the process.

Be sure to display the fraction in a well-formed manner. If the denominator is a one, display the fraction as a whole number. If the denominator is a zero, display a message that the fraction is undefined. A fraction will never be displayed with a negative denominator.

3.  Display a menu to the user that has the following options:

—Main Menu—

1. Calculate Area

2. Calculate Volume

Write a switch statement that handles the user's choice. For each of the main menu options, display a submenu that has the following options:

—Area Menu—

—Volume Menu—

a. Rectangle a. Cylinder
b. Circle b. Sphere
c. Right Triangle  

Write nested switch statements to handle each of the submenus. For all of the switch statements, use the default case to handle any incorrect menu options. If you are unsure of the correct formulas, research them on the Internet or in your math books. Display the results of each of the calculations based on the appropriate user input.

4.  The “is” functions toupper and tolower are all C functions. Rewrite these functions so that they are more C++ like. Use Boolean return types and use the char data type for parameters instead of int. Make sure you write a program that tests the functionality of these new functions.

9.15 Team Programming Exercise

As you have probably noticed, your source code for Marcus from Chapters 7 and 8 is getting more than a little messy. Break the solution you previously created into the following functions:

•  Name: GetData

•  Parameters: none

•  Return: The integer number entered by the user

•  Purpose: This function will allow the user to enter the number to be tested. Marcus would like you to limit the input from negative one million to positive one million. If the number entered is out of bounds, display an error message and have the user reenter the value

•  Name: DisplayMenu

•  Parameters: The variable that holds the menu choice, passing by reference

•  Return: none

•  Purpose: This function displays the menu to the user

•  Name: ProcessMenuChoice

•  Parameters: The variable that holds the menu choice, passing by value
The variable that holds the number entered, passing by reference

•  Return: none

•  Purpose: This function will call the appropriate function based on the menu choice that is passed in

•  Name: IsPosNeg

•  Parameters: The variable that holds the number entered, passing by value

•  Return: none

•  Purpose: This function tests the number that is passed to determine whether it is positive, negative, or zero. The function displays an appropriate message based on the results of the test

•  Name: IsOddEven

•  Parameters: The variable that holds the number entered, passing by value

•  Return: none

•  Purpose: This function tests the number that is passed to determine whether it is odd, even, or zero. The function displays an appropriate message based on the results of the test

•  Name: FindNumDigits

•  Parameters: The variable that holds the number entered, passing by value

•  Return: The number of digits

•  Purpose: This function determines the number of digits in the number that is passed in

•  Name: FindDigitAtPosition

•  Parameters: The variable that holds the number entered, passing by value
The variable that contains the digit's position, passing by value

•  Return: The digit at the specified position

•  Purpose: This function determines what digit is at a specific position in the number

•  Name: DisplayAdditionTable

•  Parameters: none

•  Return: none

•  Purpose: This function displays the addition table

•  Name: DisplayMultiplicationTable

•  Parameters: none

•  Return: none

•  Purpose: This function displays the multiplication table

Both the FindNumDigits and FindDigitAtPosition functions return a value, which is then displayed in the ProcessMenuChoice function.

Marcus has supplied you with a structure chart shown in Figure 9.15.1 that he thinks will help develop your program. Although it seems that all of the functions are accounted for, use a drawing program like Microsoft Visio to clean this up. Make sure all of the boxes are the same style and size and that it is indeed an appropriate structure chart.

images

Figure 9.15.1 Team programming structure chart

9.16 Answers to Chapter Exercises

Section 9.1

1.  c.  labels

2.  b.  main

3.  d.  All of the above are advantages.

Section 9.2

1.  a.  Nothing is returned from a function or passed to a function.

2.  c.  int hammer = CantTouchThis( 11.4, ‘A’ );

3.  b.  int

4.  c.  two

Section 9.3

1.  a.  Syntactical—no data type in a return statement.

b.  Syntactical—can't declare a variable using a reserved word.

c.  Valid.

d.  Syntactical—can only return one value.

e.  Valid.

f.  Valid, although not a very good approach.

g.  Valid.

h.  Syntactical—can only return one value.

2.  a.  False—only one value can be returned from a function.

b.  True—but we suggest you have only one return in your function.

c.  False—a function will automatically exit when it is at its end.

d.  True—main should always return an integer value.

Section 9.4

1.  c.  three

2.  d.  value

3.  c.  reference

4.  a.  Syntactical—the ampersand must come before the variable name.

void PartA(int var_a, int &var_b);

b.  Syntactical—need the data type for the second parameter.

int PartB(int x, int y, double z);

c.  Syntactical—need the data type for each of the parameters.

char LetterGrade(int & var_a, int &var_b, int var_c);

Section 9.5

1.  b.  two

2.  a.  Valid.

b.  Invalid—the first argument passed to the function must be a variable, not a numeric literal. You cannot pass a literal by reference.

c.  Invalid—the call requires at least one argument.

d.  Invalid—only one or two arguments can be passed to the function.

e.  Invalid—data types don't match.

3.  a.  Invalid—default arguments must be continuously supplied from right to left.

b.  Invalid—default arguments must be supplied starting at the right-most position.

c.  Invalid—you cannot initialize a reference to a literal.

d.  Valid.

Section 9.8

1.  b.  a character

2.  d.  isalnum

3.  c.  <cctype>

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.200.3