U 7: Iteration: 1.1 While S
U 7: Iteration: 1.1 While S
U 7: Iteration: 1.1 While S
CPS 196
Page 1
UNIT 7: ITERATION
We cover iteration in C using the while, do and for statements. Along the way, we discuss the preincrement (++<expr>), pre-decrement (--<expr>) and assignment operators +=, -=, *=, /= and %=.
1.
How would you print out a form with 50 dashed lines? How about 200? 1000? It would be very tedious to code 50, 200 or 1000 separate printf calls. All programming languages provide a way to repeat (or iterate, or loop) the execution of a statement. C provides three looping constructs: the while, do and for statements.
1.1
a) b)
while STATEMENTS
Similar to the while statements of many other programming languages. General Format of the while statement: while ( <boolean-expr> ) <boolean-expr> called [loop] condition or continuation condition <statement> [loop] body -- just a statement (perhaps a compound statement)
c)
d) e) f) g) h)
When a while statement is executed, the loop condition is evaluated first; if it's false, the loop body is not executed; otherwise, [re-]execution of the loop body and re-evaluation of the loop condition are repeated (in that order) until the first time the condition evaluates to false, which terminates execution of the while statement. Note that the loop body may not be executed at all. The loop body must therefore have the potential to falsify the loop conditionthis is the case for all loop statements (unless an "infinite loop" is desired). <statement> (loop body) can be, or include, a looping statement (in which case, we speak of a nested loop). To effect an infinite loop with a while statement, use the following idiom: while ( 1 ) <statement> C99 coders use this idiom instead (assumes stdbool.h is #included): while ( true ) <statement> Here's a classic C idiom used for repeatedly calling a function until its return value satisfies some relation: while ( ([<variable> = ]<func-name>( <arguments> )) <relop> <terminating-value> ) <statement>
i)
Examples (both employ the immediately preceding looping idiom): /* ** cat.c - copy standard input (keyboard) to standard output (screen). */ #include <stdio.h> int main( void ) { int c; /* for decl. of getchar and putchar, defn. of EOF */
type of c is int, not char, conforming to return type of the getchar function to terminate at keyboard: enter Ctrl-Z (WINDOWS) (getchar returns code of next std. input character or EOF macro value at End-Of-File; putchar writes character with code c to std. output and returns c unless error occurs, in which case it returns EOF)
--------------------------------------------------------------------------printf( "Enter age: " ); while ( scanf( "%i", &k ) == 1 ) to terminate at keyboard: enter Ctrl-Z (WINDOWS) { printf( "You don't look a day over %i!n\n", k/2 ); printf( "Enter age: " ); note repeated prompt (is it avoidable?) }
UNIT 7
CPS 196
Page 2
1.2
a) b)
do STATEMENTS
Least commonly used C looping statement. General Format of the do statement: do <statement> [loop] body; for readability, make this a compound statement while ( <boolean-expr> );
c) d) e) f)
When a do statement is executed, the loop body ( <statement>) is executed first; then, [re-]evaluation of the loop condition and re-execution of the loop body are repeated (in that order) until the first time the condition evaluates to false. Note that the loop body must be executed at least once. The C do statement is not directly equivalent to the Pascal repeat...until, though it is easy to see that Cs do...while( !<cond> ); is equivalent to repeat...until <cond> in Pascal (if you know Pascal). <statement> (loop body) can be, or include, a looping statement (in which case, we speak of a nested loop) Example (how would you do the same thing using a for or while statement?): /* read & process characters up to (and including) first newline */ do { process( c = getchar() ); } while ( c != '\n' );
1.3
a) b)
for STATEMENTS
C's most powerful looping construct (more flexible than the Pascal/Basic for or FORTRAN do statement). General Format of the for statement: for ( [<init-expr>]; [<boolean-expr>]; [<update-expr>] ) the loop header <statement> the [loop] body
also, for C99 (and later): for ( <var-declaration> [<boolean-expr>]; [<update-expr>] ) the loop header <statement> the [loop] body c) d) e) None of the three expressions in the loop header of the first format is required (but both semi-colons are). As a variable declaration always ends with a semi-colon, the second format needs two semi-colons, too; the <var-declaration> of the second format is typically, as a practical matter, an initializing declaration. When a for statement is executed, the <init-expr> (or <var-declaration>) is evaluated first; often, this is used to assign values(s) to (or declare and initialize) one or more counter variables (which may keep count of the number of loop iterations, among other uses). The <boolean-expr> is then evaluated; if it's false, the loop body is not executed; otherwise, [re-]execution of the loop body, [re-]evaluation of the <update-expr> and re-evaluation of the <boolean-expr> are repeated (in that order) until the first time <boolean-expr> evaluates to false, which concludes execution of the for statement. The <update-expr> is often used to modify the value(s) of the counter variable(s). The <boolean-expr> often compares the value(s) of the counter variable(s) to some limit value(s). Loop body (<statement>) can be, or include, a looping statement (in which case, we speak of a nested loop). The loop header for (;;) is valid and provides another way to effect an infinite loop. Example: /* print out first 16 powers of 2; assumes int k already declared */ for ( k = 0; k < 16; k = k+1 ) printf( "2^%i = %i\n", k, (int)pow( 2.0, (double)k ) ); /* C99 only: print out first 16 powers of 2 */ for ( int k = 0; k < 16; k = k+1 ) printf( "2^%i = %i\n", k, (int)pow( 2.0, (double)k ) );
f) g) h) i) j)
UNIT 7
CPS 196
Page 3
1.4
Usually, the task at hand will suggest the most appropriate statement. Use the examples given in lectures and labs as a guide. Since any of the loop statement types (while, for and do) can simulate the others, it pays to use the type of statement that makes the mechanism by which the loop terminates (and counter variables, if any, are declared, initialized and updated) clearest. Some more specific guidelines follow. a) If a variable (e.g., a counter variable) is to be uniformly updated with each iteration, then the for statement is preferred (as counter maintenance can be conveniently placed in the for loop header, which streamlines the loop body). b) For loops without uniformly maintained counter variables or the like ( i.e., loops that can't take advantage of the for statement's header structure), use the while statement or the do statement. c) In cases where the loop body must first be executed in order to evaluate the loop condition, use the do statement.
2.
The operations of adding 1 to a variable and subtracting 1 from a variable are so often required that many machines have built-in CPU instructions that perform these operations. Most higher-level languages do not have such "increment" or "decrement" operators, but C does. It is also quite common for the RHS of an assignment expression to combine the LHS of the assignment expression and some other expression with an arithmetic operator. C's assignment operators provide a means of writing such assignment expressions in a more concise, readable and less error-prone way.
2.1
a) b) c) d) e) f) g)
/* print out first 16 powers of 2, using standard counter incr. method */ for ( k = 0; k < 16; ++k ) printf( "2^%i = %i\n", k, (int)pow( 2.0, (double)k ) );
2.2
a)
2.3
a) b)
ASSIGNMENT OPERATORS
Code like k = k <operator> <expression> appears often in programs (e.g., k = k+i, k = k-2, etc.). Assignment operators provide a shorthand for such code (N.B.: the parentheses below are significantthey prevent operator precedence problems): <lvalue> <operator>= <expression> is equivalent to <lvalue> = <lvalue> <operator> (<expression>)
c) d)
All arithmetic operators can be joined with = to form assignment operators (so can some other operators). Simple Examples: k += i; k *= i+j; k -= i/j; a_very_long_name /= 2; same as k = k+(i); (here, parentheses are superfluous) same as k = k*(i+j); (here, parentheses are required) same as k = k-(i/j); (here, parentheses are superfluous) same as a_very_long_name = a_very_long_name/(2);
UNIT 7
CPS 196
Page 4
Examples: #include <stdio.h> /* for printf function */ #include <math.h> /* for pow function */ ... /* print out first 16 powers of 2 */ for ( k = 0; k < 16; k += 1 ) printf( "2^%i = %i\n", k, (int)pow( 2.0, (double)k ) ); --------------------------------------------------------------------------/* "fast exponentiation" */ long long fast_pow( int b, unsigned e ) { long long r = 1LL; long long a = b; while ( e > 0 ) { if ( e % 2 ) r *= a; a *= a; e /= 2; } return r; }