Branch and loop structures or constructs are based on a logical result. In the following we consider branching, flowcharts, and looping structures.
The following outline describes one form of a conditional test. If the TEST_EXPRESSION evaluates to true then the code in BLOCK1 is executed. In handling such an expression, 'C' treats the value zero as false and any non-zero value as true. An example of such a test expression is A > 0, which returns a non-zero value if A is larger than zero.
if (TEST_EXPRESSION){ BLOCK1; }
The keyword else is used to introduce a second block of code, executed if TEST_EXPRESSION is false.
if (TEST_EXPRESSION){ BLOCK1; } else{ BLOCK2; }
It is not unusual to follow the else keyword immediately with another test, such a construct is referred to as if - else if - else. In such an arrangement the test expressions are examined in the order given. Note that the "else if" clause is not the start of a new if construct, as at most one else clause is allowed. Note the implied priority. The first test expression that is true will execute its corresponding code block. The else keyword code block is executed in the case that no previous code block executed.
if (TEST_EXPRESSION_1){ BLOCK1; } else if (TEST_EXPRESSION_2){ BLOCK2; } else { BLOCK3; }
The following example program demonstrates a complete if - else if - else type construct. Note that multiple else if clauses are possible but that at most one else clause is allowed.
/********************************************** * sign1.c - Krista Hill - Jan. 14, 2008 * Demonsrtrates if, else if, else construct *********************************************/ #include <stdio.h> #include <stdlib.h> int main() { int val; printf("Please enter an integer value: "); scanf("%d",&val); if (val > 0){ printf("Positive\n"); } else if (val < 0){ printf("Negative\n"); } else { printf("Zero\n"); } return 0; }
The if, if else, else construct, is so commonly used with a cases of single variable that the switch construct was developed. The general format is as follows. The dots indicates where extra lines may be inserted. The value in expression may be a variable or an expression that produces a simple value.
switch ( expression ){ case VALUE1: program-statements break; case VALUE2: program-statements break; · · · case VALUEN: program-statements break; default: program-statements break; }
If a case value is found that matches the expression, the program statements that follow the case statement are executed. The break statement signals the end of each case, exiting the switch construct. A case not terminated with a break statement will lead or fall through to the case that follows it, thus the second case will also be executed. Thus two cases can share one block of code. If there is no match, code following the special optional case called default is executed.
State diagrams such as the following can be implemented with a switch structure along with if, else if, else structures. The legend shows where the input X is for each state. The switch structure has an if, else if, else structure for each of the system states. This structure can implement Mealy as well as Moore type state machines. Figure 2.1: Example state diagram |
switch(state){ case 0: if (X == 0) then { state = 1; } break; case 1: if (X == 0) then { state = 2; } else { state = 0; } break; default: state = 0; break; } |
The flow chart is a simple graphical outline of an algorithm. Besides the educational value, there are situations where the flowchart is the most natural and appropriate choice for describing an algorithm. In being an abstract notion, the flowchart can be used with varying degrees of detail. Our use of flowcharts here is to enhance the presentation of C programming topics. The C langugae can be dense and hard to interpret in places. As with other forms of documentation, the flowchart should be somewhat higher level than the code being described. In drawing a flow chart resist the temptation to exactly match the instructions in your program.
A program or function usually has an entry point and an exit point. Despite that both use the oval shape, the meaning is understood in context. Either the word Start, Enter, or the name of the function is written in the entry symbol. Flowcharts with a single exit symbol have the word Exit written in the symbol.
A processing symbol is drawn with a rectangle. A single processing symbol need not correspond to only one statement or step, but it can correspond to several statements executed in sequence without branching, or it can correspond to an entire function with its own flow chart. We will be studying functions more closely, for now consider that the name in the entry point for the lower level flowchart will be written inside the processing symbol.
Some programs and functions return a code to indicate such status information as success or failure. We can abstracts the idea of such a return code by having several exit symbols. An appropriate return code word is written into each exit symbol. In the situation that a processing box corresponds to a function which returns status codes, each code corresponds to an exit point. The following is such an example of a procedure named TEST that returns two possible exit codes.
The angled box symbol is a special processing box reserved for handling input and output. The input-output box may not describe any prompt used to aid the user in providing input data.
There are three loop constructs available to the 'C' programmer.
The do-while construct is similar, but is guaranteed to perform at least one iteration. In the following example the do-while loop tests for completion after each iteration. The line numbers are not part of the program, but rather are only inserted for your reference. Predict the final value of n when the loop exits.while( LOGICAL_STATEMENT )
{
BLOCK_STATEMENTS;
}
00 /******************************** 01 * dowhile.c - Your-name-here 02 * Just a simple demonstration 03 *******************************/ 04 #include <stdio.h> 05 int main() 06 { 07 int i = 1, n = 0; 08 09 do { 10 n++; i <<= 1; 11 i &= 0x0F 12 } while (i != 0); 13 14 printf("Final n = %d",n); 15 return 0; 16 }
The for loop construct is equivalent to a special case of the while loop. The for construct is shorthand for the following code outline.
INIT; while ( LOGIC_TEST ) { // lines of 'C' code BLOCK_STATEMENTS;
ADVANCE;
}
The INIT statement initializes an index variable. The LOGICAL statement produces a true or false result, if true the code block is executed. One block statement somehow advances the index variable. The following is the outline of the corresponding for loop construct.
The figure to the right illustrates how the generic for structure
is executed.
The structure is more compact and generally is more readable.
for( INIT; LOGIC_TEST; ADVANCE ){ // lines of 'C' code BLOCK_STATEMENTS; } |
Figure 2.6: Loop iteration box use |
The following program uses a for loop construct to add the integers from 1 to 5.
00 /****************************** 01 * sum5.c - Your-name-here 02 * Form sum from one to five 03 *****************************/ 04 #include <stdio.h> 05 int main() 06 { 07 int i, sum; 08 09 sum = 0; 10 for (i = 1; i <= 5; i++) 11 { 12 sum += i; 13 } 14 printf("Sum equals %d\n",sum); 15 16 return 0; 17 }
The keyword continue is used in a loop construct to provide a mechanism to jump to the start of the next iteration. The keyword break is used to immediately exit from a loop construct.
The following example makes use of a number of topics discussed so far. The line numbers are inserted only to help in our discussion. To understand why the program produces only a list of prime factors, just work through an example on paper and see what happens.
00 /*************************************************** 01 * primes.c - Krista Hill 02 * Produce prime factors of a positive number 03 **************************************************/ 04 #include <stdlib.h> 05 #include <stdio.h> 06 int main() 07 { 08 int i, val; 09 printf("-- Prime Factor Producer --\n"); 10 printf("Enter a positive integer value: "); 11 scanf("%d", &val); 12 13 // Test if the number is zero or negative 14 if (val <= 0) { 15 printf("%d is not a positive integer\n", val); 16 exit(0); 17 } 18 19 // One is divisible into all numbers 20 else if (val == 1) { 21 printf("1 is divisible only by itself\n"); 22 exit(0); 23 } 24 25 // Repeatedly divide out the divisible primes 26 for (i = 2; i <= val; i++) { 27 while (val % i == 0) { 28 printf("%d\n",i); 29 val /= i; 30 } 31 } 32 printf("Done!\n"); 33 return 0; 34 }
The following examples uses a switch contruct, if-else constructs, simple input and output commands, and a bunch of the operators that we have discussed. The program reads in a string of characters and uses the first character in the string in a switch construct. The preprocessor directive define assigns the value 4 to the symbols MAXDEPTH.
00 /***************************************************************
01 * rpn1.c
02 * A simple RPN style calculator. A given value is pushed onto
03 * the stack. An operation removes two values and pushes the
04 * result. 'c' clears the stack and 'e' exits the program.
05 **************************************************************/
06 #include <stdio.h>
07 #include <stdlib.h>
08 #define MAXDEPTH 4
09 int main()
10 {
11 double stack[MAXDEPTH];
12 int ix, item = -1, done = 0;
13 char buff[18];
14
15 printf("+ adds, - subtracts, e exits, c clears\n");
16 while(!done) {
17 scanf("%16s",buff);
18 switch(buff[0]) {
19
20 case 'e': // exit command
21 done = 1;
22 break;
23
24 case 'c': // clear command
25 item = -1;
26 break;
27
28 case '+':
29 printf("Add\n");
30 if (item > 0) {
31 stack[item - 1] = stack[item - 1] + stack[item];
32 item--; }
33 else {
34 printf("** Requires two items on the stack\n");}
35 break;
36
37 case '-':
38 printf("Subtract\n");
39 if (item > 0) {
40 stack[item - 1] = stack[item - 1] - stack[item];
41 item--; }
42 else {
43 printf("** Requires two items on the stack\n");}
44 break;
45
46 default: // Push a value
47 if (item < MAXDEPTH - 1) {
48 stack[++item] = atof(buff); }
49 else {
50 printf("Stack Overflow\n");}
51 break;
52 } // end of switch
53
54 // display the stack
55 for (ix = item; ix >= 0; ix--) {
56 printf("%f\n", stack[ix]);
57 }
58 printf("--------\n");
59 }
60 return 0;
61 }
The atof( ) is used to convert a number given in ASCII form, to double floating point number format. This program has two curious effects, first the input string is limited to 16 characters. A number longer than 16 characters will be interpreted as two numbers. Second, an invalid entry may be interpreted as the value zero.
flag && (valx = flag);
If flag is non-zero, its value is assigned to valx.
Enter and compile the example dowhile.c. For homework insert your name in the source code, produce the source code and the program results. Provide a brief explanation why the numerical result is correct.
Enter and compile the example sum5.c. For homework insert your name in the source code, produce the source code and the program results. Provide a brief explanation why the numerical result is correct.
Consider the primes.c program listed above. To illustrate how the program produces the list of prime factors for the decimal number 60, make a table with columns for the program line number, the value in i, and the value in val. For the given line, the table lists values just before the line executes. Start your table at program line 14 and use a pair of question marks to indicate values that are not known.
Examine the program rpn1.c closely. Write new cases for division '/' and multiplication '*'. For homework submit a printout of the program, with the new cases inserted.
The program sign1.c reports the sign of a single number. Consider that the scanf function returns an int value equal to the number of matches found between the input you provide and the search string. Modify sign1.c to produce sign2.c. For homework submit the new program and a screen shot for the inputs 5, -7, 0, and then exiting with a non-integer input value.
Explain why the if, else if, else construct in sign1.c cannot be easily replaced with a switch constuct.
Please Let me know that you read my web pages.
This supplemental set of notes is written for the computer engineering students at the University of Hartford. Copyright is reserved by the author, but copies of this document may be made for educational use as-is, provided that this statement remains attached. The author welcomes corrections, comments, and constructive criticism.