Você está na página 1de 27

Do-while: Loops in C

Lecture-9

Administrative Matters

Advanced Track Results will be announced on Monday Mentoring Please email kvsingh@iitk.ac.in specifying language preferences.

Mentoring Program

Please make an appointment with your mentor before meeting with your mentor. Mentors are students like you (but senior), and have their own academics to take care of.

do-while loop
do-while statement is a variant of while. General form: Execution:

do statement while (expr);

1. 2.

3.
4.

First execute statement. Then evaluate expr. If expr is TRUE then go to step 1. If expr is FALSE then break from loop

statement

Continuation of loop is tested after the statement.

TRUE

expr ?

FALSE

Comparative Example-I

Problem: Read integers and output each integer until -1 is seen (include -1 in output). The program fragments using while and do-while.
Using do-while int a; /*current int*/ do { scanf(%d,&a); printf(%d ,a); } while (a != -1); Using while int a; /*current int*/ scanf(%d,&a); while (a != -1) { printf(%d ,a); scanf(%d,&a); } printf(%d , a);

The while construct and do-while are equally expressive (whatever one does, the other can too).
5

Programming Tip

If you are new to C, cultivate your loops programming using one of while or do-while. When you are comfortable with one of them, the other construct becomes easy.

int prev; int curr; int len; int maxlen; scanf(%d,&prev); maxlen = 1; len=1; if (!(prev == -1)) { do { scanf(%d,&curr); if (prev < curr) { len = len + 1; /*extend */ }else{ if (maxlen < len) { maxlen = len; } len = 1; } prev = curr; } while ( !(curr == -1)); } if (maxlen < len) { maxlen = len; }

Find length of longest increasing subsequence ending in -1, including -1 in sequence.

Problem 2

The first line of the input consists of two positive integers m and n. This line is followed by m lines, each containing n integers, signifying an m X n matrix A. We have to calculate the sum of the squares of the sum of numbers in each row and print it.

i(jAij)2
row i
3 4 4 7 11 2 11 2 4 2 9 0 -1 columns j e.g. A20 = 2, A12 = 2

, i=0..m-1, j =0..n-1.

Desired output (4+7+11+2)2 + (1+1+2+4)2 + (2+9+0+ (-1))2

Double loops

Need something of a double loop here (loop inside a loop). One loop to do the row sum of each row. Once a row is finished, we square the row sum. Another (outer) loop to add the squares of row sum over all rows that have been fully read.

Inner loop: Row sum

Easy part first: assume we are at the beginning of a row (have not read any numbers yet) and write a loop to calculate the row sum.

int a; /* the current integer */ int colindex; /* index of current column */ int rowsum; /* sum of row entries read so far */ int rowsumsq; /* square of the sum of row entries */ rowsum = 0; colindex=0; while (colindex < n) { /* not finished reading n cols*/ scanf(%d, &a); /* read next number */ rowsum = rowsum + a; /* add to rowsum */ colindex = colindex + 1; /* increment colindex */ } rowsumsq = rowsum * rowsum; /*square rowsum */

10

Outer Loop Structure


We have a code that reads the next n integers from the terminal and sums them. Modify it so that it reads the next m integers from the output of the previous code, specifically the value of rowsumsq and sums them.

11

Task: Modify code below so that it reads the next m integers from the output of the previous code, specifically the value of rowsumsq and sums them.
int a; /* the current integer */ int colindex; /* index of current column */ int rowsum; /* sum of row entries read so far */ int rowsumsq; /* square of the sum of row entries */ rowsum = 0; colindex=0; while (colindex < n) { /* not finished reading n cols*/ scanf(%d, &a); /* read next number */ rowsum = rowsum + a; /* add to rowsum */ colindex = colindex + 1; /* increment colindex */ } rowsumsq = rowsum * rowsum; /*square rowsum */

12

Previous code modified to read the next m integers from the output of the previous code, specifically the value of rowsumsq and sums them.

Outer Loop: Still in Design Phase: incomplete and informal


int rowindex; /* index of current row being read */ int sqsum; /* sum of col entries read so far */ sqsum = 0; rowindex=0; while (rowindex < m) { /* not finished reading m rows*/ sqsum=sqsum+``rowsumsq; /* add to colsum */ rowindex = rowindex + 1; /* increment colindex */ } printf(%d ,colsum);

rowsumsq comes from previous code. Lets insert that code here.
13

Initialization and definition can be done together in C. A short-cut. Following code defines an integer variable a and initializes it to 10.

int a; /* define a */ a=10; /* initialize a to 10 */

The code int a = 10; defines a (i.e., creates a box named a) and initializes it to 10, both in one single statement. Has same effect as previous code. May be used for any of the basic types, int, float, etc., e.g.,

float rate = 6.50 ;

14

Comma in C

C allows multiple variables of the same type to be defined as one statement, separated by commas. a c a
2

Defines three integer Examples (independent definitions) variables named a,b and c.

int a, b, c;

int a = 2, b = 5, c=15;

float x = 3.59, y = 4.5;


int x = 5, float y = 10.0;

Defines three integer variables named a,b and c. Initializes a to 2, b to 5 and c to 15. Compilation error!

b
5

c
15

Defines two float variables named x and y. Initializes x to 3.59 and y to 10.0.

x
3.59

y
10.0
15

Insert inner loop code into outer


int rowindex = 0; /* index of current row being read */ int colsum =0; /* sum of col entries read so far */ int a; int colindex; int rowsum; int rowsumsq; while (rowindex < m) { /* not finished reading m rows */ rowsum = 0; colindex=0; /* re-initialization */ while (colindex < n) { /* not finished reading n cols */ scanf(%d, &a); rowsum = rowsum + a; colindex = colindex + 1; } rowsumsq = rowsum * rowsum; /*square rowsum */ colsum = colsum + rowsumsq; /* add to colsum */ rowindex = rowindex + 1; /* increment colindex */ }

