⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch04.htm

📁 C++ From Scratch: An Object-Oriented Approach is designed to walk novice programmers through the ana
💻 HTM
📖 第 1 页 / 共 4 页
字号:
  it? You want to generate letters at random, and you don't want the user to be   able to guess the solution. The C++ library provides a method, <tt>rand()</tt>,   which generates a pseudo-random number. It is pseudo-random in that it always   generates numbers in the same predictable order, depending on where it starts--but   they appear to be random.</p><p>You can increase the apparent randomness of the numbers that are generated   if you start the random number generator with a different <i>starting</i> number   (which we call a seed number) each time you run the program. </p><p>You provide <tt>rand()</tt> with a seed number by first calling <tt>srand()</tt>   and passing in a value. <tt>srand</tt> (<i>s</i>eed <i>random</i>) gives the   random number generate a starting point to work from. The seed determines the   first random number that will be generated. </p><p>If you don't call <tt>srand()</tt> first, <tt>rand()</tt> behaves as if you have   called <tt>srand()</tt><tt> </tt>with the seed value <tt>1</tt>. </p><p>You want to change the seed value each time you run the program so that you'll   invoke one more library function: <tt>time()</tt>. The function <tt>time</tt>   returns the system time, expressed as a large integer. </p><blockquote>  <hr>  <p><strong>NOTE: </strong> Interestingly, it actually provides you with the     number of seconds that have elapsed since midnight, January 1, 1970, according     to the system clock. This date, 1/1/1970, is known as the <i>epoch,</i> the     moment in time from which all other computer dates are calculated. </p>  <hr></blockquote><p>The <tt>time()</tt> function takes a parameter of type <tt>time_t</tt>, but   we don't care about this because it is happy taking the <tt>NULL</tt> value   instead:</p><pre><tt>         srand( (unsigned)time( NULL ) );</tt></pre><p>The sequence, then, is to call <tt>time()</tt>, pass in <tt>NULL</tt>, cast   the returned value to unsigned <tt>int</tt>, and pass that result to <tt>srand()</tt>.   This provides a reasonably random value to <tt>srand()</tt>, causing it<tt> </tt>to   initialize <tt>rand() </tt>to a nearly-random starting point.</p><blockquote>  <hr>  <p><strong>NOTE: </strong> Let's talk about casting a value. When you cast a     value to unsigned you say to the compiler, "I know you don't think this is     an unsigned integer, but I know better, so just treat it like one." In this     case, <tt>time()</tt> returns the value of type <tt>time_t</tt>, but you know     from the documentation that this can be treated as an unsigned integer--and     an unsigned integer is what <tt>srand()</tt> expects. Casting is also called     "hitting it with the big hammer." It works great, but you've disconnected     the sprinklers and disabled the alarms, so be sure you know what you're doing.</p>  <hr></blockquote><p>Now that you have a random number, you need to convert it into a letter in   the range you need. To do this, you'll use an array of 26 characters, the letters   <i>a</i>-<i>z</i>. By creating such an array, you can convert the value <tt>0</tt>   to <tt>a</tt>, the value <tt>1</tt> to <tt>b</tt><i>,</i> and so on. </p><p>Quick! What is the value of <i>z</i>? If you said <tt>25</tt>, pat yourself   on the back for not making the fence post error of thinking it would be <tt>26</tt>.</p><p>We'll call the character array <tt>alpha</tt>. You want this array to be available   from just about anywhere in your program. Earlier we talked about local variables,   variables whose scope is limited to a particular method. We also talked about   class member variables, which are variables that are scoped to a particular   object of a class. A third alternative is a <i>global variable</i>.</p><blockquote>  <hr>  <p><strong> </strong> <b>global variable</b>--A variable with no limitation     in its scope--visible from anywhere in your program</p>  <hr></blockquote><p>The advantage of global variables is that they are visible and accessible from   anywhere in your program. That is also the bad news--and C++ programmers avoid   global variables like the plague. The problem is that they can be changed from   any part of the program, and it is not uncommon for global variables to create   tricky bugs that are terribly difficult to find. </p><p>Here's the problem: You're going along in your program and everything is behaving   as expected. Suddenly, a global variable has a new and unexpected value. How'd   that happen? With global variables, it is difficult to tell because they can   be changed from just about anywhere.</p><p>In this particular case, although you want <tt>alpha</tt> to be visible throughout   the program, you don't want it changed at all. You want to create it once and   then leave it around. That is just what constants are for. Instead of creating   a global variable, which can be problematic, you'll create a <i>global constant</i>.   Global constants are just fine:</p><pre><tt>const char alpha[] = "abcdefghijklmnopqrstuvwxyz";</tt></pre><blockquote>  <hr>  <p><b>global constant</b>--A constant with no limitation in its scope--visible     from anywhere in your program.</p>  <hr></blockquote><p>This creates a constant named <tt>alpha</tt> that holds 27 characters (the   characters <i>a</i>-<i>z</i> and the terminating <tt>NULL</tt>). With this in   place,</p><pre><tt>alpha[0]</tt></pre><p>evaluates to <i>a</i>, and</p><pre><tt>alpha[25]</tt></pre><p>evaluates to <i>z</i>.</p><blockquote>  <hr>  <p><strong>NOTE: </strong> We'll include the declaration of <tt>alpha</tt> in     a new file called definedValues.h, and we'll <tt>#include</tt> that file in     any file that needs to access <tt>alpha</tt>. This way, we create one place     for all our global constants (all our defined values), and we can change any     or all of them by going to that one file.</p>  <hr></blockquote><h4> Listing 4.5 Adding Characters to the Array</h4><pre><tt>0:  for ( i = 0; i &lt; howManyPositions; )</tt><tt>1:  {</tt><tt>2:      int nextValue = rand() % (howManyLetters);</tt><tt>3:      char c = alpha[nextValue];</tt><tt>4:      if ( ! duplicatesAllowed &amp;&amp; i &gt; 0 )</tt><tt>5:      {</tt><tt>6:          int count = howMany(solution, c);</tt><tt>7:          if ( count &gt; 0 )</tt><tt>8:              continue;</tt><tt>9:      }</tt><tt>10:      // add to the array</tt><tt>11:      solution[i] = c;</tt><tt>12:      i++;</tt><tt>13:  }</tt><tt>14:  solution[i] = '\0';</tt><tt>15:  </tt><tt>16:  }</tt></pre><p> On line 0 you create a <tt>for</tt> loop to run once for each position. Thus,   if the user has asked for a code with five positions, you'll create five letters.</p><p>On line 2 you call <tt>rand()</tt>, which generates a random value. You use the   modulus operator (<tt>%</tt>) to turn that value into one in the range <tt>0</tt>   to <tt>howManyLetters</tt><tt>-1</tt>. Thus, if <tt>howManyLetters</tt> is <tt>7</tt>,   this forces the value to be <tt>0</tt>, <tt>1</tt>, <tt>2</tt>, <tt>3</tt>,   <tt>4</tt>, <tt>5</tt>, or <tt>6</tt>. </p><p>Let's assume for the purpose of this discussion that <tt>rand()</tt> first generates   the value <tt>12</tt>, and that <tt>howManyLetters</tt> is <tt>7</tt>. How is   the value <tt>12</tt> turned into a value in the range <tt>0</tt> through <tt>6</tt>?   To understand this, you must start by examining <i>integer division</i>.</p><p>Integer division is somewhat different from everyday division. In fact, it   is exactly like the division you originally learned in fourth grade. "Class,   how much is 12 divided by seven?" The answer, to a fourth grader, is "One, remainder   five." That is, seven goes into 12 exactly once, with five "left over."</p><blockquote>  <hr>  <p><strong> </strong> <b>integer division</b>--When the compiler divides two     integers, it returns the whole number value and loses the "remainder."</p>  <hr></blockquote><p>When an adult divides 12 by 7, the result is a real number (1.714285714286).   Integers, however, don't have fractions or decimal parts, so when you ask a   programming language to divide two integers, it responds like a fourth grader,   giving you the whole number value without the remainder. Thus, in integer math,   12/7 returns the value <tt>1</tt>.</p><p>Just as you can ask the fourth grader to tell you the remainder, you can use   the modulus operator (<tt>%</tt>) to ask your programming language for the remainder   in integer division. To get the remainder, you take 12 modulus 7 (<tt>12 % 7</tt>),   and the result is 5. The modulus operator tells you the remainder after an integer   division.</p><p>This result of a modulus operator is always in the range zero through the operand   minus one. In this case, zero through seven minus one (or zero through six).   If an array contains seven letters, the offsets are <tt>0</tt>-<tt>6</tt>, so   the modulus operator does exactly what you want: It returns a valid offset into   the array of letters.</p><p>On line 3 you can use the value that is returned from the modulus operator   as an offset into <tt>alpha,</tt> thus returning the appropriate letter. If you   set <tt>howManyLetters</tt> to <tt>7</tt>, the result will be that you'll always   get a number between zero and six, and, therefore, a letter in the range <i>a</i>   through <i>g</i>--exactly what you want!</p><p>Next, on line 4 you check to see whether you're allowing duplicates in this   game. If not, enter the body of the <tt>if</tt> statement.</p><p>Remember, the bang symbol (<tt>!</tt>) indicates <i>not</i>, so </p><pre><tt>if ( ! duplicatesAllowed )</tt></pre><p>evaluates <tt>true</tt> if <tt>duplicatesAllowed</tt> evaluates <tt>false</tt>.   Thus, if not, <tt>duplicatesAllowed</tt> means "if we're not allowing duplicates."   The second half of the and statement is that <i>i</i> is greater than zero.   There is no point in worrying about duplicates if this is the first letter you're   adding to the array.</p><p>On line 6 you assign to the integer variable <tt>count</tt> the result of the   member method <tt>howMany()</tt>. This method takes two parameters--a character   array and a character--and returns the number of times the character appears   in the array. If that value is greater than zero, this character is already   in the array and the <tt>continue</tt> statement causes processing to jump immediately   to the top of the <tt>for</tt> loop, on line 0. This tests <i>i</i>, which is   unchanged, so proceed with the body of the <tt>for</tt> loop on line 2, where   you'll generate a new value to try out.</p><p>If <tt>howMany()</tt> returns zero, processing continues on line 11, where   the character is added to <tt>solution</tt> at offset <tt>i</tt>. The net result   of this is that only unique values are added to the solution if you're not allowing   duplicates. Next, <tt>i</tt> is incremented (<tt>i++</tt>) and processing returns   to line 0, where <tt>i</tt> is tested against <tt>howManyPositions</tt>. When   <tt>i</tt> is equal to <tt>howManyPositions</tt>, the <tt>for</tt> loop is completed.</p><p>Finally, on line 14 you add a <tt>NULL</tt> to the end of the array to indicate   the end of the character array. This enables you to pass this array to <tt>cout</tt>,   which prints every character up to the <tt>NULL</tt>.</p><blockquote>  <hr>  <p><strong>NOTE: </strong> To designate a <tt>NULL in a character array</tt>,     use the special character <tt>'\0'</tt>. To designate <tt>NULL</tt> otherwise,     use the value <tt>0</tt> or the constant <tt>NULL</tt>. <a name="_Toc444149722"></a><a name="_Toc450554056"></a></p>  <hr></blockquote><h2> <a name="Heading28">Examining the Defined Values File</a></h2><p>Take a look at Listing 4.6, in which we declare our constant array of characters   <tt>alpha</tt><i>.</i></p><h4> Listing 4.6 definedValues.h</h4><pre><tt>0:  #ifndef DEFINED_VALUES</tt><tt>1:  #define DEFINED_VALUES</tt><tt>2:  </tt><tt>3:  #include &lt;iostream&gt;</tt><tt>4:  using namespace std;</tt><tt>5:  </tt><tt>6:  const char alpha[] = "abcdefghijklmnopqrstuvwxyz";</tt><tt>7:  </tt><tt>8:  const int minPos = 2;</tt><tt>9:  const int maxPos = 10;</tt><tt>10:  const int minLetters = 2;</tt><tt>11:  const int maxLetters = 26;</tt><tt>12:  </tt><tt>13:  #endif</tt></pre><p>This listing introduces several new elements.On line 0 you see the precompiler   directive <tt>#ifndef</tt>. This is read "if not defined," and it checks to   see whether you've already defined whatever follows (in this case, the string   <tt>DEFINED_VALUES</tt>). </p><p>If this test fails (if the value <tt>DEFINED_VALUES</tt> is already defined),   nothing is processed until the next <tt>#endif</tt> statement, on line 13. Thus,   the entire body of this file is skipped if <tt>DEFINED_VALUES</tt> is already   defined.</p><p>If this is the first time the precompiler reads this file, that value will   not yet be defined; processing will continue on line 2, at which point it will   be defined. Thus, the net effect is that this file is processed exactly once. </p><p>The <tt>#ifndef/#define</tt> combination is called an <i>inclusion guard</i>,   and it guards against multiple inclusions of the same header file throughout   your program. Every header file needs to be guarded in this way.</p><blockquote>  <hr>  <p><strong>NOTE: </strong> <i>Inclusion guards</i> are added to header files     to ensure that they are included in the program only once.</p>  <hr></blockquote><p>We intend to include the definedValues.h header file into all our other files   so that it constitutes a global set of definitions and declarations. By including,   for example, iostream.h here, we don't need to include it elsewhere in the program.</p><p>On line 6 you declare the constant character array that was discussed earlier.   On lines 8-11 you declare a number of other constant values that will be available   throughout the program. </p><CENTER><P><HR>  <A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR>  <BR><p></P><P>&#169; <A HREF="../copy.htm">Copyright 1999</A>, Macmillan Computer Publishing. Allrights reserved.</p></CENTER></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -