Index Variables

Now let's get back to our discussion of the revised pumpkin-weighing program. The last two lines in the variable definition phase define two variables, called i and k, which have been traditional names for index variables (i.e., variables used to hold indexes) since the invention of FORTRAN, one of the first relatively “user-friendly” computer languages, in the 1950s. The inventors of FORTRAN used a fairly simple method of determining the type of a variable: if it began with one of the letters I through N, it was an integer. Otherwise, it was a floating-point variable (i.e., one that can hold values that contain a fractional part, such as 3.876). This rule was later changed so that the user could specify the type of the variable regardless of its name, as in C++, but the default rules were the same as in the earlier versions of FORTRAN, to allow programs using the old rules to continue to compile and run correctly.

Needless to say, Susan had some questions about the names of index variables:

Susan: So whenever you see i or k you know you are dealing with a Vec?

Steve: Not necessarily. Variables named i and k are commonly used as indexes, but they are also used for other purposes sometimes.

Susan: Anyway, if i and k are sometimes used for other purposes, then the compiler doesn't care what you use as indexes? Again, no rules, just customs?

Steve: Right. It's just for the benefit of other programmers, who will see i and say “oh, this is probably an index variable”.

I suspect one reason for the durability of these short names is that they're easy to type, and many programmers aren't very good typists.[8] In C++, the letters i, j, k, m and n are commonly used as indexes; however, l (the letter “ell”) generally isn't, because it looks too much like a 1 (the numeral one).[9] The compiler doesn't get confused by this resemblance, but programmers very well might.

[8] I strongly recommend learning how to type (i.e., touch type). I was a professional programmer without typing skills for over 10 years before agreeing to type someone else's book manuscript. At that point, I decided to teach myself to touch-type, so I wrote a Dvorak keyboard driver for my Radio Shack Model III computer and started typing. In about a month I could type faster than with my previous two-finger method and eventually got up to 80+ words per minute on English text. If you've never heard of the Dvorak keyboard, it's the one that has the letters laid out in an efficient manner; the “home row” keys are AOEUIDHTNS rather than the absurd set ASDFGHJKL;. This “new” (1930s) keyboard layout reduces effort and increases speed and accuracy compared to the old QWERTY keyboard, which was invented in the 1880s to prevent people from typing two keys in rapid succession and jamming the typebars together. This problem has been nonexistent since the invention of the Selectric typewriter (which uses a ball rather than typebars) in 1960, but inertia keeps the old layout in use even though it is very inefficient. In any event, since I learned to type, writing documentation has required much less effort. This applies especially to writing articles or books, which would be a painful process otherwise.

[9] I also don't use variables called j in the programs in this book, because j looks too much like i and could therefore be confusing.

After the variable definitions are out of the way, we can proceed to the executable portion of our program. First we type out a note to the user, stating what to expect. Then we get to the code in Figure 4.7.

Figure 4.7. Using a for loop (from codevect1.cpp)
for (i = 0; i < 5; i ++)
  {
  cout << "Please type in weight #" << i+1 << ": ";
  cin >> Weight[i];
  }

The first line here is called a ffor statement, which is used to control a for loop; this is a loop control facility similar to the while loop we encountered in Chapter 3. The difference between these two statements is that a for loop allows us to specify more than just the condition under which the controlled block will be repetitively executed.[10] A for statement specifies three expressions (separated by “;”) that control the execution of the for loop: a starting expression, a continuation expression, and a modification expression. In our case, these are i = 0, i < 5, and i ++, respectively. Let's look at the function and meaning of each of these components.

[10] You may sometimes see the term controlled statement used in place of controlled block. Since, as we have already seen, a block can be used anywhere that a single statement can be used, controlled statement and controlled block are actually just two ways of saying nearly the same thing.

First, the starting expression, in this case i = 0. The starting expression is executed once before the block controlled by the for statement is executed. In this case, we use it to set our index variable, i, to 0, which will refer to the first element of our Weight Vec.

Next, the continuation expression, in this case i < 5. As long as this expression is true, the controlled block of the for will be executed; in this case, we will continue executing the controlled block as long as the value of i is less than 5. Note: the continuation expression is actually executed before every execution of the controlled block; thus, if the continuation expression is false when the loop is entered for the first time, the controlled block will not be executed at all.

The notion of the continuation expression is apparently confusing to some novices. Susan fell into that group.

Susan: In your definition of for, how come there is no ending expression? Why is it only a modification expression? Is there never a case for a conclusion?

