UP | HOME

Loops (While)
COP-3223H

Table of Contents

Recall: exponent on desktop calculator

\(x^e\) for e >= 1

  1. Input x and e
  2. Start with 1 in result
  3. Multiply result by x
  4. Subtract 1 from e
  5. Repeat from 3 only if e > 0

Desktop calculator program for exponent

1: 3
2: store x
3: 5
4: store e
5: 1
6: store result
----------------
7: recall result
8: *
9: recall x
10: =
11: store result
12: recall e
13: -
14: 1
15: =
16: store e
17: if e>0 goto 7
-----------------------
18: recall result
# inputs
1: 3
2: store x
3: 5
4: store e
5: 1
6: store result
----------------
# one multiplication
7: recall result
8: *
9: recall x
10: =
11: store result
# decrement e
12: recall e
13: -
14: 1
15: =
16: store e
# repeat if not done multiplying
17: if e>0 goto 7
-----------------------
18: recall result

Exponent in C (with goto)

  • Use goto as in desktop calculator program
    • To a label instead of a number
repeat:
// C code
goto repeat;
#include <stdio.h>
#include <assert.h>

int main(int argc, char **argv) {
  int x;
  int e;

  scanf("%d", &x);
  scanf("%d", &e);
  assert(e >= 1);

  int result = 1;

 repeat:

  result = result * x;

  e = e - 1;

  if (e > 0) {
    goto repeat;
  }

  printf("%d\n", result);
}

goto can be confusing

While Loops

while loops

while (condition) {
  instructions;
}
  1. Check the condition
  2. If the condition is true, run the instructions and repeat from #1
  3. If the condition is false, don't run the instructions nor repeat

Flow chart

Diagram

  • Condition check
  • instructions, then go back to condition
  • next code

while true

What will be the output of this program?

while (1) {
}
print("done!\n");

Decrement e with while loop

while (e > 0) {
  e = e - 1;
}
  • Does the program ever end?
  • What will be the value of e after the while loop (if it ends)?
#include <stdio.h>

int main(int argc, char **argv) {
  int e;

  scanf("%d", &e);

  int result = 1;

  while (e > 0) {
    e = e - 1;
  }

  printf("%d\n", e);
}

Exponent with a while loop

  • How do we use while here?
#include <stdio.h>
#include <assert.h>

int main(int argc, char **argv) {
  int x;
  int e;

  scanf("%d", &x);
  scanf("%d", &e);
  assert(e >= 1);

  int result = 1;

 repeat:

  result = result * x;

  e = e - 1;

  if (e > 0) {
    goto repeat;
  }

  printf("%d\n", result);
}
#include <stdio.h>
#include <assert.h>

int main(int argc, char **argv) {
  int x;
  int e;

  scanf("%d", &x);
  scanf("%d", &e);
  assert(e >= 1);

  int result = 1;

  while (e > 0) {
    result = result * x;
    e = e - 1;
  }

  printf("%d\n", result);
}

Differences?

Repeated guessing game

  • Guess until right
  • Fixed guesses
#include <stdbool.h>
int answer;
int guess;

printf("enter the answer: ");
scan("%d", &answer);
printf("enter the guess: ");
scan("%d", &guess);

while (guess != answer) {
  printf("enter the guess: ");
  scan("%d", &guess);
}

Factorial

do-while

do {
  instructions;
} while (condition);
  1. Run the instructions
  2. Check the condition
  3. If the condition is true, repeat from #1
  4. If the condition is false, don't repeat repeat

Differences from while

int e;
scan("%d", e);
while (e > 0) {
  printf("%d\n", e);
  e = e - 1;
}
int e;
scan("%d", e);
do {
  printf("%d\n", e);
  e = e - 1;
} while (e > 0);

Summary of differences

  1. while loops: run 0 or more times
  2. do-while loopsl run 1 or more times

Compare exponent implementations

#include <stdio.h>
#include <assert.h>

int main(int argc, char **argv) {
  int x;
  int e;

  scanf("%d", &x);
  scanf("%d", &e);

  int result = 1;

  do {
    result = result * x;
    e = e - 1;
  } while (e > 0);

  printf("%d\n", result);
}

Compare guessing game implementations

Repeated Guessing Game

From homework

Boundary conditions

0, 1, and many

Fencepost problem

0-based or 1-based

Considering all inputs

Tips

  • [x, y), inclusive start, exclusive end (easy composition)
  • 0 <= x means inclusive, x < 10 means exclusive
  • Know both 0-base (we'll see arrays later) and 1-base (for math-related stuff)

Clean up: exponent

Clean up: factorial

Clean up: finite guessing game

Example: newton's method

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  float a;  // the number to find square root of
  float x;  // the iterative guess

  printf("enter a number: ");
  /* a = (float) (getchar() - '0'); */
  scanf("%f", &a);
  printf("a: %f\n", a);

  // initially guess half of a
  x = a / 2;
  printf("initial x: %f\n", x);

  while (1) {
    x = x - (x * x - a)/(2 * x);
    /* x = x - (x * x - a)/(2); */
    printf("x: %f\n", x);
    sleep(1);
  }
}

Console animation

ssh terminal.shop

telnet starwarstel.net

ssh starwarstel.net

ttyquake / aaquake2 - Text Mode Quake II

Bouncing ball

