************* BACK AND FORTH PAGING SUBROUTINE ************

PAGEFLOP

If they want to quit, do so
 If They want to quit subsession, Do SO!
  Decrement LOCAL and GLOBAL Page Counters

FORWARD

  Increment LOCAL and GLOBAL Page Counters
   *************** END PAGEFLOP *********************
  ****** CHAPTER INTERNAL SELECTOR ALGORITHM ******

SELECTOR

   Reset Local Page Counter

SELAGAIN

 CHECK IF ONLY A <CR>

WRONGSEL

YOUR SELECTION IS NOT IN THE 0 - #SELIMIT  RANGE  Please try again

AANVANG

Copyright CourseWare Technologies Inc., 1985-88


Lesson - 12


 ADVANCED C CONCEPTS 

P1

Advanced C Concepts|Topics to Learn|12-0|10,48
  #                  Topic
 ---                -------
  1   -   Using Command Line Arguments
  2   -   Command Line Arguments Review
  3   -   Performing Error Handling
  4   -   The Union Concept
  5   -   Performing Bit Field Manipulation
  6   -   Using Pointers to Functions
  7   -   Second Review
  0   -   Return to the Main Menu

P2

Advanced C Concepts|Using Command Line Arguments|12-1.1|16,54
     Command line arguments are the means to pass
the arguments to the main() program, similar to the
arguments passed to a function


     When a program or a command is invoked, the first 
word in the command line is the executable UNIX 
program; the rest of the words are the actual 
arguments to that program.  For example,

 cat  file_1  file_2  file_3 

will invoke the program cat and pass to it the three 
command line arguments:

file_1, file_2, and file_3.

P3

Advanced C Concepts|Using Command Line Arguments|12-1.2|10,54
     The command line arguments are represented in 
the main() function with two variables:


      argc  the number of arguments the program was 
            invoked with.  (The program name is the first
            argument.)

      argv  the pointer to the array of character 
            strings that contains the arguments.

P4

Advanced C Concepts|Using Command Line Arguments|12-1.3|10,54
In the command line:

 cat  file_1  file_2  file_3 

argc = 4, and argv[0] is the name by which the program 
was invoked.  They are declared as:

                int    argc;

                char *argv[];

P5

Advanced C Concepts|Using Command Line Arguments|12-1.4| 10 , 58
     The following example demonstrates command line
arguments in a C program.  The task of the program is
to concatenate the specified files.  For example, if 
the program name is concat, the command line would 
look like this:

 concat  file_1  file_2  file_3  >  destin.dat 

The three files would be written one after another into 
the destination file destin.dat.

P6

Advanced C Concepts|Using Command Line Arguments|12-1.5| 7 , 43
On the other hand, if the command were:

concat  >  destin.dat 

then the standard input would be written to

destin.dat

P7

Advanced C Concepts|Using Command Line Arguments|12-1.6|17,54
The function that does file copying is filecopy().
For the first command line, the array of arguments 
may be represented as follows:

                      ----------
                    0 | concat |
                      ----------
                    1 | file_1 |
                      ----------
                    2 | file_2 |
                      ----------
                    3 | file_3 |
                      ----------

Since argv is initially pointing to concat the
statement *++argv will move the pointer to the
next element, i.e., file_1, and so on.

P8

Advanced C Concepts|Using Command Line Arguments|12-1.7|12,54
/* Command Line Arguments, An Example */

/*  The task is to concatenate files specified on the 
    command line and store the result in the destination 
    file and to display the result on the standard output 
    for verification.                   */

#include <stdio.h>

main(argc, argv)         /* merge files */
    int argc;        /* number of C_L_A */
    char *argv[];

P9

Advanced C Concepts|Using Command Line Arguments|12-1.8|18,58
{	/* Command Line Arguments, An Example */

   FILE *fps, *fpd, *fopen();
   if ((fpd = fopen("destin.dat","w")) != NULL)
       if (argc == 1)   /* no args: copy standard input */
           filecopy(stdin,fpd);
   else {
       while (--argc > 0)
       if ((    fps = fopen(*++argv, "r")) == NULL) {
           printf("cat: can't open %s\n", *argv);
           break;
       }
       else {
            filecopy(fps, fpd);
            fclose(fps);
       }
       fclose(fpd);
   }  }

P10

Advanced C Concepts|Using Command Line Arguments|12-1.9|14,53
/* Command Line Arguments, An Example */

