Laboratory 6
Programmer-Defined Functions
Introduction
Often, a program will require that some fundamental task be performed, perhaps repeatedly. Some familiar examples of such tasks are swapping, sorting, and determining the largest (or smallest) of two integers. In this lab, we will learn how to define such tasks as “subprograms”, or, as C++ calls them, functions. Once a function is defined, a program can simply invoke it each time it wants the particular task performed. Thus, we may avoid writing the same code multiple times throughout the program. In this lab, we experiment with defining, and then utilizing, some very useful functions.
Key Concepts
Function definition
Formal parameters
Actual parameters
Function invocation
Text processing revisited
Before the Lab
Read Sections 6.1 – 6.4 in Cohoon and Davidson.
Preliminary
- Turn the PC on, if necessary.
- Access the network.
- Copy the source files from the Lab 06 Source Files folder.
- Start up CodeWarrior.
- Open the LabWork project.
Writing a Simple Function
Observation
The program max.cpp contains a user-defined function max(), which returns the larger of two floats. This is essentially the function described in the textbook on page 275.
- Add max.cpp to the LabWork project.
- Read the source code.
- Note the max() function written just below the main() function. Be sure you understand how the max() function works.
- Note the prototype of the max() function written just before the main() function. The prototype is necessary so that the main() function will know the proper usage of max().
- Note the usage (invocation) of the max() function in main() in the line
float larger = max(x, y);
- Run the program a couple of times, once letting the first number be larger and once letting the second number be larger.
Experimentation
What would happen if we pass max() two ints instead of two floats? Would it still work? In the file max.cpp,
- Change the lines
float x, y;
floatlarger = max(x, y);
to
int x, y;
intlarger = max(x, y);
- Run max.cpp again. Does it still work? Why?
Can you anticipate any possible problems resulting from passing ints to max()?
- Run max.cpp one more time. This time enter the integers 123456789 and 987654321. Is the output correct? Why?
- Change the two lines above back to what they were.
The process of finding the smaller of two numbers is nearly identical with that of finding the larger. Therefore, a simple modification of the max() function will produce the min() function.
- Save a copy of max.cpp as min.cpp.
- Modify the function max() so that it returns the smaller of two floats. Rename the function min() and rename any variables appropriately.
- Run the program min.cpp.
Now we will use the max() function to find the largest number in a list of numbers.
- Add listMax.cpp to the LabWork project.
The program listMax.cpp will read a list of numbers entered by the user. This list is terminated with CTRL-D. Then the program will print the largest number in the list.
- Look at the code in main() to see how the max() function is used to find the largest in a list of numbers.
Note that the first value in the list is used to initialize the variable maxSoFar; the remaining values are used to updatemaxSoFar as necessary.
- Run the program. Does it appear to work?
Functions Calling Functions
Experimentation
What if we want to write a function that will find the largest of three numbers? How can we write a max() function to do that? We will do it by creating a new function maxOfThree() that calls (or invokes) max().
- Add the file max.cpp back into the LabWork project.
- Save a copy of max.cpp as maxOfThree.cpp.
- Write a second function named maxOfThree() that will find the largest of three floats. Do not remove the max() function.
The functionmaxOfThree() should have the prototype
floatmaxOfThree(float a, float b, float c);
It should use max() in the following way. First use max()to find the larger of a and b. Then use max() again to find the larger of that number and c. This is the value to be returned by maxOfThree().
- Change main() to read three floats instead of two and to find the largest of those three floats.
- Run the program to see if it works.
Using Functions to Organize a Program
Observation
We will run a newer version of the vowelCount program from Lab 5. This version makes use of functions, some of them are in the standard libraries and some of them are user-defined. The three user-defined functions are
boolisVowel(char c);
which returns true if c is a vowel,
boolisConsonant(char c);
which returns true if c is a consonant, and
boolisBlank(char c);
which returns true if c is a blank space.
- Add vowelCount2.cpp to the LabWork project.
- Read the code in main() to see how the functions are used to count the different kinds of characters.
- Read the code in the isVowel() function to see how it works. It uses a switch statement to make the decision.
- Read the code in the isConsonant() function . Note that it calls on isalpha() from the cctype library and also calls on isVowel(). Note that it negates the bool returned by isVowel() by using the “not” operator !.
- Read the code in the isBlank() function . Note that it returns the Boolean value of a comparison.
- Run vowelCount2.cpp. It reads the characters from the file woodChuck.txt. Is the output correct?
Experimentation
- Add the file wordSearch.cpp to the LabWork project.
- Open wordSearch.cpp and save a copy as wordSearch2.cpp.
Recall that this program was used in Lab 5. Its purpose is to search a text file for all occurrences of a given word and to report the number of occurrences found. One defect of the program was that it failed to take into account the possibility of upper- and lowercase letters. We solved that problem in Lab 5, but our solution was not the best. Recall that we added a for loop in two different places. The two loops were virtually identical. They differed only in the string to which they were applied. This is exactly the kind of situation that functions were designed to handle. Therefore, we will define a function toUpper() that will work for any given string, not just for chars, and then invoke it for the strings wordSearch and word. (Remember, the toupper() function in the cctype library applies only to chars.)
- Write a function toUpper() with prototype
string toUpper(string str);
that will convert each letter of str to uppercase and return the resulting string. (The object str itself should remain unchanged.)
- Incorporate the use of this function toUpper() into the comparison of word and searchWord so that only the uppercase versions are compared.
The idea is essentially to invoke the toUpper() function in the places where we inserted the for loop in Lab 5.
- Run the program to see that it works.
- Notice that this version of wordSearch2.cpp is much “cleaner” than the earlier version was.
Application
Open the MS Word document Lab 06 App.doc, found in the Lab 06 App subfolder, and follow the instructions.
Summary
We have seen the usefulness of being able to define a function and then simply call upon it in a program whenever a value, such as max(a,b), is required or a task needs to be performed. This style of programming, called modular design, has some very important advantages. First, it allows the programmer to break up a problem into several smaller, and therefore more manageable, subproblems. Second, it enforces what computer scientists call procedural abstraction. That is, it keeps the code itself organized and eliminates the need for repeating the code for the task each time the task is required.
The C++ programming language encourages its users to program in this way, with tasks delegated to different functions, and with the functions often residing in different source files. Thus, if one needs to make a change in the program, only the affected source file is recompiled. Soon, we will learn how to create our own classes, while hiding the implementation details from the client programmer. The term for this approach, also encouraged by C++, is data abstraction.
1