44 lines of C

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  int width = 40;
  int height = 20;
  int x = 0;
  int y = 0;
  int dx = 1;
  int dy = 1;
  while (1) {
    printf("\033[2J");
    printf("\033[H");
    for (int j = 0; j < height; j++) {
      for (int i = 0; i < width; i++) {
        if ((i == x) && (j == y)) {
          putchar('o');
        } else {
          putchar(' ');
        }
      }
      putchar('|');
      putchar('\n');
    }
    for (int i = 0; i < width; i++) {
      putchar('^');
    }
    putchar('\n');
    if ((0 <= (x + dx)) && ((x + dx) < width)) {
      dx = dx;
    } else {
      dx = dx * -1;
    }
    if ((0 <= (y + dy)) && ((y + dy) < height)) {
      dy = dy;
    } else {
      dy = dy * -1;
    }
    x = x + dx;
    y = y + dy;
    usleep(50 * 1000);
  }
  return 0;
}

The char type

A single character

char c;

c = 'a';

putchar(a);  // prints a character
fflush(stdout);  // ensure output

Roughly corresponding to keyboard keys. Run man ascii in bash for full set (there are other encodings as well, e.g., EBCDIC, ANSI, and Unicode).

Can also use %c in printf, e.g.,

printf("%c\n", c);

fflush is necessary in the default terminal mode, where output is only sent line-by-line

The newline character \n

\n means "go to the next line"

This is a non-printable character. Instead it controls the cursor of the terminal.

hello, world!\n vs. hello, world!

Terminal controls

Special characters to manipulate the terminal screen

\033[ followed by a code, e.g.,

  • clear screen 2J
  • move cursor back to top-left H
printf("\033[2J");  // clear screen
printf("\033[H");   // move cursor to top-left of terminal

Timing: sleep

Sleep: wait for a given amount of time

usleep(x) sleep for x microseconds

#include <unistd.h>
usleep(50 * 1000);  // sleep for 50 milliseconds (50,000 microseconds)

Example: draw with while

while_putchar.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  printf("\x1b[2J");  // clear screen
  printf("\x1b[H");

  while (1) {

    putchar('o');
    fflush(stdout);

    usleep(50 * 1000);
  }
}

Example: movement

move.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  int max = 40;
  int x;

  x = 0;
  while (1) {
    printf("\033[2J");
    printf("\033[H");

    int i = 0;
    while (i < max) {
      if (x == i) {
        putchar('o');
      } else {
        putchar(' ');
      }
      i = i + 1;
    }

    fflush(stdout);

    x = (x + 1) % max;

    usleep(50 * 1000);
  }
}

Start with just printing a characater

Example: 1-dimensional bounce

Add code to change direction

1d_bounce.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  int max = 40;
  int x;
  int dx;

  x = 0;
  dx = 1;
  while (1) {
    printf("\x1b[2J");
    printf("\x1b[H");

    int i = 0;
    while (i < max) {
      if (x == i) {
        putchar('o');
      } else {
        putchar(' ');
      }
      i = i + 1;
    }

    fflush(stdout);

    x = x + dx;
    if (0 < x && x < (max - 1)) {
      dx = dx;
    } else {
      dx = dx * -1;
    }

    usleep(50 * 1000);
  }
}

Example: 2-dimensional bounce

Add a y-axis

2d_bounce.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  int width = 40;
  int height = 20;
  int x = 0;
  int y = 0;
  int dx = 1;
  int dy = 1;
  while (1) {
    printf("\033[2J");
    printf("\033[H");
    int j = 0;
    while(j < height) {
      int i = 0;
      while (i < width) {
        if ((i == x) && (j == y)) {
          putchar('o');
        } else {
          putchar(' ');
        }
        i++;
      }
      putchar('|');
      putchar('\n');
      j++;
    }
    for (int i = 0; i < width; i++) {
      putchar('^');
    }
    putchar('\n');
    if ((0 <= (x + dx)) && ((x + dx) < width)) {
      dx = dx;
    } else {
      dx = dx * -1;
    }
    if ((0 <= (y + dy)) && ((y + dy) < height)) {
      dy = dy;
    } else {
      dy = dy * -1;
    }
    x = x + dx;
    y = y + dy;
    usleep(50 * 1000);
  }
  return 0;
}

Build from 1d bounce.

ANSI cursor control

Simplify positioning, horizontal/vertical positioning:

e.g., 3;2H

printf("\033[%d;%dH", 3, 2);

Terminal is a grid of characters (grid in xournal++), starting from 1, 1

bounce with ANSI

bounce_ansi.c

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv) {
  int width = 40;
  int height = 20;
  int x = 1;
  int y = 1;
  int dx = 1;
  int dy = 1;
  while (1) {
    printf("\033[2J");
    printf("\033[H");
    printf("\033[%d;%dH", (int)y, (int)x);
    putchar('o');
    putchar('\n');
    if ((0 < (x + dx)) && ((x + dx) < width)) {
      dx = dx;
    } else {
      dx = dx * -1;
    }
    if ((0 < (y + dy)) && ((y + dy) < height)) {
      dy = dy;
    } else {
      dy = dy * -1;
    }
    printf("\033[%d;%dH", height + 1, 0);
    printf("y: %d\n", y);
    printf("x: %d\n", x);
    x = x + dx;
    y = y + dy;
    usleep(50 * 1000);
  }
  return 0;
}

Author: Paul Gazzillo

Created: 2026-02-24 Tue 15:11

Validate