Steve: The “continuation expression” tells the compiler when you want to continue the loop; if the continuation expression comes out false, then the loop terminates. That serves the same purpose as an “ending expression” might, but in reverse.

Finally, let's consider the modification expression, i ++.[11] This is exactly equivalent to i = i + 1, which means “set i to one more than its current value”, an operation technically referred to as incrementing a variable. You may wonder why we need two ways to say the same thing; actually, there are a few reasons. One is that ++ requires less typing, which as I've already mentioned isn't a strong point of many programmers. Also, the ++ (pronounced “plus plus”) operator doesn't allow the possibility of mistyping the statement as, for example, i = j + 1; when you really meant to increment i. Another reason why this feature was added to the C language is that in the early days of C, compiler technology wasn't very advanced and the ++ operator allowed the production of more efficient programs. You see, many machines can add one to a memory location by a single machine language instruction, usually called something like inc, shorthand for increment memory. Even a simple compiler can generate an “increment memory” instruction as a translation of i ++, while it takes a bit more sophistication for the compiler to recognize i = i + 1 as an increment operation. Since incrementing a variable is a very common operation in C++, this was worth handling specially.[12]

[11] You don't need a space between the variable name and the ++ operator; however, I think it's easier to read this way.

[12] By the way, the name C++ is sort of a pun using this notation; it's supposed to mean “the language following C”. In case you're not doubled over with laughter, you're not alone. I guess you had to be there.

Here's an English translation of our sample for statement:

  1. Set the index variable i to 0.

  2. If the value of i is less than 5, execute the following block (in this case, the block with the cout and cin statements). Otherwise, skip to the next statement after the end of the controlled block; that is, the one following the closing }.

  3. Add one to the value of i and go back to step 2.

Susan didn't think these steps were very clear. Let's listen in on the conversation that ensued:

Susan: Where in the for statement does it say to skip to the next statement after the end of the controlled block when i is 5 or more?

Steve: It doesn't have to. Remember, the point of { } is to make a group of statements act like one. A for statement always controls exactly one “statement”, which can be a block contained in {}. Therefore, when the continuation expression is no longer true, the next “statement” to be executed is whatever follows the } at the end of the block.

Susan: Okay, now I get it. The { } curly brackets work together with the < 5 to determine that the program should go on to the next statement.

Steve: Right.

Susan: Now, on the “controlled block” — so other statements can be considered controlled blocks too? I mean is a controlled block basically just the same thing as a block? I reviewed your definition of block, and it seems to me that they are. I guess it is just a statement that in this case is being controlled by for.

Steve: Correct. It's called a controlled block because it's under the control of another statement.

Susan: So if we used while before the { } then that would be a while controlled block?

Steve: Right.

Susan: Then where in step 3 or in i++ does it say to go back to step 2?

Steve: Again, the for statement executes one block (the controlled block) repeatedly until the continuation expression is false. Since a block is equivalent to one statement, the controlled block can also be referred to as the controlled statement. In the current example, the block that is controlled by the for loop consists of the four lines starting with the opening { on the next line after the for statement itself and ending with the closing } after the line that says cin >> Weight[i];.

Susan: Okay. But now I am a little confused about something else here. I thought that cout statements were just things that you would type in to be seen on the screen.

Steve: That's correct, except that cout is a variable used for I/O, not a statement.

Susan: So then why is << i+1 << put in at this point? I understand what it does now but I don't understand why it is where it is.

Steve: Because we want to produce an output line that varies depending on the value of i. The first time, it should say

Please enter weight #1:

The second time, it should say

Please enter weight #2:

and so on. The number of the weight we're asking for is one more than i; therefore we insert the expression << i + 1 << in the output statement so that it will stick the correct number into the output line at that point.

Susan: How does << i+1 << end up as #1 ?

Steve: The first time, i is 0; therefore, i + 1 is 1. The # comes from the end of the preceding part of the output statement.

Now let's continue with the next step in the description of our for loop, the modification expression i ++. In our example, this will be executed five times. The first time, i will be 0, then 1, 2, 3, and finally 4. When the loop is executed for the fifth time, i will be incremented to 5; therefore, step 2 will end the loop by skipping to the next statement after the controlled block.[13] A bit of terminology is useful here: each time through the loop is called an iteration.

[13] Why is the value of i at the end of this loop 5 rather than 4? Because at the end of each pass through the loop, the modification expression (i ++) is executed before the continuation expression that determines whether the next execution will take place (i < 5). Thus, at the end of the fifth pass through the loop, i is incremented to 5 and then tested to see if it is still less than 5. Since it isn't, the loop terminates at that point.