16

int m,n; int rowindex = 0; int sqsum =0; int a, colindex, rowsum; scanf(%d,%d, &m,&n); while (rowindex < m) { rowsum = 0; colindex=0; while (colindex < n) { scanf(%d, &a); rowsum=rowsum+a; colindex=colindex+1; } sqsum=sqsum + (rowsum * rowsum); rowindex=rowindex+1; }

Input 2 3 1 0 0 1
m a 1 2

-1 1
3

Output should be 4

rowindex colindex rowsum sqsum


0 0 0 0

0
-1 0 1 1

1
2

1
2 3 0 1 2

1
1 0 0 0 1 2

0
4

17

Variation to previous problem

Suppose we interchange the role of columns and rows. That is, we wish to calculate

Sum of square of column sums Input is same as before: m,n and m X n matrix A, each row of A is given in a separate input line. How can we solve it? Not possible unless a constant fraction of the matrix is stored. (Non-trivial proof).

j ( i Aij)2 ,

i=0..m-1, j=0..n-1.

18

Examples: contd.

Calculate n choose k = nCk

exactly and efficiently. Consider the following algorithm.

n(n 1)...(n k 1) k (k 1)...1

1.

2.
3. 4. 5.

Read n,k from input. Check if 0 <= k <= n. First calculate numerator as num = n(n-1)(n-k+1). Next calculate denominator as den = k! Answer is the ratio num/den.

19

Lets quickly program this


#include <stdio.h> main () { int n,k, num, den; /* as discussed before */ int i; /* for counting till */ scanf(%d%d,&n,&k); if ((k >= 0) && (n >=k)) { /* boundary checks */ if (2*k > n) { k = n-k; } /* nCk = nCn-k */ /* now calculate num and den */ i=1; num =1; den =1; /* loop invariant: num = n(n-1)(n-i+1) for i>1 */ while (i <= k) { num = num * (n-i+1); den = den * (k-i+1); i = i+1; } printf(%d choose %d is %d, n, d, num/den); }else{ printf (Inputs out of range\n);} }

20

About division operator /


We used / in n choose k program. The division operator / in C behaves differently for the types int and float. When a, b are both variables of type int, then a/b is the integer quotient when a is divided by b. When a,b are both float, then a/b is the usual (real) division. When one operand is int and other is float, the operand from narrower type is upgraded to wider type. Then

Output

int a =5, b = 2; printf(%d , a/b);

Output float x =5.0, float y = 2.0; 2.500000 printf(%f , x/y);

float x =5.0, int y = 2; printf(%f , x/y);

Output
2.500000

21

An alternative computation
Problems with this approach? num may easily become larger than the maximum value of an int although nCk is not large. Then answer is unreliable. Example: consider 25C12 versus 25(24)(23)(13). Another way. Use the identity nC = (n/k) (n-1C k k-1)) and calculate as (n * (n-1Ck-1))/ k Order of evaluation: Multiplication must be done before integer division. E.g, 7C = (7/3) * 15 = (2.3333..)*15 = 35, but there can 3 be loss of accuracy in floating point division. Integer division of course cannot work.

22

Finding an invariant

Using nCk = (n * (n-1Ck-1))/ k First design the loop invariant. Let i be a counter that we plan to increase from i=0,1,2, , k. Maintain a variable ans of type int, which is intended to ultimately hold the final answer nCk . i ans * indicates: multiply previous value of ans by (initially 0) (initially 0) 0 1 2 k
n-k C equals 1 0 n-k+1C 1 n-k+2C 2
* (n-k+1) * (n-k+2)/2 * (n-k+3)/3 * n/k

Invariant: ans = n-k+i C i

nC k

23

Invariant: ans = n-k+i C i .Used to design loop. How? Maintain invariant: i will become i+1 in next iteration.
n-k+i+1 C n-k+iC / (i+1) = (n-k+i+1) * i+1 i

main() { int n,k,i,ans; scanf(%d%d,&n,&k); if ((k >=0) && (k <=n)) { /* input is valid! */ ans =1; i=0; while (i < k) { /* loop invariant: ans = n-k+i choose i*/ ans = (ans * (n-k+i+1))/ (i+1); /*int division */ i = i+1; } printf(%d choose %d is %d,n,k, ans); } else { printf(Input parameters out of range); } } /* end of main() */

24

When is an invariant good?


1.

Our invariant was ans = n-k+i C i . An invariant is good for a problem if invariant is ``easily maintained over successive iterations. This is ensured by

n-k+i+1 C n-k+iC / (i+1) = (n-k+i+1) * i+1 i


i=0; while (i < k) { ans = (ans * (n-k+i+1))/ (i+1); i = i+1; }

Upon termination, the problem is solved. Loop


which is desired.

terminates when i=k. By invariant, ans = nCk

,
25

#include <stdio.h> main() { int n,k,i,ans; scanf(%d%d,&n,&k); if ((k >=0) && (k <=n)) { ans =1; i=0; while (i < k) { ans=(ans*(n-k+i+1))/(i+1); i = i+1; } printf(%d choose %d is %d,n,k, ans); } else { printf(Input parameters are out of range); } }

Input 6 3 n 6 ans 1 4 10 20

Output should be 20 k
3 i 0 1 2 3

Output

6 choose 3 is 20
1*(6-3+0+1)/(0+1) = 4 4*(6-3+1+1)/(1+1) = 10

10 * (6-3+2+1)/(2+1) = 20

26

Acknowledgments

These slides are a slightly modified version of the slides by Sumit Ganguly

27

Você também pode gostar