* remove "\r" nonsense
[mascara-docs.git] / C / the.ansi.c.programming.language / notes.accompany.ansi.c / sx6e.html
blob4d88c5d10f16a6bbce611d3df2577035ad31939f
1 <!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
2 <!-- This collection of hypertext pages is Copyright 1995, 1996 by Steve Summit. -->
3 <!-- This material may be freely redistributed and used -->
4 <!-- but may not be republished or sold without permission. -->
5 <html>
6 <head>
7 <link rev="owner" href="mailto:scs@eskimo.com">
8 <link rev="made" href="mailto:scs@eskimo.com">
9 <title>section 3.5: Loops -- While and For</title>
10 <link href="sx6d.html" rev=precedes>
11 <link href="sx6f.html" rel=precedes>
12 <link href="sx6.html" rev=subdocument>
13 </head>
14 <body>
15 <H2>section 3.5: Loops -- While and For</H2>
17 <p>page 60
18 </p><p>Remember that,
19 as always,
20 the <I>statement</I> can be a brace-enclosed block.
21 </p><p>Make sure you understand how the <TT>for</TT> loop
22 <pre> for (<I>expr</I><tt>&lt;sub&gt;</tt>1<tt>&lt;/sub&gt;</tt>; <I>expr</I><tt>&lt;sub&gt;</tt>2<tt>&lt;/sub&gt;</tt>; <I>expr</I><tt>&lt;sub&gt;</tt>3<tt>&lt;/sub&gt;</tt>)
23 <I>statement</I>
24 </pre>is equivalent to the while loop
25 <pre> <I>expr</I><tt>&lt;sub&gt;</tt>1<tt>&lt;/sub&gt;</tt>;
26 while (<I>expr</I><tt>&lt;sub&gt;</tt>2<tt>&lt;/sub&gt;</tt>) {
27 <I>statement</I>
28 <I>expr</I><tt>&lt;sub&gt;</tt>3<tt>&lt;/sub&gt;</tt> ;
30 </pre>There is nothing magical
31 about the three expressions at the top of a <TT>for</TT> loop;
32 they can be arbitrary expressions,
33 and they're evaluated just as the expansion into the equivalent
34 <TT>while</TT> loop would suggest.
35 (Actually, there are two tiny differences:
36 the behavior of <TT>continue</TT>,
37 which we'll get to in a bit,
38 and the fact that the test expression, <I>expr</I><tt>&lt;sub&gt;</tt>2<tt>&lt;/sub&gt;</tt>,
39 is optional and defaults to ``true'' for a <TT>for</TT> loop,
40 but is required for a <TT>while</TT> loop.)
41 </p><p><TT>for(;;)</TT> is one way of writing an infinite loop in C;
42 the other common one is <TT>while(1)</TT>.
43 Don't worry about what a <TT>break</TT> would mean in a loop,
44 we'll be seeing it in a few more pages.
45 </p><p>pages 60-61
46 </p><p>Deep sentences:
47 <blockquote>Whether to use <TT>while</TT> or <TT>for</TT>
48 is largely a matter of personal preference...
49 <br>Nonetheless,
50 it is bad style to force unrelated computations
51 into the initialization and increment of a <TT>for</TT>,
52 which are better reserved for loop control operations.
53 </blockquote>In general,
54 the three expressions in a <TT>for</TT> loop should all
55 manipulate (initialize, test, and increment)
56 the same variable or data structure.
57 If they don't,
58 they are ``unrelated computations,''
59 and a <TT>while</TT> loop would probably be clearer.
60 (The reason that one loop or the other can be clearer is simply that,
61 when you see a <TT>for</TT> loop,
62 you <em>expect</em> to see an idiomatic
63 initialize/test/increment of a single variable or data structure,
64 and if the <TT>for</TT> loop you're looking at
65 doesn't end up matching that pattern,
66 you've been momentarily misled.)
67 </p><p>page 61
68 </p><p>When the authors
69 say that ``the index and limit of a C <TT>for</TT> loop
70 can be altered from within the loop,''
71 they mean that a loop like
72 <pre> int i, n = 10;
73 for(i = 0; i &lt; n; i++) {
74 if(i == 5)
75 i++;
76 printf("%d\n", i);
77 if(i == 8)
78 n++;
80 </pre>where <TT>i</TT> and <TT>n</TT> are modified within the loop,
81 is legal.
82 (Obviously, such a loop can be very confusing,
83 so you'll probably be better off not making use of this freedom too much.)
84 </p><p>When they say that
85 ``the index variable... retains its value when the loop
86 terminates for any reason,''
87 you may not find this too surprising,
88 unless you've used other languages where it's <em>not</em> the case.
89 The fact that loop control variables retain their values after a loop
90 can make some code
91 much easier to write;
92 for example,
93 the <TT>atoi</TT> function at the bottom of this page
94 depends on having its <TT>i</TT> counter manipulated by several loops
95 as it steps over three different parts of the string
96 (whitespace, sign, digits)
97 with <TT>i</TT>'s value preserved between each step.
98 </p><p>Deep sentence:
99 <blockquote>Each step does its part,
100 and leaves things in a clean state for the next.
101 </blockquote>This is an extremely important observation on how to write
102 clean code.
103 As you
104 study
105 the <TT>atoi</TT> code,
106 notice that
107 it falls into three parts,
108 each implementing one step of the pseudocode description:
109 <I>skip white space</I>,
110 <I>get sign</I>,
111 <I>get integer part and convert it</I>.
112 At each step, <TT>i</TT> points at the next character which
113 that step is to inspect.
114 (If a step is skipped,
115 because there is no leading whitespace or no sign,
116 the later steps don't care.)
118 </p><p>You may hear the term <dfn>invariant</dfn> used:
119 this
121 refers to some condition which exists at all stages of a
122 program or function.
123 In this case,
124 the invariant is that <TT>i</TT> always points
125 to the next character to be inspected.
126 Having
127 some well-chosen invariants can make code <em>much</em>
128 easier to write and maintain.
129 If there aren't enough invariants--if
130 <TT>i</TT> is sometimes the next character to look at
131 and sometimes the character
132 that was just looked
133 at--debugging and maintaining the code can be a nightmare.
134 </p><p>In the <TT>atoi</TT> example,
135 the lines
136 <pre> for (i = 0; isspace(s[i]); i++) /* skip white space */
138 </pre>are about at the brink of
139 ``forcing unrelated computations into the initialization and increment,''
140 especially since so much has been forced into the loop header
141 that there's nothing left in the body.
142 It would be equally clear to write this part as
143 <pre> i = 0;
144 while (isspace(s[i]))
145 i++; /* skip white space */
146 </pre></p><p>The line
147 <pre> sign = (s[i] == '-') ? -1 : 1;
148 </pre>may seem a bit cryptic at first,
149 though it's a textbook example of the use of <TT>?:</TT>
151 The line is equivalent to
152 <pre> sign = 1;
153 if(s[i] == '-')
154 sign = -1;
155 </pre></p><p>pages 61-62
156 </p><p>It's instructive to study this Shell or ``gap'' sort,
157 but don't worry if you find it a bit bewildering.
158 </p><p>Deep sentence:
159 <blockquote>Notice how the generality of <TT>for</TT>
160 makes the outer loop fit the same form as the others,
161 even though it is not an arithmetic progression.
162 </blockquote>The point is that loops don't have to count 0, 1, 2... or 1, 2, 3... .
163 (This one counts <TT>n/2</TT>, <TT>n/4</TT>, <TT>n/8</TT>... .
164 Later we'll see loops which don't step over numbers at all.)
165 </p><p>page 63
166 </p><p>Deep sentence:
167 <blockquote>The commas that separate function arguments,
168 variables in declarations, etc. are
169 <em>not</em> comma operators...
170 </blockquote>This looks strange,
171 but it's true.
172 If you say
173 <pre> for (i = 0, j = strlen(s)-1; i &lt; j; i++, j--)
174 </pre>the first comma says to do <TT>i = 0</TT> <em>then</em>
175 do <TT>j = strlen(s)-1</TT>,
177 the second comma says to do <TT>i++</TT> <em>then</em> do <TT>j--</TT>.
178 However,
179 when you say
180 <pre> getline(line, MAXLINE);
181 </pre>the comma just separates the two arguments <TT>line</TT> and <TT>MAXLINE</TT>;
182 they both have to be evaluated, but it doesn't matter in which order,
183 and they're both passed to <TT>getline</TT>.
184 (If the comma in a function call were interpreted as a comma operator,
185 the function would only receive one argument,
186 since the value of the first operand of the comma operator is
187 discarded.)
189 Since the comma operator discards the value of its first operand,
190 its first operand had better have a side effect.
191 The expression
192 <pre> ++a,++b
193 </pre>increments <TT>a</TT> and increments <TT>b</TT> and
194 (if anyone cares)
195 returns <TT>b</TT>'s value,
196 but the expression
197 <pre> a+1,b+1
198 </pre>adds 1 to <TT>a</TT>, discards it,
199 and returns <TT>b+1</TT>.
200 </p><p>If the comma operator isn't making perfect sense,
201 don't worry about it for now.
202 You're most likely to see it in the first or third expression
203 of a <TT>for</TT> statement, where it has the obvious meaning of
204 separating two
205 (or more)
206 things to do during the initialization or increment step.
207 Just
208 be careful that you don't accidentally write things like
209 <pre> for(i = 0; j = 0; i &lt; n &amp;&amp; j &lt; j; i++; j++) /* WRONG */
210 </pre>or
211 <pre> for(i = 0, j = 0, i &lt; n &amp;&amp; j &lt; j, i++, j++) /* WRONG */
212 </pre>The correct form of a multi-index loop is something like
213 <pre> for(i = 0, j = 0; i &lt; n &amp;&amp; j &lt; j; i++, j++)
214 </pre>Semicolons always separate the initialization, test, and increment parts;
215 commas may appear <em>within</em> the initialization and increment parts.
216 </p><hr>
218 Read sequentially:
219 <a href="sx6d.html" rev=precedes>prev</a>
220 <a href="sx6f.html" rel=precedes>next</a>
221 <a href="sx6.html" rev=subdocument>up</a>
222 <a href="top.html">top</a>
223 </p>
225 This page by <a href="http://www.eskimo.com/~scs/">Steve Summit</a>
226 // <a href="copyright.html">Copyright</a> 1995, 1996
227 // <a href="mailto:scs@eskimo.com">mail feedback</a>
228 </p>
229 </body>
230 </html>