Let's hear Susan's thoughts on this matter.

Susan: When you say that “step 2 will end the loop by skipping to the next statement after the controlled block”, does that mean it is now going on to the next for statement? So when i is no longer less than 5, the completion of the loop signals the next controlled block?

Steve: Yes and no. In general, after all the iterations in a loop have been performed, execution proceeds to whatever statement follows the controlled block. In this case, the next statement is indeed a for statement, so that's the next statement that is performed after the end of the current loop.

The discussion of the for statement led to some more questions about loop control facilities and the use of parentheses:

Susan: How do you know when to use () ? Is it only with if and for and while and else and stuff like that, whatever these statements are called? I mean they appear to be modifiers of some sort; is there a special name for them?

Steve: The term loop control applies to statements that control loops that can execute controlled blocks a (possibly varying) number of times; these include for and while. The if statement is somewhat different, since its controlled block is executed either once or not at all. The () are needed in that case to indicate where the controlling expression(s) end and the controlled block begins. You can also use () to control the order of evaluation of an arithmetic expression: The part of the expression inside parentheses is executed first, regardless of normal ordering rules. For example, 2*5+3 is 13, while 2*(5+3) is 16.

Susan: So then if you just wrote while CurrentWeight > 0 with no () then the compiler couldn't read it?

Steve: Correct.

Susan: Actually it is beginning to look to me as I scan over a few figures that almost everything has a caption of some sort surrounding it. Everything either has a " " or () or { } or [ ] or <> around it. Is that how it is going to be? I am still not clear on the different uses of () and { }; does it depend on the control loop?

Steve: The { } are used to mark the controlled block, while the () are used to mark the conditional expression(s) for the if, while, for, and the like. Unfortunately, () also have other meanings in C++, which we'll get to eventually. The inventor of the language considers them to have been overused for too many different meanings, and I agree.

Susan: OK, I think I have it: { } define blocks and () define expressions. How am I to know when a new block starts? I mean if I were doing the writing, it would be like a new paragraph in English, right? So are there any rules for knowing when to stop one block and start another?

Steve: It depends entirely on what you're trying to accomplish. The main purpose of a block is to make a group of statements act like one statement; therefore, for example, when you want to control a group of statements by one if or for, you group those statements into a block.

Now that we've examined the for statement in excruciating detail, what about the block it controls? The first statement in the block:

cout << "Please type in weight #" << i+1 << ": ";

doesn't contain anything much we haven't seen before; it just displays a request to enter a weight. The only difference from previous uses we've made of the cout facility, is that we're inserting a numeric expression containing a variable, i+1, into the output. This causes the expression to be translated into a human-readable form consisting of digits. All of the expressions being sent to cout in one statement are strung together to make one line of output, if we don't specify otherwise. Therefore, when this statement is executed during the first iteration of the loop, the user of this program will see:

Please type in weight #1:

Then the user will type in the first weight. The same request, with a different value for the weight number, will show up each time the user hits ENTER, until five values have been accepted.

The second statement in the controlled block,

cin >> Weight[i];

is a little different. Here, we're reading the number the user has typed in at the keyboard and storing it in a variable. But the variable we're using is different each time through the loop; it's the “ith” element of the Weight Vec. So, on the first iteration, the value the user types in will go into Weight[0], the value accepted on the second iteration will go into Weight[1], and so on, until on the fifth and last iteration, the typed-in value will be stored in Weight[4].

Here's Susan's take on this.

Susan: What do you mean by the ith element? So does Weight[i] mean you are directing the number that the user types in to a certain location in memory?

Steve: Yes, to the element whose number is the current value of i.

Susan: When you say cin >> Weight[i] does that mean you are telling the computer to place that variable in the index? So this serves two functions, displaying the weight the user types in and associating it to the index?

Steve: No, that statement has the sole function of telling the computer to place the value read in from the keyboard into element i of Vec Weight.

Susan: What I am confusing is what is being seen on the screen at the time that the user types in the input. So, the user sees the number on the screen but then it isn't displayed anywhere after that number is entered? Then, the statement cin >> Weight [i] directs it to a location somewhere in memory with a group of other numbers that the user types in?

Steve: Correct. This will be illustrated under the contents of Weight heading in Figures 4.104.13.

Figure 4.10. Initial situation

Figure 4.13. Final situation

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

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