Reviewing 'C' - Part 2

| Intro. | Part 0 | Part-1 | Part-2 | Part-3 | Part-4 | Part-5 |

Branch and loop structures or constructs are based on a logical result.  In the following we consider branching, flowcharts, and looping structures.

if, else if, else Type Constructs

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;
}

Switch Construct

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;
}

Flowcharts

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. 


Figure 2.2: Entry and exit symbols

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. 


Figure 2.3: Processing box

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.


Figure 2.4: Processing box with multiple exits

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.


Figure 2.5: Input-output box

Looping Constructs

There are three loop constructs available to the 'C' programmer. 

First consider the while construct.  As illustrated earlier in the program intest.c, as long as the Boolean test expression is true, the corresponding block of code will repeatedly execute.  Any non-zero integer value is regarded as true.  Each time the code block executes, is referred to as an iteration.  The following is the general outline of the while loop.  The LOGICAL_STATEMENT produces a single true/false result.  Again the BLOCK_STATEMENTS are executed for as long as the logical statement is true.
while( LOGICAL_STATEMENT )
{
BLOCK_STATEMENTS;
}
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.
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. 


Prime Factors Example

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 }

RPN Calculator Example

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.

Conditional Evaluation

In 'C', logical expressions are evaluated only as far as necessary, to produce a result.  This property is exploited to condition the evaluation of an expression.  If the expression to the left of a logical-OR ( || ) is true, the right side is not evaluated and the result is true.  Conversely, if the expression to the left of a logical-AND ( && ) is false, the right side is not evaluated, and the result is false

flag && (valx = flag);

If flag is non-zero, its value is assigned to valx.

Homework Problems:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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. 
Original Author: Krista Hill kmhill@hartford.edu
Copyright Date: Sun Jan 26 14:50:06 EST 2003
Last revised: Mon Feb 26 01:06:07 EST 2007