filecopy(fps,fpd)      /* append the source file to
                           the destination file and
                           verify the result         */
    FILE *fps, *fpd;
{
    int c;

    while ((c = getc(fps)) != EOF) {
        putc(c, fpd);
        putchar(c);
    }
}

P11

Advanced C Concepts|Performing Error Handling|12-3.1|17,54
     Every active C program has three file pointers 
assigned to it (that is, it has three files automatically 
opened):

       stdin   the standard input file pointer
      stdout   the standard output file pointer
      stderr   the standard error file pointer
      
      
     If a program encounters some error conditions 
it will normally write the diagnostic messages to the 
standard error, stderr.


     If possible, the output written to the standard 
error will appear on the user's terminal, the standard 
output.

P12

Advanced C Concepts|Performing Error Handling|12-3.2|13,54
    There are system calls associated with 
diagnostic error handling:

exit()   terminates the program execution when it is
          called.  The argument to exit() signals a 
          status condition for program exit.  A status 
          condition 0 signifies normal exit.  The function 
          itself calls fclose() for each open output 
          file to flush out any buffered output, then it 
          calls _exit().

_exit()  causes immediate termination without buffer 
          flushing.

P13

Advanced C Concepts|Performing Error Handling|12-3.3|11,54
The following example, identical in mechanics to an 
earlier one, shows how the diagnostic conditions are 
typically handled from C programs running under the 
UNIX operating system.  A generic file analog of 
printf(), called fprintf(), is used to write the 
diagnostic message to the standard error file stderr, 
which, if possible, is also written to the standard 
output.  Note also the use of the system call exit() 
which will terminate the program. The argument to 
exit() is the value returned by the special shell 
variable $?.  An argument other than 0 is an error exit.

P14

Advanced C Concepts|Performing Error Handling|12-3.4|9,48
/* Error Handling, An Example */

Using stderr() and exit() with
the program in Example 12.1

#include <stdio.h>
main(argc, argv)         /* merge files */
    int argc;        /* number of C_L_A */
    char *argv[];

P15

Advanced C Concepts|Performing Error Handling|12-3.5|17,59
/* Error Handling Example (continued) */
{
 FILE *fps, *fpd, *fopen();

 if ((fpd = fopen("destin.dat","w")) == NULL) {
   fprintf(stderr, "cat: can't create \"destin.dat\" file");
   exit(1);
 }
 else {
   if (argc == 1)   /* no arguments, copy standard input */
      filecopy(stdin,fpd);
   else {
      while (--argc > 0)
   if ((    fps = fopen(*++argv, "r")) == NULL) {
      fprintf(stderr,"cat: can't open %s\n", *argv);
      exit(1);                        /* diagnostic exit */
   }

P16

Advanced C Concepts|Performing Error Handling|12-3.6|11,46
/* Error Handling Example (continued) */

        else {
             filecopy(fps, fpd);
             fclose(fps);
        }
        fclose(fpd);
    }
    exit(0);            /* correct exit */
    }
}

P17

Advanced C Concepts|Performing Error Handling|12-3.7|13,58
/* Error Handling Example (continued) */

filecopy(fps, fpd)     /* append the source file to the
                 destination file and verify the result */
    FILE *fps, *fpd;
{
    int c;

    while ((c    = getc(fps)) !=    EOF) {
        putc(c, fpd);
        putchar(c);
    }
}

P18

Advanced C Concepts|The Union Concept|12-4.1|9,50
     A union is a heterogeneous data structure 
which may hold elements of different types, one 
at a time.


     It is the user's responsibility to keep track 
of which variable the union currently holds.


     Unions may not be initialized!

P19

Advanced C Concepts|The Union Concept|12-4.2|14,54
     The syntax for union declaration, union variable 
referencing, and union representation, is almost 
identical to that of structures, e.g.:

           union union_tag {
               char typ_char;
               int     typ_int;
               float typ_float;
               double typ_double;
           };


     The size of a union is the size of its largest
element!

P20

Advanced C Concepts|The Unions Concept|12-4.3|16,58
The following example illustrates unions in a C program.  
The program mechanics are rather complicated since we're
dealing with structures, pointers to structures, and the 
unions.  Note that the structure of type struct uni_struct 
is composed of a union variable uni_var and a pointer to 
the variable of type struct uni_struct (the same as the 
structure)--a classic case of self-referential structures.
When the function add_entry() is called, it receives the
union variable entry (the new entry) and a pointer to 
the current structure in the list, current_entry.   Note 
also how the space for the new variable is allocated and 
the cast used to obtain the proper type.  Finally, the new 
structure is filled, added to the list, and the current 
pointer is updated and returned to the calling function.  
Note also that the function type and the type of the 
ptr are identical.

P21

Advanced C Concepts|The Union Concept|12-4.4|13,54
add_entry() Program Example

The function add_entry() adds a new structure entry 
to a linked list of various types of variables.  The 
entries/values are passed to the function in the form 
of a union.

                 union    union_tag {
                   char typ_char;
                   int  typ_int;
                   float typ_float;
                   double typ_double;
                 };

P22

Advanced C Concepts|The Union Concept|12-4.5|11,54
add_entry() Program Example (continued)

          struct uni_struct  {
            union union_tag    uni_var;
            struct uni_struct *next_union;
          };

           struct uni_struct *
           add_entry( entry, current_entry)
               union union_tag *entry;  /* new value */
               struct uni_struct    *current_entry;

P23

Advanced C Concepts|The Union Concept|12-4.6|13,54
 Using Unions, An Example
{
    char *malloc();
    struct uni_struct    *ptr; /* pointer to the
                 next list element */
    if ((ptr = (struct uni_struct *) malloc (
        sizeof(struct    uni_struct))) != NULL) {

        ptr -> next_union = current_entry;
        ptr -> uni_var = *entry;  /* copy value  */
    }
    return ptr;
}

P24

Advanced C Concepts|The Union Concept|12-4.7|9,51
--------------------------------------------------
   Pictorial Representation of the structure uni_struct 
   from the previous screens.


      -----------      -----------      -----------
<----|    |     |<----|    |     |<----|    |     |
     |    |     |     |    |     |     |    |     |
      -----------      -----------      -----------

P25

Advanced C Concepts|Performing Bit Field Manipulations|12-5.1|12,54
     A field is a set of adjacent bits within 
a single int.


     Data representation with bit fields is useful 
when one is faced with limited storage space, and 
when one bitwise operation may give a result regarding 
several objects.


     The syntax for bit field data structure 
declaration is similar to that of a C structure.

P26

Advanced C Concepts|Performing Bit Field Manipulations|12-5.2|17,50
BIT FIELD USAGE EXAMPLE
Using bit fields to represent an individual with 
more than one profession

struct    {
     unsigned a_pro  Programmer  : 1;
     unsigned an_engineer   : 1;
     unsigned a_gardener    : 1;
     unsigned a_technician  : 1;
     unsigned a_pilot       : 1;
     unsigned a_driver      : 1;
     unsigned    : 1; /*    for padding only  */
     unsigned an_accountant : 1;
} user;

Note:  The number following the colon represents 
the field width in bits.

P27

Advanced C Concepts|Performing Bit Field Manipulations|12-5.3|18,54
     To say that the user is an accountant, a
programmer, and a driver, the operation is:

        user.a_programmer = user.an_accountant =
                  user.a_driver = 1;


     To say that the user is neither a technician
nor an accountant, the operation is:

        user.a_technician = user.an_accountant = 0;


     To test if the user is neither a pilot nor
a gardener nor a technician, the operation is:

        if (!(user.a_pilot ||    user.a_gardener    ||
          user.a_technician)) {

P28

Advanced C Concepts|Performing Bit Field Manipulations|12-5.4|4,43
      -- OR --
if (!user.a_pilot && !user.a_gardener    &&
    !user.a_technician) {
     :

P29

Advanced C Concepts|Using Pointers to Functions|12-6.1|14,56
     A function name may be passed from one function 
to another in the argument list.


     As with arrays, the function name in the argument 
list signifies the pointer/address to/of the function.


     If the function a passes to the function b  several
arguments, including pointers to functions, the function
b would not need to know the actual name of the function 
whose address has been passed to it.  Function b may use 
the address/pointer to the function variable in the calling 
statement along with its arguments.

P30

Advanced C Concepts|Using Pointers to Functions|12-6.2|10,54
     If the function whose address is known to the 
function b, returns a variable of type float, and if 
b calls this function variable as func_addr then 
inside b this variable may be declared as:

float (*func_addr)();

The actual calling statement will have the form:

(*func_addr)(arg1, arg2, .., argN);

P31

Advanced C Concepts|Using Pointers to Functions|12-6.3|11,54
     NOTE:  The declaration:

float *func_addr();

says that the function func_addr returns a pointer 
to the variable of type float.  Care must be taken 
not to confuse this with:

float (*func_addr)();

as used above.