📄 ch04.htm
字号:
</tt>(as shown in Listing 4.5).</p><h4> Listing 4.4 Implicit Call to Constructor and Destructor</h4><pre><tt>0: #include "Game.h"</tt><tt>1: #include <iostream></tt><tt>2: </tt><tt>3: Game::Game():</tt><tt>4: round(1),</tt><tt>5: howManyPositions(0),</tt><tt>6: howManyLetters(0),</tt><tt>7: duplicatesAllowed(false)</tt><tt>8: {</tt><tt>9: cout << "In the Game constructor\n"" << endl;</tt><tt>10: }</tt><tt>11: </tt><tt>12: Game::~Game()</tt><tt>13: {</tt><tt>14: cout << "In the Game destructor\n" << endl;</tt><tt>15: }</tt><tt>16: </tt><tt>17: void Game::Play()</tt><tt>18: {</tt><tt>19: </tt><tt>20: }</tt></pre><h4> Listing 4.5 Driver Program for Listing 4.4</h4><pre><tt>0: #include <iostream></tt><tt>1: #include "Game.h"</tt><tt>2:</tt><tt>3: using namespace std;</tt><tt>4:</tt><tt>5: int main()</tt><tt>6: {</tt><tt>7: cout << "Creating the game\n" << endl;</tt><tt>8: Game theGame;</tt><tt>9: cout << "Exiting main\n" << endl;</tt><tt>10: return 0;</tt><tt>11: }</tt><tt>Creating the game</tt><tt>In the Game constructor</tt><tt>Exiting main</tt><tt>In the Game destructor</tt></pre><p>Here we've stripped the constructor down to do nothing except print an informative message. As you can see, creating the <tt>Game</tt> object causes the constructor to be invoked. Returning from <tt>main() </tt>ends the function and implicitly destroys any local objects. This causes the destructor to be invoked, which prints an equally informative message. <a name="_Toc444149710"></a></p><h3> <a name="Heading19">Using the Debugger</a></h3><p>Although this works, it is tedious to add these printout messages; in any case, you can only infer the effect because you don't actually see the constructor being invoked. The debugger is a far more powerful tool.</p><p>Load Listings 4.1, 4.2, and 4.3 into a project and compile, link, and run it. Now, put a break point on line 5 in Listing 4.3--the creation of the <tt>Game</tt> object (see Figure 4.?). You are ready to see what this does, so step into the function call. You find yourself at the opening brace to the constructor.</p><p>The debugger is a powerful tool for learning C++. It can show you explicitly what is happening in your program as it runs. Because you'll be using the debugger throughout this book, you might want to take a few minutes and read the documentation that came with your programming environment to learn more about how to use your debugger. <a name="_Toc444149711"></a><a name="_Toc450554051"></a></p><h2> <a name="Heading20">Examining the Constructor</a></h2><p>Careful examination of the constructor reveals that you have, essentially, duplicated the logic you had in <tt>main() </tt>in the preceding chapter. The one exception is that you are now capturing and storing the user's preferences in member variables as shown on lines 25, 39, and 52. These member variables are part of the object and will, therefore, persist and contain these values after the constructor returns. <a name="_Toc444149712"></a><a name="_Toc450554052"></a></p><h2> <a name="Heading21">The Other Methods</a></h2><p>The <tt>Game</tt> object has two other methods: a destructor and the <tt>Play()</tt> method. At this time neither of these methods has any action, and you'll note that <tt>Play()</tt> is not yet called. This <i>stubbed out</i> function exists only to remind the programmer of his intent--that eventually this class will include a meaningful <tt>Play()</tt> method.</p><blockquote> <hr> <p><strong>NOTE: </strong> When a programmer wants to show a method or function but does not want to do the work of implementing that function, he <i>stubs it out</i>: He creates a stub function that does nothing more than return, or at most prints, a message "in myTestMethod" and then returns. <a name="_Toc444149713"></a><a name="_Toc450554053"></a></p> <hr></blockquote><h2> <a name="Heading22">Storing the Pattern</a></h2><p>The computer creates a pattern that the human player guesses. How is this pattern to be stored? Clearly, you need the capability to store between <tt>minLetters</tt> and <tt>maxLetters</tt> characters as a pattern against which you can compare the human's guesses. </p><blockquote> <hr> <p><strong>NOTE: </strong> Let me explain the preceding sentence because this is exactly how programmers talk about a problem like this: "The capability to store between <tt>minLetters</tt> and <tt>maxLetters</tt> characters." This sentence is easier to understand if we use sample values: If <tt>minLetters</tt> is <tt>2</tt> and <tt>maxLetters</tt> is <tt>10</tt>, this sentence means that you need the capability to store between <tt>2</tt> and <tt>10</tt> letters in a pattern. </p> <p> Programmers become comfortable using variables rather than absolute values in their formulations of a problem. The astute reader might also note that in fact we store these values (<tt>minLetter</tt> and <tt>maxLetter</tt>) as constants, not variables. That is true, but the values can vary from one compiled version to another, so they are variable in the more general sense.</p> <hr></blockquote><p>So how <i>do</i> you store the computer's secret code? Let's assume that the player chooses seven possible letters with five positions, and the computer generates a secret code of <tt>acbed</tt>. How do you store this string of letters?</p><p>You have several options. You can use the built-in array class or the standard library string, you can create your own data structure to hold the letters, or you can use one of the standard library collection classes.</p><p>The rest of this chapter examines arrays in some detail; in coming chapters you'll turn to other alternatives. <a name="_Toc444149714"></a><a name="_Toc450554054"></a></p><h2> <a name="Heading23">What Is an Array?</a></h2><p>An <i>array</i> is a fixed-size<i> </i>collection of data storage locations, each of which holds the same type of data. Each storage location is called an <i>element</i> of the array.</p><blockquote> <hr> <p><strong> </strong> <b>Array</b>--A fixed size collection of data</p> <hr></blockquote><p>You declare an array by writing the type, followed by the array name and the subscript. The <i>subscript</i> is the number of elements in the array, surrounded by square brackets. For example</p><pre><tt>long LongArray[25];</tt></pre><p>declares an array of 25 long integers, named <tt>LongArray</tt>. When the compiler sees this declaration, it sets aside enough memory to hold all 25 elements. Because each long integer requires 4 bytes, this declaration sets aside 100 contiguous bytes of memory, as illustrated in Figure 4.1.</p><blockquote> <hr> <p><strong> </strong> <b>subscript</b>--The number of elements in an array</p> <hr></blockquote><p><b>Figure 4.1 </b><i>Declaring an array. <a name="_Toc444149715"></a></i></p><h3> <a name="Heading24">Initializing Arrays</a></h3><p>You can initialize a simple array of built-in types, such as integers and characters, when you first declare the array. After the array name, put an equal sign (=) and a list of comma-separated values enclosed in braces. For example</p><pre><tt>int IntegerArray[5] = { 10, 20, 30, 40, 50 };</tt></pre><p>declares <tt>IntegerArray</tt> to be an array of five integers. It assigns <tt>IntegerArray[0]</tt> the value <tt>10</tt>, <tt>IntegerArray[1]</tt> the value <tt>20</tt>, and so on.</p><p>If you omit the size of the array, an array that is just big enough to hold the initialization is created. Therefore, if you write</p><pre><tt>int IntegerArray[] = { 10, 20, 30, 40, 50 };</tt></pre><p>you create exactly the same array as you did in the preceding example.</p><p>If you need to know the size of the array, you can ask the compiler to compute it for you. For example</p><pre><tt>int IntegerArrayLength = sizeof(IntegerArray)/sizeof(IntegerArray[0]);</tt></pre><p>sets the <tt>int</tt> variable <tt>IntegerArrayLength</tt> to the result that is obtained by dividing the size of the entire array by the size of each individual entry in the array. That quotient is the number of members in the array.</p><p>You cannot initialize more elements than you've declared for the array. Therefore,</p><pre><tt>int IntegerArray[5] = { 10, 20, 30, 40, 50, 60};</tt></pre><p>generates a compiler error because you've declared a five-member array and initialized six values. You can, however, write</p><pre><tt>int IntegerArray[5] = { 10, 20};</tt></pre><p>Uninitialized array members have no guaranteed values; therefore, any value might be in an array member if you don't initialize it. <a name="_Toc444149716"></a></p><h4>Initializing Character Arrays</h4><p>You can use a special syntax for initializing character arrays. Rather than writing</p><pre><tt>char alpha[] = { 'a', 'b', 'c' };</tt></pre><p>you can write</p><pre><tt>char alpha[] = "abc"; </tt></pre><p>This creates an array of four characters and initializes with the three letters shown, followed by a <tt>NULL</tt> character. It is exactly as if you had written</p><pre><tt>char alpha[4] = {'a','b','c',0}</tt></pre><p>It adds the <tt>NULL</tt> because <tt>NULL</tt>-terminated strings have special meaning in C and C++. <a name="_Toc444149717"></a></p><h4>C-Style Strings</h4><p>C++ inherits from C the capability to create <i>strings</i>, which are meaningful groups of characters used to store words, phrases, and other strings of characters. These strings are represented in C and C++ as <tt>NULL</tt>-terminated arrays of characters. The old C library string.h, still a part of C++, provides methods for manipulating these strings: copying them, printing them, and so on. </p><p>The new Standard Library now includes a far better alternative: the <tt>string</tt> class. Objects of type <tt>string</tt> offer all the functionality of old C-style <tt>NULL</tt>-terminated arrays of characters, but with all the benefits of being well-defined types. That is, the new libraries are object-oriented, type safe, and well encapsulated.</p><p>You'll look at <tt>string</tt> objects in some detail as we go forward, and along the way I'll review some of the details of how C-style strings are used. For now, you're actually using this array of characters as a simple array, and it is not <tt>NULL</tt>-terminated. You are using the array as a collection. The objects that are being collected happen to be characters, but they can just as easily be integers or anything else you can store in an array. <a name="_Toc444149718"></a></p><h3> <a name="Heading25">Array Elements</a></h3><p>You access each of the array elements by referring to an offset from the array name. Array elements are counted from zero. Therefore, the first array element is <tt>arrayName[0]</tt>. </p><p>In the version of the program we'll examine for the rest of this chapter, you'll add a member variable <tt>solution</tt>, which will hold an array of characters that represent the solution to the code generated by the compiler.</p><p>The declaration for that array is</p><pre><tt> char solution[maxPos+1];</tt></pre><p>This creates an array of characters that can hold exactly one more than <tt>maxPos</tt> characters. <tt>maxPos</tt> is a symbolic constant defined to <tt>10</tt>, so this defines an array of 11 characters. The 11th character is the <tt>NULL</tt> character.</p><p>Because arrays count from offset <tt>0</tt>, the elements in this array are <tt>solution[0], solution[1], solution[2]...solution[9]</tt>. <a name="_Toc444149719"></a></p><h3> <a name="Heading26">Writing Past the End of an Array</a></h3><p>When you write a value to an element in an array, the compiler computes where to store the value, based on the size of each element and the subscript. Suppose that you ask to write over the value at <tt>solution[5]</tt>, which is the sixth element. The compiler multiplies the offset (<tt>5</tt>) by the size of each element. Since this is a <tt>char</tt> array, each element is 1 byte, so the math is fairly simple. The compiler then moves that many bytes (5) from the beginning of the array and writes the new value at that location.</p><p>If you ask to write at <tt>solution[12]</tt>, the compiler ignores the fact that there is no such element. It computes how far past the first element it is to look, and then writes over whatever is at that location. This can be virtually any data, and writing your new value there might have unpredictable results. If you're lucky, your program will crash immediately. If you're unlucky, you'll get strange results elsewhere in your program, and you'll spend weeks trying to find the bug. <a name="_Toc444149720"></a></p><h4>Fence Post Errors</h4><p>It is so common to write to one past the end of an array that this bug has its own name. It is called a <i>fence post error</i>. This refers to the problem in counting how many fence posts you need for a 10-foot fence if you need one post for every foot: Most people answer ten, but of course you need 11. Figure 4.2 makes this clear.</p><p><b>Figure 4.2 </b><i>Fence post errors.</i></p><p>This sort of "off by one" counting can be the bane of any programmer's life. Over time, however, you'll get used to the idea that a 25-element array counts only to element 24, and that everything counts from zero. </p><blockquote> <hr> <p><strong>NOTE: </strong> Fence post errors are responsible for one of the great misunderstandings of our time: when the new millennium begins. A millennium is 1,000 years. We are ending the second millennium of the Common Era, and we are about to start the third--but when, exactly?</p> <p> The first Millennium began with the year 1 and ended with the year 1000. The second Millennium runs from 1001 to 2000. The third will begin on January 1, 2001. (Don't tell the newspapers.)</p> <p> Of course, to a C++ programmer this is all wrong. We begin counting with 0, and 1K is 1,024, thus the third C++ Millennium begins on January 1, 2048. Call it the Y2K2 problem.</p> <p> Some programmers refer to <tt>ArrayName[0]</tt> as the <i>zeroth</i> element. Getting into this habit is a big mistake. If <tt>ArrayName[0]</tt> is the zeroth element, what is <tt>ArrayName[1],</tt> the <i>oneth</i>? If so, when you see <tt>ArrayName[24]</tt>, will you realize that it is not the 24th element, but rather the 25th? It is far better to say that <tt>ArrayName[0]</tt> is at offset zero and is the first element. <a name="_Toc444149721"></a><a name="_Toc450554055"></a></p> <hr></blockquote><h2> <a name="Heading27">Generating the Solution</a></h2><p>Now that you have an array to hold the solution, how do you add letters to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -