Using a Function

Now that we have seen how to write the Average function, let's see how to use it to solve our original problem. The program in Figure 5.5 uses our Average function twice, once to average two weights and once to average two ages.

Figure 5.5. Using the Average function (codefunc1.cpp)
#include <iostream>
using namespace std;

short Average(short First, short Second)
{
  short Result;

  Result = (First + Second) / 2;

  return Result;
}

int main()
{
  short FirstWeight;
  short SecondWeight;
  short FirstAge;
  short SecondAge;
  short AverageWeight;
  short AverageAge;

  cout << "Please type in the first weight: ";
  cin >> FirstWeight;

  cout << "Please type in the second weight: ";
  cin >> SecondWeight;

  AverageWeight = Average(FirstWeight, SecondWeight);

  cout << "Please type in the first age: ";
  cin >> FirstAge;

  cout << "Please type in the second age: ";
  cin >> SecondAge;

  AverageAge = Average(FirstAge, SecondAge);

  cout << "The average weight was: " << AverageWeight << endl;
  cout << "The average age was: " << AverageAge << endl;

  return 0;
}

As always, calling a function requires specifying its name and its argument(s) and doing something with the return value, if any. In this case, we call Average with the arguments FirstWeight and SecondWeight, and store the result in AverageWeight. This is accomplished via the line AverageWeight = Average(FirstWeight, SecondWeight);. Later, we call Average with the arguments FirstAge and SecondAge, and store the result in AverageAge. We do this via the line AverageAge = Average(FirstAge, SecondAge);.

The value of writing a function to average two numbers wasn't obvious to Susan at first. After some discussion, however, she agreed that it was valuable. Here's the conversation that convinced her:

Susan: In general, I just don't understand why you even need to call the Average function in the first place; it looks like extra steps to me. It seems to me that all you need are your two input values, which end up just giving you the results right there for weight and age. I think that this is what bothers me the most. For example, when you get done with the set of weights, you should just have your results right then and there instead of calling the function of Average.

Steve: But what is the result you want? You want the average of the weights. Where is that calculated?

Susan: After you are done with that, then you already have written a set of ages so you can just use the result of that. It just seems like you are going in circles unnecessarily with this program. That is why I don't understand it.

Steve: Again, just because you have a set of ages doesn't mean that you have the average age; some code somewhere has to calculate that average.

Susan still had a lot of trouble with visualizing the way this function worked. However, running it in the debugger got her moving again, resulting in the following discussion:

Susan: Why does everything start out initialized to 0 except Result, which appears to hold an address in memory?

Steve: The values of uninitialized variables are not reliable. In this case, I'm getting a similar value of Result to the one you're getting; however, you cannot count on this. There's also no reason to think that the contents of Result are a memory address; they're just garbage until the variable is initialized.

Susan: Steve, I don't understand this; first you tell me that those numbers are garbage but represent addresses in memory and now you tell me that they are just garbage, but that they are not reliable. I don't understand, if they are uninitialized, how they ever could be reliable. This implies that at some time you could get an expected value even if they are uninitialized. They should always be garbage. So, when do those numbers represent memory addresses and when not?

Steve: Apparently I've confused you unnecessarily again. Here are the facts:

1. A variable always represents an address in memory.

2. However, the contents of an uninitialized variable are garbage.

3. Since they are garbage, they represent nothing.

4. Since they are garbage, they can have any value, which may or may not appear to have meaning. Regardless of appearances, the value of an uninitialized variable is meaningless.

Then our discussion returned to the topic of how the main program works:

Susan: Oh, OK, so AverageWeight = Average(FirstWeight, SecondWeight); is the part that starts the Average function running?

Steve: Right.

Susan: Then after averaging the weights, why does Result go to 0? It looks to me that Result has no value at these points and I don't understand why.

Steve: Because you're looking at the next call to Average, where its variable Result is uninitialized again. By default, variables are uninitialized whenever they are created, which occurs each time the function where they "live" is entered. The "old" Result from the first call to Average “died” when the first call to Average was finished, and the new Result that is created on the second call is uninitialized until we set it to some known value.

The next topic we discussed was how to create a new program and get it to run.

Susan: Now when you start out a new program; are all the new implementation files named with a .cpp extension?

Steve: Yes.

Susan: So this code in Average is where the real averaging takes place, right? Is this the "Average command"? I thought Average meant to average, so what is the deal?

Steve: The deal is that something has to do the averaging; rather than writing the same code every time we need to average another set of two numbers, we put that code in one place (the Average function) and call it whenever we need its assistance.

Susan: OK, then this brings up another one of my questions. How come you write the Average function before the main function?

Steve: So that the main function knows how to call the Average function. There's another way to allow a function to call another one that doesn't come before it in the file, but I thought it was easier to show it this way at first.

Susan: If the main function is going to be executed first, then how come the Average function is written first? Does the compiler always look for main first?

Steve: Yes.

Susan: Yeah, but could the Average function then just be written after main instead of before it? Just to be there when it is needed, instead of before it is needed? Am I right that you still would not have to write it twice; it would still be there for the next time it is needed, right?

Steve: The Average function can be anywhere, even in a different module, but at the point that you try to use it, the compiler has to know about it. To be precise, you have to specify its name, return type, and what arguments it takes. Otherwise, the program won't compile. On the other hand, the compiled version of the Average function doesn't have to be available until the executable is created;[8] if it's not available at that point, you'll get an error saying that you have referenced an undefined function.

[8] This is done by the linker, which we'll get to later in this chapter.

Susan: So does that mean you could put the Average function anywhere you want? Then could it or any "subfunction" be put anywhere you want because the main function would always be executed first? Or could you mess up the code if you put it in a really ridiculous place like inside an output or input statement. . . or could the compiler be able to ignore something like that and go about business as usual? I guess because of the brackets it should ignore such a thing but I am not sure. See, these are the things that we novices are obliged to ponder.

Steve: You can't start a function definition in the middle of another function. That's called a nested function and it's not allowed in C++. The rule can be stated approximately as "You can start a function definition anywhere except in the middle of another definition."

Susan: So then the "cue" for the Average function to begin is the word Average (weight) or (age), when the compiler sees that word it just begins that separate function to start its little calculation.

Steve: That's right, except that it needs two arguments, not just one.

Susan: And that function since it was named Average causes the averaging function to work. Is that how it goes?

Steve: If I understand your question, it's not the name that makes the Average function do the averaging, it's the code that adds up the two values and divides by 2. We could replace all the references to Average with the word Glorp and the compiler wouldn't care; however, a future programmer trying to read the program probably wouldn't be amused by that name.

Susan: Oh, so there is nothing magical about the word Average, I thought it might trigger a function of averaging. Well, that sounds reasonable; it's more for us humans than the computer. And then that brings up another question, along the same line of thinking. After the Average function has done its thing, how does the program go from return Result; to the next output statement that asks for the ages? What triggers that change? I am not seeing this in the code.

Steve: The return keyword tells the compiler to hand back control to the function that called the one where the return is, as indicated in Figure 5.2.

This discussion didn't slake her thirst for knowledge about how to write a program. Here is how we continued:

Susan: Can I mix shorts with strings using the headers that are already stated in the test program?

Steve: Mixing shorts with strings is a dubious proposition, sort of like adding apples and oranges together; could you be more specific about what you're trying to do?

Susan: What if you wanted to add a numerical value to your program such as test: You have to put in a short, right? So if you added a short, what else would you have to do to make it work? Or would you have to start over with another main function after the first part and then declare new variables? I tried that too, and the compiler did not like that either. Very inflexible it is. I will tell you after one more try what I am doing. This will keep you in suspense.

Steve: It depends on what you're trying to do with the short. It's usually best to have a specific problem in mind that you're trying to solve by writing a program. Then you may see how to use these facilities (shorts, strings, Vecs, etc.) to solve your problem; if not, you can ask me how they would fit into the solution.

As for your second suggestion, you're not allowed to have more than one main function in a program, because the compiler wouldn't know which one to use as the starting address for the program.

Susan: I am not really trying to solve anything, I just want to have the user type in more info and that info is a number — wait!! That is it, in that case it will be like an ASCII character and it doesn't need a short, right? That's right. I can still use a string. We are not crunching any numbers with this.

Steve: As long as you don't try to do any calculations, you can read the data into a string, even data that looks like a number; of course, that data entry method is pretty loose, since if the user types "abc" as an age, the program will accept it.

Susan: Can you define a string without a word but with just a wildcard type of variable like when we use i in shorts? In other words, does it matter what we call a variable?

Steve: A variable is always a “wildcard”, whether it's a short or a string. For example, a short variable always has a name, such as i, or index (or whatever makes sense to you), and a value, which is a number such as 14 or 99. A string variable also has a name, such as FirstName, or street (or whatever makes sense to you), and a value, which consists of characters rather than a number, such as "Susan" or "Wesley".

As you can see, using a function isn't very difficult. We have to provide it with the material to work on (its arguments) and can store its return value in a variable for further processing (or use it directly, if we wish). But there's a little more here than meets the eye. How does the variable FirstWeight, for example, get transformed into the variable First that we used when writing the function?

This explanation requires us to look at some more underlying software technology. To be precise, we're going to spend some time examining the infrastructure that makes computers usable for programmers. First, though, we have to consider a more general notion, that of a "virtual computer".

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

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