Previous: 4.3.1 The switch Statement
Up: 4.3 New Control Constructs
Next: 4.3.3 The continue Statement
Previous Page: 4.3.1 The switch Statement
Next Page: 4.3.3 The continue Statement
C provides a statement for circumstances like this; the break statement. A break can only be used within a switch statement or any looping statement (so far we have only seen while). Its syntax is very simple:
To fix our problem above,
Figure 4.20 shows
an implementation of print_next() using a switch statement.
Once control passes to a label, the control continues down the line of statements until the break statement is encountered. In the above case, if c is 'Z', then an 'A' is printed and the switch statement is terminated. Similarly, if c is 'z', then 'a' is printed and the control passes to the next statement after the switch. If there is no match, then the control passes to the default label, and a character with value c + 1 is printed. The switch statement ends at this point anyway, so no break is required.
Here is a sample session with the program after encrypt.c and chrutil.c are compiled and linked.
This use of the switch statement with break statements in
the various cases is a common and efficient way to implement a
multiway branch in C.
For example,
we can now reimplement our print_category() function from
Figure 4.4 as shown in Figure 4.21.
As mentioned above, the break statement can also be used to terminate a loop. Let us consider our previous word extraction task: reading text input and printing each word in the text (see Figure 4.16). However, now we will consider non-printable characters other than white space and the end of file marker as invalid. They will represent an error in the input and we will use a break statement to abort the program.
For this task, we will no longer count characters, words, and lines, simply extract words and print them, one per line. In our previous algorithm, each iteration of the loop processed one character and we used a flag variable, inword to carry information from one iteration to the next. For this program we will modify our algorithm so that each iteration of the loop will process one word. Each word is found by first skipping over leading delimiters, then, as long as we read printable, non-delimiter characters, we can print the word. The character terminating the word must be a delimiter unless it is a non-printable character or we have reached the end of file. In either of those cases, we abort the program, printing a message if a non-printable character was encountered. Otherwise, we print the newline terminating the word and process the next word. Here is the revised algorithm with the code shown in Figure 4.22.
while there are more characters to read skip over leading delimiters (white space) while character is legal for a word print character read next character if EOF, terminate the program if character is non-printable, print a message and abort the program print a newline ending the word
The program uses two functions: delimitp() tests if the argument is a delimiter, and illegal() tests if the argument is not a legal character (printable or a delimiter). They are in the source file chrutil.c; their prototypes are in chrutil.h. We have already defined delimitp() (see Figure 4.15). We will soon write illegal().
In the main loop, we skip over leading delimiters with a while loop, and then, as long legal ``word'' characters are read we print and read characters. If either of these loops terminates with EOF, the loop is terminated by a break statement and the program ends. (Note, if EOF is detected while skipping delimiters, the word processing loop will be executed zero times). If a non-printable, non-delimiter character is found, the program is aborted after a message is printed to that effect. Otherwise, the word is ended with a newline and the loop repeats.
Function illegal() is easy to write: legal characters are printable (in the ASCII range 32 through 126) or white space. Here is the function and its prototype.
/* File: chrutil.c - continued Header Files: tfdef.h, chrutil.h */ /* Function tests if c is printable. */ int illegal(char c) { if (IS_PRINT(c) || IS_WHITE_SPACE(c)) return FALSE; return TRUE; }/* File: chrutil.h - continued */
#define IS_PRINT(c) ((c) >= 32 && (c) < 127)
int illegal(char c); /* Tests if c is legal. */
We have also added the macro IS_PRINT to the header file. The program file words.c and the source file chrutil.c can now be compiled and linked. A sample session when the program is executed is shown below.
It is also possible, though not advisable, to use a break statement to terminate an otherwise infinite loop. Consider the program fragment:
n = 0; while (1) { n = n + 1; if (n > 3) break; printf("Hello, hello, hello\n"); } printf("Print statement after the loop\n");The loop condition is the constant 1, which is always True so the loop body will be repeatedly executed, n will be incremented, and the message printed, until n reaches 4. The condition (n > 3) will now be True, and the break statement will be executed. This will terminate the while loop, and control passes to the print statement after the loop. If the if statement containing the break statement were not present, the loop would execute indefinitely.
While it is possible to use a break statement to terminate an infinite loop, it is not a good practice because use of infinite loops makes program logic hard to understand. In a well structured program, all code should be written so that program logic is clear at each stage of the program. For example, a loop should be written so that the normal loop terminating condition is immediately clear. Otherwise, program reading requires wading through the detailed code to see how and when the loop is terminated. A break statement should be used to terminate a loop only in cases of special or unexpected events.