1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
|
<chapter title="Control Structures">
<p>In this chapter all the control structures in Pike will be
explained. Control structures are used to control the flow of the
program execution. Note that functions that make the program pause and
simple function calls are not qualified as control structures.</p>
<section title="Conditions">
<p>Conditions are control structures that, given a test condition
selects what code to be executed. These range from the binary "execute
or not" to a large table of code where the selection of which code to
run is based on an input parameter.</p>
<subsection title="if">
<p>The simplest one is called the <b>if statement</b>. It can be
written anywhere where a statement is expected and it looks like
this:</p>
<example>
if( expression )
statement1;
else
statement2;
</example>
<p>Please note that there is no semicolon after the parenthesis or after the
<tt>else</tt>. Step by step, <tt>if</tt> does the following:</p>
<ol>
<li>First it evaluates <i>expression</i>.</li>
<li>If the result was <b>false</b> go to point 5.</li>
<li>Execute <i>statement1</i>.</li>
<li>Jump to point 6.</li>
<li>Execute <i>statement2</i>.</li>
<li>Done.</li>
</ol>
<p>This is actually more or less how the interpreter executes the if statement.
In short, <i>statement1</i> is executed if <i>expression</i> is <b>true</b>
otherwise <i>statement2</i> is executed. If you are not interested in
having something executed if the expression is false you can drop the
whole else part like this:</p>
<example>
if( expression )
statement1;
</example>
<p>If on the other hand you are not interested in evaluating something
if the expression is <b>false</b> you should use the <b>not</b>
operator to negate the true/false value of the expression. See
<fixme>chapter</fixme> for more information about the <b>not</b>
operator. It would look like this:</p>
<example>
if( ! expression )
statement2;
</example>
<p>Any of the statements here and in the rest of this chapter can
also be a <b>block</b> of statements. A block is a list of statements,
separated by semicolons and enclosed by brackets. Note that you should
never put a semicolon after a block of statements. The example above
would look like this;</p>
<example>
if ( ! expression )
{
statement;
statement;
statement;
}
</example>
<p>It is also possible to place several if statements in sequence, so
that if the first expression is false it continues with the next one
and the next one until the first true expression is found.</p>
<example>
if ( expression1 )
statement1;
else if ( expression2 )
statement2;
else if ( expression3 )
statement3;
else
statement4;
</example>
<p>A special case of the above example is when in every expression you
compare one variable with different values. For those applications the
switch statement described below can be used instead to increas
performance and simplify the code.</p>
</subsection>
<subsection title="switch">
<p>A more sophisticated condition control structure is the <b>switch
statement</b>. A switch lets you select one of many choices depending
on the value of an expression and it can look something like this:</p>
<example>
switch ( expression )
{
case constant1:
statement1;
break;
case constant2:
statement2;
break;
case constant3 .. constant4:
statement3;
break;
default:
statement5;
}
</example>
<p>As you can see, a switch statement is a bit more complicated than an
if statement. It is still fairly simple however. It starts by evaluating
the expression it then searches all the <tt>case</tt> statements in the
following block. If one is found to be equal to the value returned by
the expression, Pike will continue executing the code directly following
that <tt>case</tt> statement. When a <tt>break</tt> is encountered Pike
will skip the rest of the code in the switch block and continue executing
after the block. Note that it is not strictly necessary to have a break
before the next case statement. If there is no break before the next case
statement Pike will simply continue executing and execute the code after
that case statement as well.</p>
<p>One of the case statements in the above example differs in that it is
a <b>range</b>. In this case, any value between <i>constant3</i> and
<i>constant4</i> will cause Pike to jump to <i>statement3</i>. Note
that the ranges are inclusive, so the values <i>constant3</i> and
<i>constant4</i> are also valid.</p>
</subsection>
</section>
<section title="Loops">
<p>Loops are used to execute a piece of code more than once. Since this can
be done in quite a few different ways there are four different loop
control structures. They may all seem very similar, but using the right
one at the right time makes the code a lot shorter and simpler.</p>
<subsection title="while">
<p><tt>While</tt> is the simplest of the loop control structures. It looks
just like an <tt>if</tt> statement without the else part:</p>
<example>
while ( expression )
statement;
</example>
<p>The difference in how it works isn't that big either, the statement is
executed if the expression is true. Then the expression is evaluated
again, and if it is true the statement is executed again. Then it
evaluates the expression again and so forth... Here is an example of
how it could be used:</p>
<example>
int e=1;
while(e<5)
{
show_record(e);
e=e+1;
}
</example>
<p>This would call show_record with the values 1, 2, 3 and 4.</p>
</subsection>
<subsection title="for">
<p><tt>For</tt> is simply an extension of <tt>while</tt>. It provides an
even shorter and more compact way of writing loops. The syntax looks
like this:</p>
<example>
for ( initializer_statement ; expression ; incrementor_expression )
statement ;
</example>
<p>For does the following steps:</p>
<ol>
<li> Executes the the <i>initializer_statement</i>. The initializer statement
is executed only once and is most commonly used to initialize the loop
variable.</li>
<li> Evaluates <i>expression</i></li>
<li> If the result was false it exits the loop and continues with the
program after the loop.</li>
<li> Executes <i>statement</i>.</li>
<li> Executes the <i>increment_expression</i>.</li>
<li> Starts over from 2.</li>
</ol>
<p>This means that the example in the while section can be written like this:</p>
<example>
for(int e=1; e<5; e=e+1)
show_record(e);
</example>
</subsection>
<subsection title="do-while">
<p>Sometimes it is unpractical that the expression is always evaluated before
the first time the loop is executed. Quite often you want to execute
something, and then do it over and over until some condition is satisfied.
This is exactly when you should use the do-while statement.</p>
<example>
do
statement;
while ( expression );
</example>
<p>As usual, the <i>statement</i> can also be a block of statements, and then
you do not need a semicolon after it. To clarify, this statement executes
<i>statement</i> first, and then evaluates the <i>expression</i>. If the
expression is <b>true</b> it executes the loop again. For instance, if you
want to make a program that lets your modem dial your Internet provider,
it could look something like this:</p>
<!-- Can someone come up with a better example? -->
<example>
do {
modem->write("ATDT441-9109\n"); // Dial 441-9109
} while(modem->gets()[..6]] != "CONNECT");
</example>
<p>This example assumes you have written something that can communicate with
the modem by using the functions <tt>write</tt> and <tt>gets</tt>.</p>
</subsection>
<subsection title="foreach">
<p><tt>Foreach</tt> is unique in that it does not have an explicit test expression
evaluated for each iteration in the loop. Instead, <tt>foreach</tt> executes
the statement once for each element in a set. <tt>Foreach</tt> has two
syntaxes, the first of which look like this:</p>
<example>
foreach ( array_expression, variable )
statement;
</example>
<p>We have already seen an example of <tt>foreach</tt> in the <tt>find_song</tt>
function in chapter 2. What foreach does is:</p>
<ol>
<li> It evaluates the <i>array_expression</i> which must return an array.</li>
<li> If the array is empty, exit the loop.</li>
<li> It then assigns the first element from the array to the <i>variable</i>.</li>
<li> Then it executes the <i>statement</i>.</li>
<li> If there are more elements in the array, the next one is assigned to
the <i>variable</i>, otherwise exit the loop.</li>
<li> Go to point 4.</li>
</ol>
<p><tt>Foreach</tt> is not really necessary, but it is faster and clearer than
doing the same thing with a <tt>for</tt> loop, as shown here:</p>
<example>
array tmp1 = array_expression;
for ( tmp2 = 0; tmp2 < sizeof(tmp1); tmp2++ )
{
variable = tmp1 [ tmp2 ];
statement;
}
</example>
<p>The second syntax for <tt>foreach</tt> is the more flexible iterator syntax,
which can be used to iterate over arrays, mappings, multisets and strings as
well as some objects. It also has the option of providing the index value:</p>
<example>
foreach ( iterable_expression; optional_index_variable; optional_value_variable )
statement;
</example>
<p>This is approximately equivalent to:</p>
<example>
for (Iterator iter = get_iterator(iterable_expression); iter; iter->next()) {
optional_index_variable = iter->index();
optional_value_variable = iter->value();
statement;
}
</example>
<p>See <ref>get_iterator()</ref> for further details.</p>
</subsection>
</section>
<section title="Breaking out of loops">
<p>The loop control structures above are enough to solve any problem, but
they are not enough to provide an easy solution to all problems. One thing
that is still missing is the ability to exit a loop in the middle of it.
There are three ways to do this:</p>
<subsection title="break">
<p><tt>break</tt> exits a loop, switch, or catch statement immediately and continues
executing after the loop. <tt>Break</tt> can not be used outside of one of these.
It is quite useful in conjunction with <tt>while(1)</tt> to
construct command parsing loops for instance:</p>
<example>
while(1)
{
string command=Stdio.Readline()->read("> ");
if(command=="quit") break;
do_command(command);
}
</example>
<p>When you want to break out of more than the innermost loop, you can tell
<tt>break</tt> what loop to break free of using lables, as in:</p>
<example>
array arr1, arr2;
while(1)
{
// ...
a:if(sizeof(arr1) >= sizeof(arr2))
{
int i = sizeof(b), j = sizeof(yb);
while(i)
if(b[--i] != yb[--j])
break a;
// the code here is only run when arr1
// and arr2 share some common suffix
}
// execution continues here
}
</example>
<p>Inside a <tt>catch</tt> block, <tt>break</tt> will terminate the block with no
exception being thrown; <tt>catch</tt> will return zero, as if execution had
continued to the end of the block.</p>
</subsection>
<subsection title="continue">
<p><tt>Continue</tt> does almost the same thing as <tt>break</tt>, except instead of
breaking out of the loop it only breaks out of the loop body. It then continues
to execute the next iteration in the loop. For a <tt>while</tt> loop, this
means it jumps up to the top again. For a <tt>for</tt> loop, it jumps to the
incrementor expression. For a <tt>do-while</tt> loop it jumps down to the
expression at the end. To continue our example above, <tt>continue</tt> can be used
like this:</p>
<example>
while(1)
{
string command=Stdio.Readline()->read("> ");
if(strlen(command) == 0) continue;
if(command=="quit") break;
do_command(command);
}
</example>
<p>This way, <tt>do_command</tt> will never be called with an empty string as
argument.</p>
</subsection>
<subsection title="return">
<p><tt>Return</tt> doesn't just exit the loop, it exits the whole function. We have seen
several examples how to use it chapter 2. None of the functions in chapter
two returned anything in particular however. To do that you just put the return
value right after <tt>return</tt>. Of course the type of the return value
must match the type in the function declaration. If your function declaration
is <tt>int main()</tt> the value after <tt>return</tt> must be an <b>int</b>.
For instance, if we wanted to make a program that always returns an error
code to the system, just like the UNIX command <tt>false</tt> this is how
it would be done:</p>
<example>
#!/usr/local/bin/pike
int main()
{
return 1;
}
</example>
<p>This would return the error code <tt>1</tt> to the system when the program
is run.</p>
</subsection>
</section>
</chapter>
|