?? ch07.htm
字號:
<PRE><FONT COLOR="#0066FF">1: //Listing 7.13
2: //Demonstrates null statement
3: // as body of for loop
4:
5: #include <iostream.h>
6: int main()
7: {
8: for (int i = 0; i<5; cout << "i: " << i++ << endl)
9: ;
10: return 0;
<TT>11: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: i: 0
i: 1
i: 2
i: 3
i: 4
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>The <TT>for</TT> loop on
line 8 includes three statements: the initialization statement establishes the counter
<TT>i</TT> and initializes it to <TT>0</TT>. The condition statement tests for <TT>i<5</TT>,
and the action statement prints the value in <TT>i</TT> and increments it.<BR>
There is nothing left to do in the body of the <TT>for</TT> loop, so the null statement
(<TT>;</TT>) is used. Note that this is not a well-designed <TT>for</TT> loop: the
action statement is doing far too much. This would be better rewritten as</P>
<PRE><FONT COLOR="#0066FF">8: for (int i = 0; i<5; i++)</FONT></PRE>
<PRE><FONT COLOR="#0066FF">
9: cout << "i: " << i << endl;</FONT></PRE>
<P><FONT COLOR="#0066FF"><BR>
</FONT>While both do exactly the same thing, this example is easier to understand.
<H4 ALIGN="CENTER"><A NAME="Heading47"></A><FONT COLOR="#000077">Nested Loops</FONT></H4>
<P>Loops may be nested, with one loop sitting in the body of another. The inner loop
will be executed in full for every execution of the outer loop. Listing 7.14 illustrates
writing marks into a matrix using nested <TT>for</TT> loops.</P>
<P><A NAME="Heading48"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 7.14. Illustrates
nested for loops.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: //Listing 7.14
2: //Illustrates nested for loops
3:
4: #include <iostream.h>
5:
6: int main()
7: {
8: int rows, columns;
9: char theChar;
10: cout << "How many rows? ";
11: cin >> rows;
12: cout << "How many columns? ";
13: cin >> columns;
14: cout << "What character? ";
15: cin >> theChar;
16: for (int i = 0; i<rows; i++)
17: {
18: for (int j = 0; j<columns; j++)
19: cout << theChar;
20: cout << "\n";
21: }
22: return 0;
<TT>23: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: How many rows? 4
How many columns? 12
What character? x
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis: </B></FONT>The user is prompted for the number
of <TT>rows</TT> and <TT>columns</TT> and for a character to print. The first <TT>for</TT>
loop, on line 16, initializes a counter (<TT>i</TT>) to <TT>0</TT>, and then the
body of the outer for loop is run.<BR>
On line 18, the first line of the body of the outer <TT>for</TT> loop, another <TT>for</TT>
loop is established. A second counter (<TT>j</TT>) is also initialized to <TT>0</TT>,
and the body of the inner <TT>for</TT> loop is executed. On line 19, the chosen character
is printed, and control returns to the header of the inner <TT>for</TT> loop. Note
that the inner <TT>for</TT> loop is only one statement (the printing of the character).
The condition is tested (<TT>j < columns</TT>) and if it evaluates <TT>true</TT>,
<TT>j</TT> is incremented and the next character is printed. This continues until
<TT>j</TT> equals the number of columns.</P>
<P>Once the inner <TT>for</TT> loop fails its test, in this case after 12 <TT>X</TT>s
are printed, execution falls through to line 20, and a new line is printed. The outer
<TT>for</TT> loop now returns to its header, where its condition (<TT>i < rows</TT>)
is tested. If this evaluates <TT>true</TT>, <TT>i</TT> is incremented and the body
of the loop is executed.</P>
<P>In the second iteration of the outer <TT>for</TT> loop, the inner <TT>for</TT>
loop is started over. Thus, <TT>j</TT> is reinitialized to <TT>0</TT> and the entire
inner loop is run again.</P>
<P>The important idea here is that by using a nested loop, the inner loop is executed
for each iteration of the outer loop. Thus the character is printed <TT>columns</TT>
times for each row.
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>As an aside, many C++ programmers
use the letters <TT>i</TT> and <TT>j</TT> as counting variables. This tradition goes
all the way back to FORTRAN, in which the letters <TT>i</TT>, <TT>j</TT>, <TT>k</TT>,
<TT>l</TT>, <TT>m</TT>, and <TT>n</TT> were the only legal counting variables. Other
programmers prefer to use more descriptive counter variable names, such as <TT>Ctrl</TT>
and <TT>Ctr2</TT>. Using <TT>i</TT> and <TT>j</TT> in <TT>for</TT> loop headers should
not cause much confusion, however.
<HR>
</BLOCKQUOTE>
<H4 ALIGN="CENTER"><A NAME="Heading50"></A><FONT COLOR="#000077">Scoping in for Loops</FONT></H4>
<P>You will remember that variables are scoped to the block in which they are created.
That is, a local variable is visible only within the block in which it is created.
It is important to note that counting variables created in the header of a <TT>for</TT>
loop are scoped to the outer block, not the inner block. The implication of this
is that if you have two <TT>for</TT> loops in the same function, you must give them
different counter variables, or they may interfere with one another.
<H3 ALIGN="CENTER"><A NAME="Heading51"></A><FONT COLOR="#000077">Summing Up Loops</FONT></H3>
<P>On Day 5, "Functions," you learned how to solve the Fibonacci series
problem using recursion. To review briefly, a Fibonacci series starts with 1, 1,
2, 3, and all subsequent numbers are the sum of the previous two:</P>
<PRE><FONT COLOR="#0066FF">1,1,2,3,5,8,13,21,34...
</FONT></PRE>
<P>The nth Fibonacci number is the sum of the n-1 and the n-2 Fibonacci numbers.
The problem solved on Day 5 was finding the value of the nth Fibonacci number. This
was done with recursion. Listing 7.15 offers a solution using iteration.</P>
<P><A NAME="Heading52"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 7.15. Solving
the nth Fibonacci numberusing iteration.</B></FONT><FONT COLOR="#0066FF"></FONT>
<PRE><FONT COLOR="#0066FF">1: // Listing 7.15
2: // Demonstrates solving the nth
3: // Fibonacci number using iteration
4:
5: #include <iostream.h>
6:
7: typedef unsigned long int ULONG;
8:
9: ULONG fib(ULONG position);
10: int main()
11: {
12: ULONG answer, position;
13: cout << "Which position? ";
14: cin >> position;
15: cout << "\n";
16:
17: answer = fib(position);
18: cout << answer << " is the ";
19: cout << position << "th Fibonacci number.\n";
20: return 0;
21: }
22:
23: ULONG fib(ULONG n)
24: {
25: ULONG minusTwo=1, minusOne=1, answer=2;
26:
27: if (n < 3)
28: return 1;
29:
30: for (n -= 3; n; n--)
31: {
32: minusTwo = minusOne;
33: minusOne = answer;
34: answer = minusOne + minusTwo;
35: }
36:
37: return answer;
<TT>38: }</TT>
Output: Which position? 4
3 is the 4th Fibonacci number.
Which position? 5
5 is the 5th Fibonacci number.
Which position? 20
6765 is the 20th Fibonacci number.
Which position? 100
3314859971 is the 100th Fibonacci number.
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis</B></FONT><B>: </B>Listing 7.15 solves the Fibonacci
series using iteration rather than recursion. This approach is faster and uses less
memory than the recursive solution.<BR>
On line 13, the user is asked for the position to check. The function <TT>fib()</TT>
is called, which evaluates the position. If the position is less than 3, the function
returns the value <TT>1</TT>. Starting with position 3, the function iterates using
the following algorithm:<BR>
<B><BR>
1.</B> Establish the starting position: Fill variable <TT>answer</TT> with <TT>2</TT>,
<TT>minusTwo</TT> with <TT>0</TT> (<TT>answer</TT>-2), and <TT>minusOne</TT> with
<TT>1</TT> (<TT>answer</TT>-1). Decrement the position by 3, because the first two
numbers are handled by the starting position.<BR>
<BR>
<B>2.</B> For every number, count up the Fibonacci series. This is done by<BR>
<B>a.</B> Putting the value currently in <TT>minusOne</TT> into <TT>minusTwo</TT>.<BR>
<BR>
<B>b.</B> Putting the value currently in <TT>answer</TT> into <TT>minusOne</TT>.<BR>
<BR>
<B>c.</B> Adding <TT>minusOne</TT> and <TT>minusTwo</TT> and putting the sum in <TT>answer</TT>.<BR>
<BR>
<B>d.</B> Decrementing <TT>n</TT>.<BR>
<BR>
<B>3.</B> When <TT>n</TT> reaches <TT>0</TT>, return the answer.<BR>
<BR>
This is exactly how you would solve this problem with pencil and paper. If you were
asked for the fifth Fibonacci number, you would write:</P>
<PRE><FONT COLOR="#0066FF">1, 1, 2,</FONT></PRE>
<P>and think, "two more to do." You would then add <TT>2+1</TT> and write
<TT>3</TT>, and think, "one more to find." Finally you would write <TT>3+2</TT>
and the answer would be <TT>5</TT>. In effect, you are shifting your attention right
one number each time through, and decrementing the number remaining to be found.</P>
<P>Note the condition tested on line 30 (<TT>n</TT>). This is a C++ idiom, and is
exactly equivalent to <TT>n != 0</TT>. This <TT>for</TT> loop relies on the fact
that when <TT>n</TT> reaches <TT>0</TT> it will evaluate <TT>false</TT>, because
<TT>0</TT> is false in C++. The <TT>for</TT> loop header could have been written:</P>
<PRE><FONT COLOR="#0066FF">for (n-=3; n>0; n++)</FONT></PRE>
<P>which might have been clearer. However, this idiom is so common in C++ that there
is little sense in fighting it.</P>
<P>Compile, link, and run this program, along with the recursive solution offered
on Day 5. Try finding position 25 and compare the time it takes each program. Recursion
is elegant, but because the function call brings a performance overhead, and because
it is called so many times, its performance is noticeably slower than iteration.
Microcomputers tend to be optimized for the arithmetic operations, so the iterative
solution should be blazingly fast.</P>
<P>Be careful how large a number you enter. <TT>fib</TT> grows quickly, and long
integers will overflow after a while.
<H3 ALIGN="CENTER"><A NAME="Heading54"></A><FONT COLOR="#000077">switch Statements</FONT></H3>
<P>On Day 4, you saw how to write <TT>if</TT> and <TT>if/else</TT> statements. These
can become quite confusing when nested too deeply, and C++ offers an alternative.
Unlike <TT>if</TT>, which evaluates one value, <TT>switch</TT> statements allow you
to branch on any of a number of different values. The general form of the <TT>switch</TT>
statement is:</P>
<PRE><FONT COLOR="#0066FF">switch (expression)
{
case valueOne: statement;
break;
case valueTwo: statement;
break;
....
case valueN: statement;
break;
default: statement;
}
</FONT></PRE>
<P>expression is any legal C++ expression, and the statements are any legal C++ statements
or block of statements. <TT>switch</TT> evaluates <TT>expression</TT> and compares
the result to each of the <TT>case</TT> values. Note, however, that the evaluation
is only for equality; relational operators may not be used here, nor can Boolean
operations.</P>
<P>If one of the <TT>case</TT> values matches the expression, execution jumps to
those statements and continues to the end of the <TT>switch</TT> block, unless a
<TT>break</TT> statement is encountered. If nothing matches, execution branches to
the optional <TT>default</TT> statement. If there is no default and there is no matching
value, execution falls through the <TT>switch</TT> statement and the statement ends.
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>It is almost always a good idea
to have a <TT>default</TT> <TT>case</TT> in <TT>switch</TT> statements. If you have
no other need for the <TT>default</TT>, use it to test for the supposedly impossible
case, and print out an error message; this can be a tremendous aid in debugging.
<HR>
</BLOCKQUOTE>
<P>It is important to note that if there is no <TT>break</TT> statement at the end
of a <TT>case</TT> statement, execution will fall through to the next <TT>case</TT>
statement. This is sometimes necessary, but usually is an error. If you decide to
let execution fall through, be sure to put a comment, indicating that you didn't
just forget the <TT>break</TT>.</P>
<P>Listing 7.16 illustrates use of the <TT>switch</TT> statement.</P>
<P><A NAME="Heading55"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 7.16. Demonstrating
the switch statement</B></FONT><FONT SIZE="2" COLOR="#000077"><B>.</B></FONT><FONT
COLOR="#0066FF"></FONT>
<PRE><FONT COLOR="#0066FF">1: //Listing 7.16
2: // Demonstrates switch statement
3:
4: #include <iostream.h>
5:
6: int main()
7: {
8: unsigned short int number;
9: cout << "Enter a number between 1 and 5: ";
10: cin >> number;
11: switch (number)
12: {
13: case 0: cout << "Too small, sorry!";
14: break;
15: case 5: cout << "Good job!\n"; // fall through
16: case 4: cout << "Nice Pick!\n"; // fall through
17: case 3: cout << "Excellent!\n"; // fall through
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -