Tuesday, September 4, 2012

CPro1 Lecture: Program Controls


_______________________________ 6 ________________________
                                                    Program Controls
OBJECTIVE
Chapter 4, “Statements, Expressions, and Operators,” covered the if statement, which gives you some control over the flow of your programs.  Many times, though, you need more than just the ability to make ture and false conditions.  This chapter introduces three new ways to control the flow of the program.  You will learn
·  What an array is.
·  The definition of single- and multidimensional numeric arrays.
·  How to declare and initialize arrays.
·  How to use simple arrays.
·  How to use for, while  and do..while loops to execute statements multiple times.
·  How you can nest program control statements.
·  How to use the break and continue statements.
·  What infinite loops are and why you might use them.
·  What the goto statement is and why you should avoid it.
·  How to use the switch statement.
·  How to control program exits.
·  How to execute function automatically on program completion.
·  How to execute system commands in your program.

What Is An Array ?
An array is an indexed group of data storage locations that have the same name and are distinguished from each other by a subscript, or index --- a number following the variable name, enclosed in brackets.  Like other C variables, arrays must first be declared.  An array declaration includes both the data type and the size of the array (the number of elements in the array).  For example, the statement
int data[1000];
declares an array named data that is type int and has 1,000 elements.  The individual elements are referred to by subscript as data[0] through data[999].  The first element is data[0] --- not data[1].  In other languages, such as BASIC and Pascal, the first element of an array is 1; this is not true in C.
Each element of this array is equivalent to a normal integer variable and can be used the same way.  The subscript of an array can be another C variable, such as in this example:
int data[1000];
int count;
count = 100;
data[count] = 12;
DO / DON’T
DON’T  declare arrays with subscripts larger than you will need; it wastes memory. is more readable.
DON’T  forget that in C, arrays are referenced starting with subscript 0 not 1.
Single-Dimensional Arrays
A single-dimensional array is an array that has only a single subscript.  A subscript is a number in brackets following an array’s name.  This number can identify the number of individual elements in the array.  For example,
float expenses[12];
expenses is a single-dimensional array that contains twelve elements.  Each of the twelve elements is the exact equivalent of a single float variable.  All of C’s data types can be used for array.  C array elements are always numbered starting at 0, so the twelve elements of expenses are numbered 0 - 11.
An array element can be used in your program anywhere a nonarray variable of the same type can be used.  Individual elements of the array are accessed by using the array name followed by the element subscript enclosed in square brackets.  Here are some examples:
expenses[1] = 89.95;         /* store the value 89.95 in the second array element*/
expenses[10]= expenses[11];         /* assign the value that is stored in array element                                                      expenses[11] to array element expenses[10]*/
When you use arrays, keep the element numbering scheme in mind: In an array of n elements, the allowable subscripts  range from 0 to n-1. If you use the subscript value n, you may get program errors. The C compiler does not recognize whether your program uses an array subscript that is out of bounds. Your program compiles & links, but out-of-range subscripts generally produce erroneous results.
DO / DON’T
DON’T  forget that array subscripts start at element 0.
DO      use array instead of creating several variables that store the same thing.(Fro example, if you want to store total sales for each month of the year, create an array with twelve elements to hold expenses, rather than creating an expense variable for each month.)
Multidimensional Arrays
A multidimensional array has more than one subscript. A two-dimensional array has two subscripts, a three-dimensional array has three subscripts, and so on. There is no limit to the number a C array can have. There is a limit on total array size, however. Because of the way memory  models works, you should not try to create more than 64K of data variables for now.
For example, you might write a program that plays checkers. The checkerboard contains 64 squares arranged in eight rows & eight column. Your program could represent the board as two-dimensional array, as follows:
int checkers[8][8];
The resulting array has 64 elements:  checker[0][0], checker[0][1], checker[0][2]...checker[7][6], checker[7][7].
Similarly, a three-dimensional array could be thought of as a cube.  Four-dimensional arrays (and higher) are probably best left to your imagination.  All arrays, no matter how many dimensions they have, are stored sequentially in memory.
Naming and Declaring Arrays
Syntax   :    typename arrayname[elements];
Where   :     typename is the type of data each array element will hold.
arrayname is the name of the array.  It must be unique.  The rules in assigning names to arrays are the same as for variable names.
Example:    int months[12];

DO / DON’T
DO       use #define statements to create constants that can be used when declaring arrays.  Then you can change easily the number of elements in the array.
DO      avoid multidimensional arrays with more than three dimensions.  Remember multidimensional arrays can get very big, very quickly.
Initializing Arrays
You can initialize all or part of an array when you first declare it.  Follow the array declaration with an equal sign and a list of values enclosed in braces and separated by commas.  The listed values are assigned in order to array elements starting at number 0.  Here are some examples:
int array[4] = {100,200,300,400};   /* assigns the value 100 to array[0], 200 to array[1], 300                                           to array[2], and 400 to array[3]. */
int array[] = {100,200,300,400};    /* if you omit the array size, the compiler creates an array                                 just large enough to hold the initialization values */
int array[10] = {1,2,3};            /* you can also include too few initialization, however if                                         you do not explicitly initialize an array element, you                                            cannot be sure what value it holds when the program runs */
int array[3] = {1,2,3,4,5};         /* WRONG.  If you include too many initializers (more                                         initializers than array element), the compiler detects an                                  error */
Multidimensional arrays also can be initialized.  The list of initialization value is assigned to array elements in order, with the last array subscript changing first.  For example:
int array[4][3] = {1,2,3,4,5,6,7,8,9,10,11,12};
int array[4][3] = { {1,2,3} , {4,5,6} , {7,8,9} , {10,11,12} };
both results in the following assignments:
array[0][0] is equal to 1
array[0][1] is equal to 2
array[0][2] is equal to 3
array[1][0] is equal to 4
array[1][1] is equal to 5
array[1][2] is equal to 6
. . .
array[3][1] is equal to 11
array[3][2] is equal to 12
Controlling Program Execution
The default order of execution in a C program is top-down.  Execution starts at the beginning of the main()function and progresses, statement by statement until the end of main()is reached.  However, this order is rarely encountered in real C programs.  The C language includes a variety of program control statements that enable you to control the order of program execution.
The for Statement
Description:  The for statement is a C programming construct that executes a block of one or more statements a certain number of times.  It is sometimes called the for loop because program execution typically loops through the statement more than one time.
Syntax:
for (initial; condition; increment/decrement)
       statement(s)
Where:
initial is any valid C expression.  It is usually an assignment statement that sets a variable to a particular value.
condition is any valid C expression.  It is usually a relational expression.  When condition evaluates to   false (zero), the    for statement terminates and execution passes to the first statement following statement(s); otherwise, the C statement(s) in statement(s) are executed.
increment/decrement  is any valid C expression.  It is usually an expression that increments or decrements a variable initialized by the initial expression.
statement(s)are the C statements that are executed as long as the condition remains true.
Example 1:
/* Prints the value of x as it counts from 0 to 9 */
int x;
for (x = 0; x < 10; x ++)
       printf(“\nThe value of x is %d”, x);
Example 2:
/* Obtains values from the user until 99 is entered */
int nbr=0;
for ( ; nbr!=99; )
         scanf(“%d“, &nbr);
Example 3:
/* enables user to enter up to 10 integer values            */
/* values are stored in an array named value.  If 99 is     */
/*          entered, the loop stops                                */
int value[10];
int ctr,nbr=0;
for ( ctr = 0; ctr < 10 && nbr != 99; ctr ++) {
     puts(“Enter a number, 99 to quit “);
     scanf(“%d”, &nbr);
     value[ctr] = nbr;
}
Nesting for Statements
A for statement can be executed within another for statement.  This is called nesting.  By nesting for statements, some complex programming can be done.
Listing 6.1.  Demonstration of nested for statements.
1:   /* Demonstrates nesting two for statements */
2:
3:   #include <stdio.h>
4:
5:   void draw_box(int row, int column)
6:
7:   main()
8:   {
9:       draw_box(5,10);
10:  }
11:
12:  void draw_box(int row, int column)
13:  {
14:      int col;
15:      for ( ; row > 0; row --)
16:      {
17:       for (col=column; col > 0; col --)     
18:       printf(“X”);
19:       printf(“\n”);
20:      }
21:  }
The output for Listing 6.1 is
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
DO / DON’T
DON’T  put too much processing in the for statement.  Although you can use the comma separator, it is often clearer to put some of the functionality into the body of the loop.
DO       remember the semicolon if you use a for with a null statement.  Put the semicolon placeholder on a separate line, or place a space between it and the end of the for statement.
            for(count = 0; count < 1000; array[count] = 50) ;
       /* note space */
The while Statement
Description:  The while statement, also called the while loop, executes a block of statements as long as a specified condition is true.
Syntax:
while ( condition )
       statement(s)
Where:
condition is any valid C expression, usually a relational expression.  When condition evaluates to false (zero), the while statement terminates and execution passes to the first statement following statement(s); otherwise, the C statement(s) in statement(s) are executed.
statement(s)are the C statement(s) that are executed as long as the condition remains true.
Example 1:
int x = 0;
while (x < 10)
{
       printf(“\nThe value of x is %d”, x);
       x++;
}
Example 2:
/* get numbers until you get one greater than 99 */
int nbr=0;
while ( nbr <= 99)
       scanf(“%d”,&nbr);
Example 3:
/* enables user to enter up to 10 integer values            */
/* values are stored in an array named value.  If 99 is     */
/*          entered, the loop stops                                */
int value[10];
int ctr,nbr=0;
while ( ctr < 10 && nbr != 99)
{
     puts(“Enter a number, 99 to quit”);
     scanf(“%d”, &nbr);
     value[ctr] = nbr;
     ctr++;
}
Nesting while Statements
Just like the for and if statements, while statements can also be nested.
Listing 6.2.  Demonstration of nested  while statements.
1:   /* Demonstrates nested while statements */
2:   #include <stdio.h>
3:   int array[5];
5:   main()
6:   {
7:       int ctr = 0, nbr = 0;
8:       printf(“This program prompts you to enter 5 numbers\n”);
9:       printf(“Each number should be from 1 to 10\n”);
10:      while ( ctr < 5 )
11:      {
12:       nbr = 0;
13:       while ( nbr < 1 || nbr > 10 )
14:       {
15:         printf(“\nEnter number %d of 5: “,ctr + 1);
16:         scanf(“%d”,&nbr);
17:       }
18:       array[ctr] = nbr;
19:       ctr++;
20:      }
21:      for (ctr = 0; ctr < 5; ctr ++)
22:       printf(“\nValue %d is %d, ctr + 1, array[ctr] );
23:  }
The output for Listing 6.2 is
This program prompts you to enter 5 numbers
Each number should be from 1 to 10
Enter number 1 of 5 : 3
Enter number 2 of 5 : 6
Enter number 3 of 5 : 3
Enter number 4 of 5 : 9
Enter number 5 of 5 : 2
Value 1 is 3
Value 2 is 6
Value 3 is 3
Value 4 is 9
Value 5 is 2
DO / DON’T
DON’T  use the following convention if it is not necessary.
            while ( x )
       Instead use
       while ( x!= 0 )
            Although both work, the second is clearer when debugging the code.  When compiled, these produce virtually the same code
DO       use the for statement instead of the while statement if you need to initialize and increment within your loop.  The for statement keeps the initialization, condition, and increment statements all together.  The while statement does not.
The do . . while Loop
Description:  C’s third loop construct is the do..while loop, which executes a block of statements as long as a specified condition is true.  The do..while loop tests the condition at the end of the loop rather that at the beginning as is done by the for loop and the while loop.
Syntax:
do
{
   statement(s)
} while (condition);
Where:
condition is any valid C expression, usually a relational expression.  When condition evaluates to false (zero), the while statement terminates and execution passes to the first statement following the while statement; otherwise, the program loops back to the do and the C statement(s) in statement(s) are executed.
statement(s)are either a single C statement or a block of statements that are executed the first time through the loop and then as long as condition remains true.
Example 1:
/* prints even though condition fails */
int x = 10;
do
{
  printf(“\nThe value of x is %d”, x);
} while (x!=10);
Example 2:
/* get numbers until you get one greater than 99 */
int nbr;
do
{
   scanf(“%d”,&nbr);
} while (nbr <= 99);
Example 3:
/* enables user to enter up to 10 integer values              */
/* values are stored in an array named value.  If 99 is       */
/*     entered, the loop stops                                */
int value[10];
int ctr=0 ,nbr;
do
{
   puts(“Enter a number, 99 to quit”);
   scanf(“%d”, &nbr);
   value[ctr] = nbr;
   ctr++;
} while ( ctr < 10 && nbr != 99 );
Nested Loops
The term nested loop refers to a loop that is contained within another loop.  C places no limitation on the nesting of loops except that each inner loop must be enclosed completely in the outer loop; you cannot have overlapping loops.
DO / DON’T
DON’T  try to overlap loops.  You can nest them, but they must be entirely within each other.
DO       use the do..while statement when you know that a loop should be executed at least once.
More Program Control
Ending Loops Early
The break Statement
Description:  break is used inside a loop or switch statement.  It causes the control of a program to skip past the end of the current loop (for, while, or do..while) or switch statement.  No further iterations of the loop execute; the first command following the loop of switch statement executes.
Syntax:
   break;
Example :
   #include <stdio.h>
   int x;
   printf(“Counting from 1 to 10\n”);

   /* having no condition in the for loop will cause it to loop forever */
   for (x = 1; ; x++ )
   {
       if (x == 10)         /* This checks for the value of 10 */
       break;               /* This ends the loop */
       printf(“\n%d”, x);
   }
The continue Statement
Description:  continue is used inside a loop.  It causes the control of a program to skip the rest of the current iteration (for, while, or do..while) of a loop and starts the next iteration.
Syntax:
   continue;
Example :
   #include <stdio.h>
   int x;
   printf(“Printing only the even numbers from 1 to 10\n”);

   for (x = 1; x <= 10; x++ )
   {
       if (x % 2 != 0)      /* See of the number is NOT even */
       continue;            /* Get next instance x */
       printf(“\n%d”, x);
   }
The goto Statement
Description:  The goto statement is one of C’s unconditional jump, or branching, statements.  When program execution reaches a goto statement, execution immediately jumps, or branches, to the location specified by the goto statement.  The statement is unconditional because execution always branches when a goto statement is encountered; the branch does not depend on any program conditions (unlike if statements, for example).
Syntax:
   goto target;
Where:
   target is a label statement that identifies the program location where execution is to branch.  A label statement consists of an identifier followed by a colon and a C statement.
   location1:  a C statement;
      If you want the label by itself on a line, you can follow it with the null statement (a semicolon by itself).
   location1: ;
      A goto statement and its target label must be in the same function, although they can be in different blocks.
Example :
   /* Demonstrates the goto statement */
   #include <stdio.h>
   main()
   {
         int n;

   start: ;
  
         puts(“Enter a number between 0 and 10: “);
         scanf(“%d”, &n);
         if (n < 0 || n > 10)
               goto start;
         else if (n == 0)
               goto location0;
         else if (n == 1);         
               goto location1;
         else
                goto location2;

   location0: ;
         puts(“You entered 0.”);
         goto end;
   location1: ;
         puts(“You entered 1.”);
         goto end;
   location2: ;
         puts(“You entered something between 2 and 10.”);
   end: ;
   }
Notes :  It is strongly recommended that you never use the goto statement anywhere in your programs.  There are two reasons:
·         You don’t need it.  Seldom can you find programming tasks that require the goto statement.  You always can write the needed code using C’s other branching statements.
·         It’s dangerous.  The goto statement may seem like an ideal solution for certain programming problems, but its easy to abuse.  When program execution branches with a goto statement, no record is kept of where the execution came from, so execution can weave willy-nilly in the program.  This type of programming is known in the trade as spaghetti code.
Now, some careful programmers can write perfectly fine programs that use goto.  There might be situations where a judicious use of goto is the simplest solution to a programming problem.  It is never the only solution, however.  If you’re going to ignore this warning, at least be careful!
DO / DON’T
DO       avoid using the goto statement if possible.
DON’T  confuse break and continuebreak ends a loop, whereas continue starts the next iteration.
The switch Statement
Description:  The switch statement allows for multiple branches from a single expression.  It is more efficient asn easier to follow than a mutileveled if statement.  A switch statement evaluates an expression an expression and then branches to the case statement that contains the template matching the expression’s result.  If no template matches the expression’s result, control goes to the default statement.  If there is no default statement, control goes to the end of the switch statement.
      Program flow continues from the case statement down unless a break statement is encountered.  If a break statement is encountered, control goes to the end of the switch statement.
Syntax:
   switch (expression)
   {
         case template_1:  statement(s);
         case template_2:  statement(s);
         . . .
         case template_n:  statemennt(s);
         default:  statement(s);
   }
Example 1:
      switch (letter)
   {
         case ‘A’:
         case ‘a’:  printf(“You entered A”);
                   break;
         case ‘B’:
         case ‘b’:  printf(“You entered B”);
                   break;
         . . .
         default:   printf(“I don’t have a case for %c”, letter);
   }
Example 2:
      switch (number)
   {
         case 0:  puts(“Your number is 0 or less”);
         case 1:  puts(“Your number is 1 or less”);
         case 2:  puts(“Your number is 2 or less”);
         case 3:  puts(“Your number is 3 or less”);
         . . .
         . . .
         case 99: puts(“Your number is 99 or less”);
                 break;
         default:
   }

Infinite Loops
What is an infinite loop and why you would want one in your program?  An infinite loop is one that, left to its own devices, would run forever.  It can be a for loop, a while loop, or a do..while loop.  For example, if you write
while (1)
{
  /* additional code goes here */
}
you create an infinite loop.  The condition that the while tests is the constant 1, which is always true and cannot be changed by program execution.  Therefore, on its own, the loop never terminates.
In the last section, however, you saw that the break statement can be used to exit a loop.  Without the break statement, an infinite loop would be useless.  With break, you can take advantage of infinite loops.
You can also create an infinite for loop or an infinite do..while loop, as follows:
for (; ;)
{
  /* additional code goes here */
}
do
{
  /* additional code goes here */
} while (1)
An infinite loop can be used to test many conditions and determine whether the loop should terminate.  It might be difficult to include all the test conditions in parentheses after the while statement.  It might be easier to test the conditions individually in the body of the loop, and then exit by executing a break as needed.
Listing 6.3.  Using an infinite loop and switch statement to implement a menu system.
1: /* Demonstrates using an infinite loop and switch statement to implement a menu system */
2: #include <stdio.h>
3: #include <stdlib.h>
4: int menu(void)
5:
6: main()
7: {
8:   int choice;
9:   while (1)
10:  {
11:    /* Get the user’s selection and branch based on the input */
12:    switch ( menu() )
13:    {
14:      case 1: {
15:       puts(“\nExecuting choice 1.”);
16:       delay(150000);    
17:      }     
18:      case 2: {
19:       puts(\nExecuting choice 2.”);
20:       delay (150000);
21:      }
22:      case 3: {
23:       puts(\nExiting program now.”);
24:       delay (150000);
25:       exit(0);
26:      }
27:      default:{
28:       puts(\Invalid choice, try again.”);
29:       delay (150000);
30:      }
31:    }
32:  }
33: }
34:
35: int menu(void)
36: /* Displays a menu and inputs user’s selection */
37: {
38:  int reply;
39:  puts(“Enter 1 for task A.”);
40:  puts(“Enter 2 for task B.”);
41:  puts(“Enter 3 to exit program.”);
42:  scanf(“%d”, &reply);
43:  return reply;
44: }
DO / DON’T
DON’T  forget to use break statements if your switch statements need them.
DO       use a default case in a switch statement even if you think you have covered all possible cases.
DO       use a switch statement instead of an if statement if there are more than two conditions being evaluated for the same variable.
DO       line up your case statements so that they are easy to read.
Exiting the Program
A C program normally terminates when execution reaches the closing brace of the main() function.  However, you can terminate a program at any time by calling the library exit().  You also can specify one or more functions to be automatically executed at termination.
The exit() Function
Description:  The exit() function terminates program execution and returns control to the operating systrem.  This function takes a single type int argument that is passed back to the operating system to indicate the success or failure of the program.
Syntax:
   #include <stdlib.h>
   exit (status);
Where:
   status is an integer that indicates the success or failure of the program.  If status has a value of 0, it indicates that the program terminated normally.  A value of 1 (or higher) indicates that the program terminated with some sort of error.
The atexit() Function
Description:  The atexit() function is used to specify, or register, one or more functions that are automatically executed when the program terminates.  This function might not be available on a non-DOS systems.  You can register as many as 32 functions; at program termination, they are executed in reverse order.  The last function registered is the first function executed.  When all the functiond registered by the atexit() have been executed, the program terminates and returns control to the operating system.
Syntax:
   #include <stdlib.h>
   int atexit ( void (*) (void) );
Note:
   atexit() takes a function pointer as its argument.  Functions registered with atexit() must have a return type of void.
Listing 6.4.  Using the exit() and atexit() functions.
1:   /* Demonstrates the exit() and atexit() functions */
2:   #include <stdio.h>
3:   #include <stdlib.h>
4:   #include <time.h>
5:  
6:   void cleanup( void )
7:  
8:   main()
9:   {
10:    int reply;
11:    /* Register the function to be called at exit. */
12:   
13:    atexit(cleanup);
14:   
15:    puts(“Enter 1 to exit, any other to continue.”);
16:    scanf(“%d”, &reply);
17:
18:    if (reply == 1)
19:    exit(1);
20:   
21:    /* Pretend to do some work. */     
22:    for (reply=0; reply < 5; reply++)
23:    {
24:      puts(“Working...”)
25:      delay(150000);
26:    }
27:  }
28:
29:  void cleanup(void)
30:  {
31:    puts(“\nPreparing for exit...”);   
32:    delay(150000);
33:  }
Executing Operating System Commands in a Program
The atexit() Function
Description:  The system() function enables you to execute operating system commands in a running C program.  This can be useful, allowing you to read a disk’s directory listing or format a disk without exiting the program.  After the operating system command is executed, execution returns to the program at the location immediately following the call to system().  If the command you pass to system() is not a valid operating system command, you get a Bad command or file name error message before returning to the program.
Syntax:
   #include <stdlib.h>
   system (command)
Example :
   #include <stdlib.h.>
   #include <stdio.h>

   main()
   {
       char input[40];
       while (1)
       {
         /* Get the user’s command */
         puts(“\nInput the desired DOS command, blank to exit.”);
         gets(input);
        
         /* Exit if a blank line was entered */
         if ( input[0] == ‘\0’ )
            exit(0);

         /* Execute the command */
         system(input);
       }
   }