Learning C Language Day 6

Main content: while statement, do statement, for statement, exit loop, empty statement, etc.

A loop is a statement that repeatedly executes other statements (the loop body). In C language, each loop has a controlling expression. Each time the loop body is executed (the loop repeats once), the controlling expression is evaluated. If the expression is true (i.e., non-zero), the loop continues to execute.

while Statement

The format of the while statement is as follows:

while (expression) statement;

The expression in parentheses is the controlling expression, and the statement after the parentheses is the loop body. Example:

while (i < n)  // controlling statement
    i = i * 2;

When executing the while statement, the value of the controlling expression is first calculated. If the value is non-zero (i.e., true), the loop body is executed, and then the expression is evaluated again. This process (evaluate the controlling expression first, then execute the loop body) continues until the value of the controlling expression becomes zero, at which point it stops.

Example program:

#include <stdio.h>

int main() {
    int i = 1,
        n = 10;

    while (i < n) {
        i = i * 2;
        printf("%d ", i);
    }

    return 0;
}

/* Output
* 2 4 8 16
*/

Tracking the execution of the while statement:

i = 1; i is now 1.

Is i < n true? Yes, continue.

i = i * 2; i is now 2.

Is i < n true? Yes, continue.

i = i * 2; i is now 4.

Is i < n true? Yes, continue.

i = i * 2; i is now 8.

Is i < n true? Yes, continue.

i = i * 2; i is now 16. Is i < n true? No, exit the loop.

If multiple statements are needed, simply enclose them in a pair of curly braces to form a compound statement.

The following statement displays a countdown message:

#include <stdio.h>

int main() {
    int i = 10;

    while (i > 0) {
        printf("T minus %d and counting\n", i);
        i--;
    }

    return 0;
}

Output:

T minus 10 and counting
T minus 9 and counting
T minus 8 and counting
T minus 7 and counting
T minus 6 and counting
T minus 5 and counting
T minus 4 and counting
T minus 3 and counting
T minus 2 and counting
T minus 1 and counting

The while statement can often be written in various ways. For example, we can perform the decrement operation on variable i inside the printf function call, making the countdown loop more concise:

while (i > 0) 
   printf("T minus %d and counting\n", i--);

Infinite Loop

If the value of the controlling expression is always non-zero, the while statement will not terminate. Sometimes, a non-zero constant is intentionally used as the controlling expression to create an infinite loop:

while (1)...

Unless the loop body contains a statement that breaks the loop (break, goto, return) or calls a function that terminates the program, the above form of the while statement will execute indefinitely.

Program to Display Square Table

Write a program to display a square table. First, the program prompts the user to enter a number n, then displays n lines of output, each line containing a number from 1 to n and its square value. This program prints a table of squares. Enter number of entries in table: 5 1 1 2 4 3 9 4 16 5 25

square.c

#include <stdio.h>

int main() {
    int i, n;

    printf("This program prints a table of squares.\n");
    printf("Enter number of entries in table:");
    scanf_s("%d", &n);

    i = 1;
    while (i <= n) {
        printf("%10d%10d\n", i, i * i);
        i++;
    }

    return 0;
}

Output:

This program prints a table of squares.
Enter number of entries in table: 5
         1         1
         2         4
         3         9
         4        16
         5        25

Program to Sum a Series of Integers

In the following example using the while statement, we wrote a program to sum a series of integers input by the user. Below is what the user sees:

This program sums a series of integers.

Enter integers (0 to terminate): 8 23 71 5 0

The sum is: 107

sum.c

#include <stdio.h>

int main(void) {

    int n, sum = 0;

    printf("This program sums a series of integers.\n");
    printf("Enter integers (0 to terminate): ");
    scanf_s("%d", &n);
    while (n != 0) {
        sum += n;
        scanf_s("%d", &n);
    }
    printf("The sum is: %d\n", sum);

    return 0;
}

Output:

This program sums a series of integers.
Enter integers (0 to terminate): 8 23 71 5 0
The sum is: 107

do Statement

