Lecture 5: Repetition - PowerPoint PPT Presentation

About This Presentation
Title:

Lecture 5: Repetition

Description:

Lecture 5: Repetition While not learned Terminating Loops Prematurely Inside a loop, a break statement causes the execution to immediately jump out of that loop, and ... – PowerPoint PPT presentation

Number of Views:84
Avg rating:3.0/5.0
Slides: 40
Provided by: Goo7539
Category:

less

Transcript and Presenter's Notes

Title: Lecture 5: Repetition


1
Lecture 5 Repetition
  • While not learned

2
The Need for Repetition
  • At the compile time, we cannot generally know how
    long the program is going to run
  • If the program reads its input from an arbitrary
    data file, we can't know beforehand how long this
    file will be
  • Some interactive game between human and machine
    can take arbitrarily many moves, and the human
    might want to play the game arbitrarily many
    times
  • Language must have some mechanism to keep doing
    something over and over, as many times as it's
    needed
  • Recursion works in principle, but has its
    downsides
  • Explicit looping often simpler and superior
  • Three types of loop structures, all equally
    powerful in principle, in practice handy in
    different situations

3
While-Loop
  • Of the three different loop structures offered in
    C, while-loops are conceptually the simplest
  • Resembles if-statement, but does not have an else
  • Conceptually, keep executing the loop body again
    and again while the condition is true
  • Loop terminates when the loop condition becomes
    false
  • Note that the truth of the loop condition is not
    checked constantly between every statement in the
    loop body, but only at the beginning of the loop,
    and then again between the repetitions of the
    loop body
  • Condition may be temporarily false during the
    loop, but become true again before it is checked

4
Countdown With While
  • / Outputs a countdown from n to 0. /
  • int countdown_with_while(int n)
  •     int c n / Good style to use a separate
    loop counter /
  •     while(c gt 0)
  •         printf("d... ", c)
  •         c c - 1
  •     
  •     printf("Liftoff!\n")

5
Behaviour of While-Loops
  • A while-loop will execute its body zero times, if
    the condition is false to begin with (for
    example, call the countdown function with a
    negative n)
  • Normally, a while-loop will execute its body some
    finite number of times and then terminate
  • It is possible to have an infinite loop that
    never terminates (for example, forget to write in
    the statement to decrement c in the countdown
    function)
  • Some sort of infinite loops are necessary for
    programs that are supposed to run forever (until
    they are explicitly terminated by user), but in
    this course, infinite loops are logic errors
  • Of course, the loop itself may be infinite
    while(1), but you jump out of it, if some
    condition is true

6
Do-While Loop
  • The second type of loop offered in C is
    the do-while
  • Clearly the least commonly used of the three one
    famous study of real world programs revealed that
    out of all loops in them, only 1 are do-while
  • Do-while behaves exactly the same way as the
    while-loop, but is guaranteed to execute its body
    at least once before it starts looking at the
    loop condition
  • The possibility of executing the loop body zero
    times does not exist, even if the condition is
    initially false
  • do-while is most useful in situations where
    testing the condition simply does not make any
    sense until the loop body has been executed once

