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

📄 chapter3.html

📁 Kernighan and Ritchie - The C Programming Language c程序设计语言(第二版)称作是C语言学习的圣经
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html><head><title>Chapter 3 - Control Flow</title></head><body><hr><p align="center"><a href="chapter2.html">Back to Chapter 2</a>&nbsp;--&nbsp;<a href="kandr.html">Index</a>&nbsp;--&nbsp;<a href="chapter4.html">Chapter 4</a><p><hr><h1>Chapter 3 - Control Flow</h1>The control-flow of a language specify the order in which computations areperformed. We have already met the most common control-flow constructions inearlier examples; here we will complete the set, and be more precise aboutthe ones discussed before.<h2><a name="s3.1">3.1 Statements and Blocks</a></h2>An expression such as <tt>x = 0</tt> or <tt>i++</tt> or <tt>printf(...)</tt>becomes a <em>statement</em> when it is followed by a semicolon, as in<pre>   x = 0;   i++;   printf(...);</pre>In C, the semicolon is a statement terminator, rather than a separator as itis in languages like Pascal.<p>Braces <tt>{</tt> and <tt>}</tt> are used to group declarations and statementstogether into a <em>compound statement</em>, or <em>block</em>, so that theyare syntactically equivalent to a single statement. The braces that surroundthe statements of a function are one obvious example; braces around multiplestatements after an <tt>if</tt>, <tt>else</tt>, <tt>while</tt>, or <tt>for</tt>are another. (Variables can be declared inside <em>any</em> block; we willtalk about this in <a href="chapter4.html">Chapter 4</a>.) There is no semicolonafter the right brace that ends a block.<h2><a name="s3.2">3.2 If-Else</a></h2>The <tt>if-else</tt> statement is used to express decisions. Formally the syntaxis<pre>   if (<em>expression</em>)       <em>statement<sub>1</sub></em>   else       <em>statement<sub>2</sub></em></pre>where the <tt>else</tt> part is optional. The <em>expression</em> is evaluated;if it is true (that is, if <em>expression</em> has a non-zero value),<em>statement<sub>1</sub></em> is executed. If it is false (<em>expression</em>is zero) and if there is an <tt>else</tt> part, <em>statement<sub>2</sub></em>is executed instead.<p>Since an <tt>if</tt> tests the numeric value of an expression, certain codingshortcuts are possible. The most obvious is writing<pre>   if (<em>expression</em>)</pre>instead of<pre>   if (<em>expression</em> != 0)</pre>Sometimes this is natural and clear; at other times it can be cryptic.<p>Because the <tt>else</tt> part of an <tt>if-else</tt> is optional,there is anambiguity when an else if omitted from a nested <tt>if</tt> sequence. This isresolved by associating the <tt>else</tt> with the closest previous<tt>else</tt>-less <tt>if</tt>. For example, in<pre>   if (n &gt; 0)       if (a &gt; b)           z = a;       else           z = b;</pre>the <tt>else</tt> goes to the inner <tt>if</tt>, as we have shown by indentation.If that isn't what you want, braces must be used to force the properassociation:<pre>   if (n &gt; 0) {       if (a &gt; b)            z = a;   }   else       z = b;</pre>The ambiguity is especially pernicious in situations like this:<pre>   if (n &gt; 0)       for (i = 0; i &lt; n; i++)           if (s[i] &gt; 0) {               printf("...");               return i;           }   else        /* WRONG */       printf("error -- n is negative\n");</pre>The indentation shows unequivocally what you want, but the compiler doesn'tget the message, and associates the <tt>else</tt> with the inner <tt>if</tt>.This kind of bug can be hard to find; it's a good idea to use braces whenthere are nested <tt>if</tt>s.<p>By the way, notice that there is a semicolon after <tt>z = a</tt> in<pre>   if (a &gt; b)       z = a;   else       z = b;</pre>This is because grammatically, a <em>statement</em> follows the <tt>if</tt>,and an expression statement like ``<tt>z = a;</tt>'' is always terminated by asemicolon.<h2><a name="s3.3">3.3 Else-If</a></h2>The construction<pre>   if (<em>expression</em>)       <em>statement</em>   else if (<em>expression</em>)       <em>statement</em>   else if (<em>expression</em>)       <em>statement</em>   else if (<em>expression</em>)       <em>statement</em>   else       <em>statement</em></pre>occurs so often that it is worth a brief separate discussion. This sequenceof <tt>if</tt> statements is the most general way of writing a multi-waydecision. The <em>expressions</em> are evaluated in order; if an<em>expression</em> is true, the <em>statement</em> associated with it isexecuted, and this terminates the whole chain. As always, the code for each<em>statement</em> is either a single statement, or a group of them in braces.<p>The last <tt>else</tt> part handles the ``none of the above'' or default casewhere none of the other conditions is satisfied. Sometimes there is noexplicit action for the default; in that case the trailing<pre>   else       <em>statement</em></pre>can be omitted, or it may be used for error checking to catch an``impossible'' condition.<p>To illustrate a three-way decision, here is a binary search function thatdecides if a particular value <tt>x</tt> occurs in the sorted array <tt>v</tt>.The elements of <tt>v</tt> must be in increasing order. The function returns theposition (a number between 0 and <tt>n-1</tt>) if <tt>x</tt> occurs in <tt>v</tt>,and -1 if not.<p>Binary search first compares the input value <tt>x</tt> to the middle elementof the array <tt>v</tt>. If <tt>x</tt> is less than the middle value, searchingfocuses on the lower half of the table, otherwise on the upper half. Ineither case, the next step is to compare <tt>x</tt> to the middle element of theselected half. This process of dividing the range in two continues until thevalue is found or the range is empty.<pre>   /* binsearch:  find x in v[0] &lt;= v[1] &lt;= ... &lt;= v[n-1] */   int binsearch(int x, int v[], int n)   {       int low, high, mid;       low = 0;       high = n - 1;       while (low &lt;= high) {           mid = (low+high)/2;           if (x &lt; v[mid])               high = mid + 1;           else if (x  &gt; v[mid])               low = mid + 1;           else    /* found match */               return mid;       }       return -1;   /* no match */   }</pre>The fundamental decision is whether <tt>x</tt> is less than, greater than, orequal to the middle element <tt>v[mid]</tt> at each step; this is a naturalfor <tt>else-if</tt>.<p><strong>Exercise 3-1.</strong> Our binary search makes two tests inside theloop, when one would suffice (at the price of more tests outside.) Write aversion with only one test inside the loop and measure the difference inrun-time.<h2><a name="s3.4">3.4 Switch</a></h2>The <tt>switch</tt> statement is a multi-way decision that tests whether anexpression matches one of a number of <em>constant</em> integer values, andbranches accordingly.<pre>   switch (<em>expression</em>) {       case <em>const-expr</em>: <em>statements</em>       case <em>const-expr</em>: <em>statements</em>       default: <em>statements</em>   }</pre>Each case is labeled by one or more integer-valued constants or constantexpressions. If a case matches the expression value, execution starts at thatcase. All case expressions must be different. The case labeled <tt>default</tt>is executed if none of the other cases are satisfied. A <tt>default</tt> isoptional; if it isn't there and if none of the cases match, no action at alltakes place. Cases and the default clause can occur in any order.<p>In <a href="chapter1.html">Chapter 1</a> we wrote a program to count the occurrencesof each digit, white space, and all other characters, using a sequence of<tt>if ... else if ... else</tt>. Here is the same program with a <tt>switch</tt>:<pre>   #include &lt;stdio.h&gt;   main()  /* count digits, white space, others */   {       int c, i, nwhite, nother, ndigit[10];       nwhite = nother = 0;       for (i = 0; i &lt; 10; i++)           ndigit[i] = 0;       while ((c = getchar()) != EOF) {           switch (c) {           case '0': case '1': case '2': case '3': case '4':           case '5': case '6': case '7': case '8': case '9':               ndigit[c-'0']++;               break;           case ' ':           case '\n':           case '\t':               nwhite++;               break;           default:               nother++;               break;           }       }       printf("digits =");       for (i = 0; i &lt; 10; i++)           printf(" %d", ndigit[i]);       printf(", white space = %d, other = %d\n",           nwhite, nother);       return 0;   }</pre>The <tt>break</tt> statement causes an immediate exit from the <tt>switch</tt>.Because cases serve just as labels, after the code for one case is done,execution <em>falls through</em> to the next unless you take explicit action toescape. <tt>break</tt> and <tt>return</tt> are the most common ways to leave a<tt>switch</tt>. A <tt>break</tt> statement can also be used to force an immediateexit from <tt>while</tt>, <tt>for</tt>, and <tt>do</tt> loops, as will bediscussed later in this chapter.<p>Falling through cases is a mixed blessing. On the positive side, it allowsseveral cases to be attached to a single action, as with the digits in thisexample. But it also implies that normally each case must end with a <tt>break</tt>to prevent falling through to the next. Falling through from one caseto another is not robust, being prone to disintegration when the program ismodified. With the exception of multiple labels for a single computation,fall-throughs should be used sparingly, and commented.<p>As a matter of good form, put a <tt>break</tt> after the last case (the<tt>default</tt> here) even though it's logically unnecessary. Some day whenanother case gets added at the end, this bit of defensive programming willsave you.<p><strong>Exercise 3-2.</strong> Write a function <tt>escape(s,t)</tt> thatconverts characters like newline and tab into visible escape sequences like<tt>\n</tt> and <tt>\t</tt> as it copies the string <tt>t</tt> to <tt>s</tt>.Use a <tt>switch</tt>. Write a function for the other direction as well,converting escape sequences into the real characters.<h2><a name="s3.5">3.5 Loops - While and For</a></h2>We have already encountered the <tt>while</tt> and <tt>for</tt> loops. In<pre>   while (<em>expression</em>)       <em>statement</em></pre>the <em>expression</em> is evaluated. If it is non-zero, <em>statement</em>is executed and <em>expression</em> is re-evaluated. This cycle continuesuntil <em>expression</em> becomes zero, at which point execution resumesafter <em>statement</em>.<p>The <tt>for</tt> statement<pre>   for (<em>expr<sub>1</sub></em>; <em>expr<sub>2</sub></em>; <em>expr<sub>3</sub></em>)       <em>statement</em></pre>is equivalent to<pre>   <em>expr<sub>1</sub></em>;   while (<em>expr<sub>2</sub></em>) {       <em>statement</em>       <em>expr<sub>3</sub></em>;   }</pre>except for the behaviour of <tt>continue</tt>, which is described in<a href="#s3.7">Section 3.7</a>.<p>Grammatically, the three components of a <tt>for</tt> loop are expressions. Mostcommonly, <em>expr<sub>1</sub></em> and <em>expr<sub>3</sub></em> are assignments or functioncalls and <em>expr<sub>2</sub></em> is a relational expression. Any of the three partscan be omitted, although the semicolons must remain. If <em>expr<sub>1</sub></em> or<em>expr<sub>3</sub></em> is omitted, it is simply dropped from the expansion. If thetest, <em>expr<sub>2</sub></em>, is not present, it is taken as permanently true, so<pre>   for (;;) {       ...   }</pre>is an ``infinite'' loop, presumably to be broken by other means, such as a<tt>break</tt> or <tt>return</tt>.<p>Whether to use <tt>while</tt> or <tt>for</tt> is largely a matter of personalpreference. For example, in<pre>   while ((c = getchar()) == ' ' || c == '\n' || c = '\t')       ;   /* skip white space characters */</pre>there is no initialization or re-initialization, so the <tt>while</tt> is mostnatural.<p>

⌨️ 快捷键说明

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