The do statement is closely related to the while statement. In fact, the do statement is essentially a while statement, except that its controlling expression is evaluated after each execution of the loop body. The format of the do statement is as follows:

do statement while (expression);

When executing the do statement, the loop body is executed first, and then the value of the controlling expression is calculated. If the value of the expression is non-zero, the loop body is executed again, and the value of the expression is calculated again. After the loop body is executed, if the value of the controlling expression becomes 0, the execution of the do statement is terminated.

Rewrite the previous countdown program using the do statement:

#include <stdio.h>

int main(void) {
int i = 10;

do {
printf("T minus %d and counting\n", i);
  i--;
 } while (i > 0);

return 0;
}

Output:

T minus 10 and counting
T minus 9 and counting
T minus 8 and counting
T minus 7 and counting
T minus 6 and counting
T minus 5 and counting
T minus 4 and counting
T minus 3 and counting
T minus 2 and counting
T minus 1 and counting

It is best to always enclose all do statements in curly braces, whether needed or not, because do statements without curly braces can easily be mistaken for while statements:

do 
   printf("T minus %d and counting\n", i--); 
while (i > 0);

Program to Calculate the Number of Digits in an Integer

Now write a program to calculate the number of digits in a nonnegative integer input by the user:

Enter a nonnegative integer: 60

The number has 2 digit(s).

The method is to repeatedly divide the input integer by 10 until the result becomes 0, and the number of divisions is the required number of digits. Since we do not know how many division operations will be needed to reach 0, it is clear that the program needs some kind of loop. But should we use a while statement or a do statement? The do statement is clearly more appropriate because every integer (including 0) has at least one digit.

numdigit.c

#include <stdio.h>

int main(void) {
    int digits = 0, n;

    printf("Enter a nonnegative integer: ");
    scanf_s("%d", &n);

    do {
        n /= 10 ;
        digits++;
    } while (n > 0);

    printf("The number has %d digit(s).\n", digits);

    return 0;
}

Output:

Enter a nonnegative integer: 50
The number has 2 digit(s).

Enter a nonnegative integer: 5000
The number has 4 digit(s).

To illustrate that the do statement is the correct choice, let’s observe what would happen if we replaced the do loop with a similar while loop:

while (n > 0) { n /= 10; digits++; }

If the initial value of n is 0, the above loop will not execute at all, and the program will print The number has 0 digit(s).

for Statement

The format of the for statement is as follows:

for (declaration or expression 1; expression 2; expression 3) statement

Where expressions 1, 2, and 3 are all expressions. Here is an example:

for (i = 10; i > 0; i--) 
    printf("T minus %d and counting\n", i);

When executing the for statement, the variable i is first initialized to 10, then it checks if i is greater than 0. Since the result of the check is true, it prints the message T minus 10 and counting, then the variable i is decremented. The condition i > 0 is checked again. The loop body executes a total of 10 times, during which the variable i changes from 10 to 1.

The for statement is closely related to the while statement. In fact, except for a few rare cases, a for loop can always be replaced with an equivalent while loop:

for (declaration or expression 1; expression 2; expression 3) statement

is equivalent to:

expression 1;
while (expression 2) { 
 statement 
 expression 3; 
}

As shown in the pattern above, <span>expression 1</span> is the initialization step that is executed once before the loop starts; <span>expression 2</span> is used to control the termination of the loop (as long as expression2 is non-zero, the loop will continue to execute); <span>expression 3</span> is an operation that is executed last in each loop. Applying this pattern to the previous for loop example yields:

i = 10; 
while (i > 0) { 
   printf("T minus %d and counting\n", i); 
 i--; 
}

Common Usage of for Statement

Counting up from <span>0</span> to <span>n-1</span>:

for ( i = 0; i < n; i++) ...

Counting up from <span>1</span> to <span>n</span>:

for ( i = 1; i <= n; i++) ...

Counting down from <span>n-1</span> to <span>0</span>:

for ( i = n - 1; i >= 0; i--) ...

Counting down from <span>n</span> to <span>1</span>:

for ( i = n; i > 0; i--) ...

Omitting Expressions in for Statement

Typically, a for statement uses three expressions to control the loop, but some for loops may not need that many, so C allows any or all expressions to be omitted.

If the first expression is omitted, there is no initialization operation before the loop executes:

i = 10; 
for (; i > 0; --i) 
   printf("T minus %d and counting\n", i);

In this example, the variable i is initialized by a separate assignment statement, so the first expression is omitted in the for statement. (Note that the semicolon between the first and second expressions must be retained. Even if some expressions are omitted, the control expression must always have two semicolons.)

If the third expression in the for statement is omitted, the loop body must ensure that the value of the second expression eventually becomes false. Our for statement example can be written as follows:

for (i = 10; i > 0;) 
   printf("T minus %d and counting\n", i--);

To compensate for the consequences of omitting the third expression, we decrement the variable i in the loop body.

When both the first and third expressions in the for statement are omitted, it is equivalent to a while statement. For example, the loop:

for (; i > 0;)
    printf("T minus %d and counting\n", i--);

is equivalent to

while (i > 0) 
    printf("T minus %d and counting\n", i--);

If the second expression is omitted, it defaults to true, so the for statement will not terminate (unless stopped in some other way). This creates an infinite loop…

for ( ; ; )...

for Statement in C99

In C99, the first expression of the for statement can be replaced with a declaration, allowing programmers to declare a variable for use in the loop:

for (int i = 0; i < n; i++) // Variable i does not need to be declared before this statement.

Variables declared in the for statement are not accessible outside the loop (not visible outside the loop):

for (int i = 0; i < n; i++) { 
   ... 
   printf("%d", i); /* legal; i is visible inside loop */ 
   ... 
} 
printf("%d", i); /*** WRONG ***/

Multiple variables can be declared in a for statement as long as they are of the same type:

for (int i = 0, j = 0; i < n; i++)

Comma Operator

Sometimes, we may want to write a for statement with two (or more) initial expressions, or we want to increment several variables at once during each loop. Using a comma expression as the first or third expression in the for statement can achieve these ideas.

expression 1, expression 2

The evaluation of a comma expression is done in two steps: first, evaluate expression 1 and discard the computed value; second, evaluate expression 2, taking this value as the value of the entire expression.

For example, suppose the values of variables i and j are 1 and 5, respectively. When evaluating the comma expression ++i, i+j, the variable i is incremented first, and then i+j is calculated, so the value of the expression is 7.

Sometimes, it is necessary to chain a series of comma expressions together, just as it is sometimes necessary to chain assignment expressions together. The comma operator is left associative, so the compiler interprets the expression:

i = 1, j = 2, k = i + j

as

((i = 1), (j = 2)), (k = (i + j))

Improved Version of the Program to Display Square Table

square2.c

#include <stdio.h>

int main() {
int i, n;

printf("This program prints a table of squares.\n");
printf("Enter number of entries in table:");
 scanf_s("%d", &n);

for (i = 1; i <= n; i++)
printf("%10d%10d\n", i, i * i );

return 0;
}

Output:

This program prints a table of squares.
Enter number of entries in table: 5
   1         1
   2         4
   3         9
   4        16
   5        25

Another version of the same program:

square3.c

#include <stdio.h>

int main() {
int i, n, odd, square;

printf("This program prints a table of squares.\n");
printf("Enter number of entries in table:");
 scanf_s("%d", &n);

 i = 1;
 odd = 3;
for (square = 1; i <= n; odd += 2) {
printf("%10d%10d\n", i, square);
  ++i;
  square += odd;
 }

return 0;
}

Process Analysis:

Initial Value i=1 n=5 square=1 odd=3
First Loop 1 1<5 1 3
Second Loop 2 2<5 4 (1+3) 5
Third Loop 3 3<5 9 (4+5) 7
Fourth Loop 4 4<5 16 (9+7) 9
Fifth Loop 5 5=5 25 (16+9) 11
Sixth Loop 6 6>5 End Loop

Output:

This program prints a table of squares.
Enter number of entries in table: 5
   1         1
   2         4
   3         9
   4        16
   5        25

Exiting Loops

break Statement

We have previously discussed how the break statement transfers program control out of a switch statement. The break statement can also be used to exit while, do, or for loops.

Suppose we want to write a program to test whether a number n is prime. Our plan is to write a for statement that divides n by all numbers from 2 to n-1. Once a divisor is found, we break out of the loop without needing to continue trying. After the loop terminates, we can use an if statement to determine whether the loop terminated early (thus n is not prime) or normally (n is prime):

break.c

/*
Write a program to test whether a number n is prime.
A prime number is a natural number greater than 1 that has no divisors other than 1 and itself.
*/

#include <stdio.h>

int main() {
    int d, n;

    printf("Enter a num: ");
    scanf_s("%d", &n);
    getchar();

    for (d = 2; d < n; d++) {
        if (n % d == 0)
            break;
    }
    if (d < n) 
        printf("%d is divisible by %d\n", n, d); // n is divisible by d
    else
        printf("%d is prime\n", n);  // n is prime

    return 0;
}

Output:

Enter a num: 5
5 is prime

Enter a num: 9
9 is divisible by 3

The break statement is particularly useful for cases where the exit point is in the middle of the loop body rather than before or after the loop body. Loops that read user input and terminate upon encountering a special input value often fall into this category.

The break statement transfers program control out of the innermost while, do, for, or switch statement that contains it. Therefore, when these statements are nested, the break statement can only break out of one level of nesting.

Consider the case where a switch statement is nested within a while statement:

while (...) { 
   switch (...) { 
   ... 
   break; 
   ... 
 } 
}

The break statement can transfer program control out of the switch statement, but it cannot break out of the while loop.

continue Statement

<span>break</span> and <span>continue</span> are different

break continue
Transfers program control to the end of the loop body Transfers program control to the beginning of the loop body
Causes the program control to exit the loop Keeps the program control within the loop
Can be used in switch statements and loops (while, do, and for) Can only be used in loops (while, do, and for)

The following example illustrates a simple application of the continue statement by reading a series of numbers and summing them. The loop terminates after reading 10 non-zero numbers. Whenever a number 0 is read, the continue statement is executed, skipping the remaining part of the loop body (i.e., the statements sum += i; and n++;) but still remaining in the loop.

#include <stdio.h>

int main() {
    int i, n = 0, sum = 0;

    while (n < 10) {
        printf("num:");
        scanf_s("%d", &i);
        if (i == 0)
            continue;
        sum += i;
        n++;
        /* continue jumps to here */
    }
    printf("%d", sum);

    return 0;
}

Output:

num:0    // When 0 is input, sum and n++ are not executed
num:1
num:2
num:3
num:4
num:5
num:0     // When 0 is input, sum and n++ are not executed
num:6
num:7
num:8
num:9
num:10
55

If the continue statement were not used, the above example could be written as follows:

n = 0; 
sum = 0; 
while (n < 10) { 
   scanf("%d", &i); 
   if (i != 0) { 
   sum += i; 
   n++; 
 }
}

goto Statement

The goto statement can jump to any labeled statement within a function. C99 introduced a restriction: the goto statement cannot be used to bypass the declaration of variable-length arrays.

Format:

goto label;

Labeled statement:

label: statement

If there were no break statement in C language, the following goto statement could be used to exit the loop early:

for (d = 2; d < n; d++) 
   if (n % d == 0) 
      goto done; 
   done: 
   if (d < n) 
   printf("%d is divisible by %d\n", n, d); 
  else 
   printf("%d is prime\n", n);

The goto statement was common in early programming languages, but it is rarely used in everyday C programming.

For example, the break statement can exit a switch statement, but it cannot exit a loop. The goto statement solves this problem:

while (...) { 
   switch (...) { 
   ... 
   goto loop_done; /* break won't work here */ 
   ... 
   } 
} 
loop_done: ...

The goto statement is also useful for exiting nested loops.

Program for Ledger Calculation

Many simple interactive programs are menu-based: they display a list of commands available for the user to choose from. Once the user selects a command, the program executes the corresponding action and prompts the user for the next command; this process continues until the user selects the “exit” or “stop” command.

Develop a program to maintain the balance of a ledger. The program will provide the user with a menu of options: clear account balance, credit account, debit account, display current balance, exit program. The options are represented by integers 0, 1, 2, 3, and 4, respectively. A session of the program would look like this:

When the user inputs<span>command 4</span> (i.e., exit), the program needs to exit both the switch statement and the outer loop. The break statement cannot achieve this, and we do not want to use the goto statement. Therefore, we decide to use the return statement, which will terminate the program and return control to the operating system.

*** ACME checkbook-balancing program *** 
Commands: 0=clear, 1=credit, 2=debit, 3=balance, 4=exit

Enter command: 1
Enter amount of credit: 1042.56
Enter command: 2
Enter amount of debit: 133.79
Enter command: 1
Enter amount of credit: 1754.32
Enter command: 2
Enter amount of debit: 1400
Enter command: 2
Enter amount of debit: 68
Enter command: 2
Enter amount of debit: 50
Enter command: 3
Current balance: $1145.09
Enter command: 4

cheking.c

#include <stdio.h>

int main() {
    int cmd;
    float balance = 0.0f, credit = 0.0f, debit = 0.0f;

    printf("*** ACME checkbook-balancing program ***\n");
    printf("Commands: 0=clear, 1=credit, 2=debit, ");
    printf("3=balance, 4=exit\n\n");

    for (; ;) {
        printf("Enter command: ");
        scanf_s("%d", &cmd);
        while (getchar() != '\n'); // Clear the buffer, this is important!!!
        switch (cmd) {
        case 0:
            balance = 0.0f;
            break;
        case 1:
            printf("Enter amount of credit: ");
            scanf_s("%f", &credit);
            balance += credit;
            break;
        case 2:
            printf("Enter amount of debit: ");
            scanf_s("%f", &debit);
            balance -= debit;
            break;
        case 3:
            printf("Current balance: $%.2f\n", balance);
            break;
        case 4:
            return 0;
        default:
            printf("Commands: 0=clear, 1=credit, 2=debit, ");
            printf("3=balance, 4=exit\n\n");
            break;
        }
    }

    return 0;
}

Empty Statement

A statement can be empty, meaning it has nothing but a semicolon at the end. Here is an example:

i = 0; ; j = 1;

This line contains three statements: one statement assigns a value to i, one is an empty statement, and one assigns a value to j.

The main benefit of an empty statement is to write a loop with an empty loop body. Just like the loop for finding prime numbers:

for (d = 2; d < n; d++) 
  if (n % d == 0) 
  break;

If the condition n % d == 0 is moved to the loop control expression, the loop body would become empty:

for (d = 2; d < n && n % d != 0; d++) 
 /* empty loop body */;

If a semicolon is accidentally placed after the parentheses of an if, while, or for statement, it creates an empty statement, causing the if, while, or for statement to terminate prematurely.

In an if statement, if a semicolon is placed after the parentheses, regardless of the value of the controlling expression, the action of the if statement is clearly the same:

if (d == 0);  /*** WRONG ***/ 
   printf("Error: Division by zero\n");

Because the printf function call is not within the if statement, it will execute regardless of whether d is equal to 0.

In a while statement, if a semicolon is placed after the parentheses, it will create an infinite loop:

i = 10; 
while (i > 0);    /*** WRONG ***/ 
    { 
     printf("T minus %d and counting\n", i); 
     --i; 
 }

Another possibility is that the loop terminates, but only one loop body statement is executed after the loop terminates.

i = 11; 
while (--i > 0); /*** WRONG ***/ 
  printf("T minus %d and counting\n", i);

// Output
T minus 0 and counting

In a for statement, placing a semicolon after the parentheses will cause only one loop body statement to execute:

for (i = 10; i > 0; i--); /*** WRONG ***/ 
  printf("T minus %d and counting\n", i);

// Output
T minus 0 and counting

== Exercises See You Next Time Bye! ==

Leave a Comment