7
Asking User for Constrained Input
  • / Keep asking the user for a number until he
    types in a number that is between min and max,
    inclusive. /
  • int ask_for_number(int min, int max)
  •     int num
  •     do
  •         printf("Enter integer between d and d
    ", min, max)
  •         scanf("d", num)
  •     while(num lt min num gt max)
  •     return num

8
A Sentinel-Controlled Loop
  • int sum_of_inputs(int min, int max)
  •     int sum 0, curr
  •     do
  •         curr ask_for_number(min, max)
  •         sum curr
  •     while(curr ! 0) / Stop when input is 0
    /
  •     return sum

9
Rationale for For-Loops
  • The third type of loop structure in C is suitable
    for the common task of iterating through the
    values of a range of integers, one value at the
    time
  • For example, go through the numbers from 1 to 100
  • The for-loop header defines this range, and the
    loop body contains the statements you execute for
    each value
  • To define an integer range, you need to define
    three things where it begins (1), where it ends
    (100), and the step size between the consecutive
    values of the range (1)
  • It is not a coincidence that the header of a
    for-loop consists of three parts, for the three
    things that define a range
  • We can still use while like in countdown, but
    using a for-loop makes it clear that we are going
    through a range

10
Defining a Range With For-Loop
  • Syntactically, a for-loop is of the form for(I
    C U) B
  • The initialization I defines where the range
    starts, and is an assignment to the loop counter
    variable that keeps track of which value we are
    currently at
  • The condition C defines where the range ends, but
    does so in a negated way, be defining where the
    range still continues
  • As long as the condition is true, we are still
    inside the range and the loop executes its body B
    one more time
  • The update U is an assignment to the loop counter
    that calculates the next value in the range
  • For example for(c 1 c lt 100 c)

11
Some Example Ranges
  • Even numbers from -100 to 100
  • for(c - 100 c lt 100 c 2) ...
  • All numbers from start to end
  • for(c start c lt end c) ...
  • Powers of two from 1 to 65536 ( 216)
  • for(c 1 c lt 65536 c c 2) ...
  • Powers of three up to 3n
  • for(c 0, p 1 c lt n c, p p 3) ...
  • For convenience, the last example uses two
    separate loop variables, separated by the comma
    operator that can be used to combine two
    expressions into one, used where the language
    syntax requires one expression

12
Example Countdown With For
  • / Outputs a countdown from n to 0. Note that
    using a for loop, the loop body does not need to
    talk about the logic of iterating through the
    values, but can just contain the statements that
    you want to execute for each value. /
  • void countdown_with_for(int n)
  •     int c / Still have to declare the loop
    counter variable /
  •     for(c n c gt 0 c--)
  •         printf("d... ", c)
  •     
  •     printf("Liftoff!\n")

13
Example Output a List of Numbers
  • / Output the numbers from start to end separated
    by commas, taking care that you don't write a
    trailing comma after the last number in the
    series. /
  • void output_numbers(int start, int end)
  •     int c
  •     for(c start c lt end c)
  •         printf("d", c)
  •         if(c lt end)  printf(", ") 
  •     

14
Example Rolling Multiple Dice
  • / Roll the dice given number of times and return
    total. /
  • int roll_dice(int n_dice, int sides)
  •     int total 0
  •     int roll
  •     for(roll 1 roll lt n_dice roll)
  •         total 1 rand() sides
  •    
  •     return total

15
Example Harmonic Sum
  • / H_n 1 1/2 1/3 ... 1/n /
  • double harmonic(int n)
  •     double result 0.0
  •     int i
  •     for(i 1 i lt n i)
  •         result 1.0 / i
  •    
  •     return result

16
Example Primality Testing
  • int is_prime(int n)
  •     int c
  •     if(n lt 2) return 0
  •     if(n 2) return 1
  •     if(n 2 0) return 0
  •     / Iterate through odd numbers from 3 to
    sqrt(n) /
  •     for(c 3 c c lt n c 2)      
  •         / For each such number, check if it
    divides n. /
  •         if(n c 0) return 0
  •     
  •     return 1 / Only after we checked all
    divisors... /

17
Example Goldbach Conjecture
  • / Check if the positive even number n gt 4 can be
    expressed as a sum of two prime numbers. /
  • int verify_goldbach(int n)
  •     int a
  •     for(a 3 a lt n / 2 a 2)
  •         if(is_prime(a) is_prime(n - a))
    return 1
  •    
  •     / This should not happen, assuming valid n.
    /
  •     return 0

18
Example Fibonacci Numbers
  • / 1, 1, 2, 3, 5, 8, 13, 21, 34, ... /
  • int fib(int n)
  •     int a 1, b 1, i, c
  •     for(i 2 i lt n i)
  •         c a b / Next number in series /
  •         a b      / Shift the current two
    numbers /
  •         b c
  •    
  •     return b

19
Example Debt Calculator
  • int debt(double debt, double interest, double
    payment)
  •     int years 0
  •     double old_debt
  •     while(debt gt 0)
  •         old_debt debt
  •         debt debt interest / 100.0 -
    payment
  •         if(old_debt lt debt) return -1
  •         years
  •    
  •     return years

20
Example Binary Power
  • double power(double base, int exp)
  •     double result 1.0
  •     if(exp lt 0) return 1.0 / power(base, -exp)
  •     while(exp gt 0)
  •         if(exp 2 1) result result
    base
  •         base base base
  •         exp exp / 2
  •    
  •     return result

21
Example Solving a Root by Halving
  • / Assume F is a continuous function of doubles
    defined as a macro, and F(a) and F(b) initially
    have different signs. /
  • double solve(double a, double b)
  •     double mid, fmid
  •     while(b - a gt 0.000001) / desired
    precision /
  •         mid (a b) / 2 fmid F(mid)
  •         if(fmid gt 0 F(a) gt 0) a mid
  •         else if(fmid lt 0 F(a) lt 0) a mid
  •         else b mid
  •    
  •     return (a b) / 2

22
Example Hailstone Numbers
  • int count_hailstone(int n)
  •     int steps 0
  •     while(n gt 1)
  •         steps
  •         if(n 2 0) n n / 2
  •         else n 3 n 1
  •    
  •     return steps
  • / The famous open Collatz conjecture says that
    for any starting value n, this process will reach
    1 in finite time. /

23
Nested Loops
  • Since the body of any looping statement can be
    any series of statements, these statements can be
    conditions and even other inner loops nested
    inside the outer loop
  • It might be first difficult to intuit the
    behaviour of nested loops, but this becomes
    easier when you just think of how an ordinary
    clock works
  • To count through one day, the hour counter goes
    through the numbers from 0 to 23
  • For each hour, the minute counter goes through
    the numbers from 0 to 59, starting again the next
    hour
  • For each minute, the second counter goes through
    the numbers from 0 to 59, starting again the next
    minute
  • Implemented next as three nested loops

24
Counting Time With Nested Loops
  • void count_time_through_day()
  •     int hour, minute, second
  •     for(hour 0 hour lt 24 hour)
  •         for(minute 0 minute lt 60 minute)
  •             for(second 0 second lt 60
    second)
  •                 / Whatever you do with the
    current second... /
  •            
  •        
  •    

25
As Long As The Total Is Correct...
  • To count to five, we humans count "one, two,
    three, four, five", with or without using our
    fingers to keep track
  • If something is supposed to happen a total of
    five times, but the actual loop counter values
    don't matter, we could just as well count "ten,
    eleven, twelve, thirteen, fourteen" and it would
    be just as correct
  • In computing, it is often convenient to start
    counting from zero, instead of one
  • The canonical loop to do something exactly n
    times goes
  • for(c 0 c lt n c) ...

26
Off By One
  • Writing loop logic, off by one is a common type
    of logic error in which the loop runs one round
    too many or too few
  • Do not try to fix this by mechanistically
    converting the terminating condition from lt to
    lt, or vice versa, but reason for what values the
    loop is supposed to run
  • Common subtype is fencepost error if there is a
    fencepost every 10 meters, and the fence is 100
    meters long, how many fenceposts are there?
  • How many integers are there from 10 to 20?
  • How about from -10 to 10?
  • Fencepost errors can be avoided by using
    zero-based indexing, and expressing ranges with
    an exclusive end

27
Example Output A Rectangle
  • / Output a filled rectangle of given character
    using nested loops, outer loop counting the rows,
    and for each row, the inner loop counting the
    columns. /
  • void output_rectangle(int rows, int cols, char
    ch)
  •     int r, c
  •     for(r 0 r lt rows r)
  •         for(c 0 c lt cols c)
  •             printf("c", ch)
  •        
  •         printf("\n") / Newline after each row
    /
  •    

28
Example Output a Deck of Cards
  • void output_deck()
  •     int suit, rank
  •     for(suit 0 suit lt 4 suit)
  •         for(rank 1 rank lt 13 rank)
  •             switch(rank)
  •                 case 11 printf("jack of ")
    break
  •                 case 12 printf("queen of ")
    break
  •                 case 13 printf("king of ")
    break
  •                 case 1 printf("ace of ") break
  •                 default printf("d of ", rank)
    break
  •            
  •             switch(suit)
  •                 case 0 printf("clubs\n") break
  •                 case 1 printf("diamonds\n")
    break
  •                 case 2 printf("hearts\n")
    break
  •                 case 3 printf("spades\n")
    break
  •            
  •        
  •      

29
Example Output Prime Factors
  • void output_prime_factors(int n)
  •     int c 2 / First potential factor /
  •     while(n gt c)
  •         if(n c 0)
  •             printf("d ", c) / Eliminate one
    factor /
  •             n n / c
  •        
  •         else  / Move on to try the next
    potential divisor /
  •             c (c 2)? 1 2 
  •         
  •    
  •     printf("\n")

30
Functions Simulating Nested Loops
  • void output_one_row(int cols, char ch)
  •     int c
  •     for(c 0 c lt cols c)
  •         printf("c", ch)
  •    
  •     printf("\n")
  • void output_rectangle(int rows, int cols, char
    ch)
  •     int r
  •     for(r 0 r lt rows r)
  •         output_one_row(cols, ch)
  •    

31
Example Radix Conversions
  • / First, a utility function to return the digit
    character for the given digit. Assumes that digit
    is at most 36. /
  • char get_digit(int d)
  •     if(d lt 10) return '0' d
  •     else return 'A' (d - 10)
  • / The character '0' is not the same as zero.
    Since characters are really integers, it is okay
    to perform integer arithmetic on them. The
    function assumes that characters '0', ..., '9'
    are consecutive in the encoding table, as are
    also 'A', ..., 'Z'./

32
Radix Conversion Using While
  • void output_int(int n, int base)
  •     int p 1
  •     while(p base lt n) p p base
  •     / p is now the highest power of base that is
    lt n. /
  •     while(p gt 0) / Descend through the powers
    of base
  •         printf("c", get_digit(n / p) )
  •         n n p
  •         p p / base
  •    

33
Radix Conversion With Recursion
  • / In this particular problem, recursion is so
    much simpler that I just have to show it. The
    loop was complicated because we have to output
    digits starting with the most significant one,
    which is harder to find than the least
    significant digit. With recursion, this order
    doesn't matter. /
  • void output_int(int n, int base)
  •     / Output the digits before the last one. /
  •     if(n gt base)  output_int(n / base) 
  •     / Output the last digit. /
  •     printf("c", get_digit(n base))

34
Terminating Loops Prematurely
  • Inside a loop, a break statement causes the
    execution to immediately jump out of that loop,
    and move to the statement following the loop
  • If used inside nested loops, break jumps out of
    the innermost loop that contains this statement
  • If you want to jump out of an outer loop, you
    need to first give this loop a label, an
    identifier followed by a colon placed before the
    loop, and use this label in the break statement
    to specify which loop you want to terminate
  • In principle, any loop that uses break can be
    rewritten as an equivalent loop that does not use
    that statement
  • Jumping around tends to bring back the bad old
    days of unstructured spaghetti code and makes the
    program logic harder to follow

35
Continue
  • continue is a statement similar to break, but
    instead of jumping out of the loop altogether, it
    jumps to the next round of the loop, skipping the
    rest of the body
  • Somewhat confusingly named, since this statement
    would have been better titled maybe skip or next
  • Most commonly used to skip some of the values
    inside the range for which the loop doesn't need
    to do anything
  • Just like with break, you can use a label to
    determine which loop you want to move to the next
    round
  • In modern C, did you know you can put URL's in
    code?
  • http//www.ryerson.ca

36
Files With Unknown Amount of Data
  • When reading data from a file so that the file
    doesn't in its beginning tell us how many items
    of data it contains, we need a way to tell that
    we have reached the end of file
  • Function feof(f) tells you this for the file f
  • Use something like while(!feof(f)) ...
  • Alternatively, can use the fact that fscanf, in
    addition to assigning the values, returns the
    constant EOF if you have already reached the end
    of file
  • Use something like while(fscanf(...) ! EOF)
    ...
  • Better when there is extra whitespace at end of
    file
  • Also works with scanf just as well as with fscanf

37
Example Variance from File
  • double variance(FILE f)
  •     double sum 0, sum_sq 0, x, avg_sq, avg
  •     int total 0
  •     while(fscanf(f, "f", x) ! EOF)
  •         sum x sum_sq x x
  •         total
  •    
  •     avg sum / total
  •     avg_sq sum_sq / total
  •     return avg_sq - avg avg
  • / It is the caller's responsibility to open and
    close the file. /

38
Raw Text, The Universal Data Format
  • Storing numbers as text takes more space than
    storing them as bytes, since you effectively use
    only ten of the 256 possible values of each byte
    (plus whatever whitespace, comma or other
    separator characters you use)
  • Application-specific binary data formats can take
    a lot less space compared to human-readable text
  • However, text can be easily edited and
    transformed, and it does not impose hard
    constraints on the maximum values of each data
    field when stored in a fixed space
  • Prefer text files over custom binary formats,
    unless there really is a large amount of data
    (sound, pictures, video)
  • Can always compress and decompress text anyway
    with standard compression algorithms

39
 
  • "When I am working on a problem, I never think
    about beauty. I think only of how to solve the
    problem. But when I have finished, if the
    solution is not beautiful, I know it is wrong."
  • Buckminster Fuller
  • "John von Neumann draws attention to what seemed
    to him a contrast. He remarked that for simple
    mechanisms, it is often easier to describe how
    they work than what they do, while for more
    complicated mechanisms, it is usually the other
    way around."
  • Edsger W. Dijkstra
Write a Comment
User Comments (0)
About PowerShow.com