NEW C PRIMER PLUS SECOND EDITION
CHAPTER 10 NOTES
Copyright (C) 1993 by The Waite Group
Copyright (C) 1997 by Linda Buck


 1. Array Initialization
    --------------------
    (1) There is no default initialization for arrays declared inside a
        function.
    (2) Under ANSI C, arrays declared inside a function may be
        initialized.  Initialization takes place every time the function
        in which it is declared is called.
    (3) The number of items in an array initialization list should match
        the size of the array.
    (4) If the number of items in an array initialization list is less
        than the size of the array, extra elements are initialized to
        zero. 
    (5) If the number of items in an array initialization list is
        greater than the size of the array, the compiler issues an error
        message.
    (6) If you use empty brackets when initializing an array, the
        program will count the number of items in the list and make the
        array that large.

 2. Example 10.1
    ------------
    Program #1:
    /* arrinit1.c -- shows array initialization */
    #include <stdio.h>
    int main(void)
    {
      /* there is no default initialization for arrays declared inside a
         function */
      int arr[3];

      printf("array = %d %d %d\n", arr[0], arr[1], arr[2]);
      return 0;
    }

    Output #1:
    array = 425 0 25

    Program #2:
    /* arrinit2.c -- shows array initialization */
    #include <stdio.h>
    void func(void);
    int main(void)
    {
      printf("First call:\n");
      func();
      printf("Second call:\n");
      func();
      return 0;
    }

    void func(void)
    {
      /* under ANSI C, arrays declared inside a function may be
         initialized -- initialization takes place every time the
         function in which it is defined is called */
      int arr[3] = {11, 13, 15};

      printf("array = %d %d %d\n", arr[0], arr[1], arr[2]);
      arr[0] = arr[1] = arr[2] = 0;
      printf("array = %d %d %d\n", arr[0], arr[1], arr[2]);
    }

    Output #2:
    First call:
    array = 11 13 15
    array = 0 0 0
    Second call:
    array = 11 13 15
    array = 0 0 0

 3. Example 10.2
    ------------
    (1) Declaration:
        /* the number of items in an array initialization list should
           match the size of the array */
        int arr[5] = {11, 13, 15, 17, 19};

        Memory:
               ------
        arr[0] | 11 |
               ------
        arr[1] | 13 |
               ------
        arr[2] | 15 |
               ------
        arr[3] | 17 |
               ------
        arr[4] | 19 |
               ------

    (2) Declaration:
        /* if the number of items in an array initialization list is
           less than the size of the array, extra elements are
           initialized to zero */ 
        int arr[5] = {11, 13, 15};

        Memory:
               ------
        arr[0] | 11 |
               ------
        arr[1] | 13 |
               ------
        arr[2] | 15 |
               ------
        arr[3] |  0 |
               ------
        arr[4] |  0 |
               ------

    (3) Declaration:
        /* if the number of items in an array initialization list is
           less than the size of the array, extra elements are
           initialized to zero */ 
        int arr[5] = {0};

        Memory:
               -----
        arr[0] | 0 |
               -----
        arr[1] | 0 |
               -----
        arr[2] | 0 |
               -----
        arr[3] | 0 |
               -----
        arr[4] | 0 |
               -----

        Comment:
        This is a quick way to initialize an array to 0.

    (4) Declaration:
        /* if the number of items in an array initialization list is
           greater than the size of the array, the compiler issues an
           error message */
        int arr[5] = {11, 13, 15, 17, 19, 21, 23};

        Compiler Error Message:
        too many initializers

    (5) Declaration:
        /* if you use empty brackets when initializing an array, the
           program will count the number of items in the list and make
           the array that large */
        int arr[] = {11, 13, 15, 17, 19};

        Memory:
               ------
        arr[0] | 11 |
               ------
        arr[1] | 13 |
               ------
        arr[2] | 15 |
               ------
        arr[3] | 17 |
               ------
        arr[4] | 19 |
               ------

 4. Assigning Array Values
    ----------------------
    (1) You can assign a value to an array element.
    (2) You cannot assign one array to another as a unit.
    (3) You cannot use the list-in-braces form except when initializing.

    Valid Example:
    #include <stdio.h>
    #define SIZE 5
    int main(void)
    {
      int i;
      int arr1[SIZE] = {11, 13, 15, 17, 19};
      int arr2[SIZE];

      for (i = 0; i < SIZE; i++)
        arr2[i] = arr1[i];
      ...
    }

    Invalid Example:
    #include <stdio.h>
    #define SIZE 5
    int main(void)
    {
      int arr1[SIZE] = {11, 13, 15, 17, 19};
      int arr2[SIZE];

      arr2 = arr1;              /* not allowed */
      arr2[SIZE] = arr1[SIZE];  /* allowed, trashes memory */
        /* gets whatever value happens to be at the first location after
           the end of the arr1 array and assigns it to the first
           location after the end of the the arr2 array */
      arr2[SIZE] = {11, 13, 15, 17, 19};  /* not allowed */
      ...
    }

 5. Functions, Arrays, and Pointers
    -------------------------------
    (1) C does not allow arrays to be passed as function arguments.
    (2) When you use an array name as a function argument, you pass the
        starting address of the array to the function.  The function
        then uses a pointer set to that address to access the original
        array in the calling program.
    (3) When you declare a formal argument in C,
            type arr[];
        and
            type *arr;
        are exactly equivalent.  Both state that arr is a pointer-to-
        type.
    (4) Because you pass a pointer instead of the array, the same
        function can be used for different sized arrays.  If a function
        needs to know the array size, the array size must also be passed
        as an argument.

 6. Example 10.3
    ------------
    Problem:
    Write a function that reads an array and a function that prints an
    array.

    Program:
    /* arrio1.c -- reads and prints an array using array notation */
    #include <stdio.h>
    #define SIZE 5
    int read_array(double ar[], int max);
    void show_array(double ar[], int n);
    int main(void)
    {
      int n;
      double arr[SIZE];

      printf("This program reads and prints an array.\n");
      n = read_array(arr, SIZE);
      printf("Array\n");
      show_array(arr, n);
      return 0;
    }
    
    int read_array(double ar[], int max)
    {
      int i;

      printf("Please enter %d numbers.  Type q to quit.\n", max);
      for (i = 0; i < max && scanf("%lf", &ar[i]) == 1; i++);
      return i;
    }

    void show_array(double ar[], int n)
    {
      int i;

      for (i = 0; i < n; i++)
        printf("%.2lf ", ar[i]);
      putchar('\n');
    }

    Screen:
    Output: This program reads and prints an array.
    Output: Please enter 5 numbers.  Type q to quit.
    Input:  1.5 3.5 5.5 q
    Output: Array
    Output: 1.50 3.50 5.50 

 7. Example 10.4
    ------------
    Problem:
    Write a function that multiplies each element of an array by a
    number.

    Program:
    /* arrmult1.c -- multiplies each element of an array by a number
                     using array notation */
    #include <stdio.h>
    #define SIZE 3
    void multiply_array(double ar[], int n, double num);
    void show_array(double ar[], int n);
    int main(void)
    {
      double arr[SIZE] = {1.5, 3.5, 5.5};

      printf("This program multiplies each element of an array by a "
        "number.\n");
      printf("Original Array\n");
      show_array(arr, SIZE);
      multiply_array(arr, SIZE, 2.5);
      printf("Array after Multiplying each Element by 2.5\n");
      show_array(arr, SIZE);
      return 0;
    }

    void multiply_array(double ar[], int n, double num)
    {
      int i;

      for (i = 0; i < n; i++)
        ar[i] *= num;
    }

    void show_array(double ar[], int n)
    {
      int i;

      for (i = 0; i < n; i++)
        printf("%.2lf ", ar[i]);
      putchar('\n');
    }

    Output:
    This program multiplies each element of an array by a number.
    Original Array
    1.50 3.50 5.50 
    Array after Multiplying each Element by 2.5
    3.75 8.75 13.75 

 8. Example 10.5
    ------------
    Problem:
    Write a function that appends one array to another array.

    Program:
    /* arrapp1.c -- appends one array to another using array notation */
    #include <stdio.h>
    #define SIZE 10
    int append_array(double ar1[], int n1, double ar2[], int n2);
    void show_array(double ar[], int n);
    int main(void)
    {
      int n1;
      double arr1[SIZE] = {1.5, 3.5};
      double arr2[] = {2.5, 4.5, 6.5};

      printf("This program appends one array to another.\n");
      printf("First Array\n");
      show_array(arr1, 2);
      printf("Second Array\n");
      show_array(arr2, 3);
      n1 = append_array(arr1, 2, arr2, 3);
      printf("First Array after Appending Second Array\n");
      show_array(arr1, n1);
      return 0;
    }

    /* appends the second array to the first array */
    int append_array(double ar1[], int n1, double ar2[], int n2)
    {
      int i1, i2;

      for (i1 = n1, i2 = 0; i2 < n2; i1++, i2++)
        ar1[i1] = ar2[i2];
      return i1;
    }

    void show_array(double ar[], int n)
    {
      int i;

      for (i = 0; i < n; i++)
        printf("%.2lf ", ar[i]);
      putchar('\n');
    }

    Output:
    This program appends one array to another.
    First Array
    1.50 3.50 
    Second Array
    2.50 4.50 6.50 
    First Array after Appending Second Array
    1.50 3.50 2.50 4.50 6.50 

 9. Example 10.6
    ------------
    Problem:
    Write a function that finds a number in an array.

    Program:
    /* arrfind1.c -- finds a number in an array using array notation */
    #include <stdio.h>
    #define SIZE 5
    int find_array(int ar[], int n, int num);
    void show_array(int ar[], int n);
    int main(void)
    {
      int num, pos;
      int arr[SIZE] = {13, 17, 15, 19, 11};

      printf("This program finds a number in an array.\n");
      printf("Array\n");
      show_array(arr, SIZE);
      while (1)
      {
        printf("\nPlease enter an integer.  Type q to quit.\n");
        if (scanf("%d", &num) != 1)
          break;
        pos = find_array(arr, SIZE, num);
        if (pos == -1)
          printf("Number %d not found.\n", num);
        else
          printf("Number %d found at position %d counting from 0.\n",
            num, pos);
      }
      return 0;
    }

    int find_array(int ar[], int n, int num)
    {
      int i;

      for (i = 0; i < n; i++)
      {
        if (ar[i] == num)
          return i;
      }
      return -1;
    }
      
    void show_array(int ar[], int n)
    {
      int i;

      for (i = 0; i < n; i++)
        printf("%d ", ar[i]);
      putchar('\n');
    }

    Function #2:
    int find_array(int ar[], int n, int num)
    {
      int i;

      for (i = 0; i < n; i++)
      {
        if (ar[i] == num)
          break;
      }
      if (i < n)
        return i;
      else
        return -1;
    }

    Function #3:
    int find_array(int ar[], int n, int num)
    {
      int i, match;
      
      for (i = 0, match = -1; i < n; i++)
      {
        if (ar[i] == num)
        {
          match = i;
          break;
        }
      }
      return match;
    }

    Screen:
    Output: This program finds a number in an array.
    Output: Array
    Output: 13 17 15 19 11 
    Output:
    Output: Please enter an integer.  Type q to quit.
    Input:  15
    Output: Number 15 found at position 2 counting from 0.
    Output:
    Output: Please enter an integer.  Type q to quit.
    Input:  12
    Output: Number 12 not found.
    Output:
    Output: Please enter an integer.  Type q to quit.
    Input:  q

10. Example 10.7
    ------------
    Problem:
    Write a function that deletes all occurrences of a number from an
    array.

    Program:
    /* arrdel1.c -- deletes all occurrences of a number from an array
                    using array notation */
    #include <stdio.h>
    #define SIZE 6
    int delete_array(int ar[], int n, int num);
    void show_array(int ar[], int n);
    int main(void)
    {
      int n;
      int arr[SIZE] = {15, 12, 15, 15, 14, 15};

      printf("This program deletes all occurrences of a number from an "
        "array.\n");
      printf("Original Array\n");
      show_array(arr, SIZE);
      n = delete_array(arr, SIZE, 15);
      printf("Array after Deleting all Occurrences of 15\n");
      show_array(arr, n);
      return 0;
    }

    int delete_array(int ar[], int n, int num)
    {
       int i, ndups;

       for (i = 0, ndups = 0; i < n; i++)
       {
         if (ar[i] == num)
           ndups++;
         else
           ar[i-ndups] = ar[i];
       }
       return n - ndups;
    }

    void show_array(int ar[], int n)
    {
      int i;

      for (i = 0; i < n; i++)
        printf("%d ", ar[i]);
      putchar('\n');
    }

    Function #2:
    int delete_array(int ar[], int n, int num)
    {
       int i1, i2;

       for (i1 = 0, i2 = 0; i1 < n; i1++)
       {
         if (ar[i1] != num)
           ar[i2++] = ar[i1];
       }
       return i2;
    }

    Output:
    This program deletes all occurrences of a number from an array.
    Original Array
    15 12 15 15 14 15 
    Array after Deleting all Occurrences of 15
    12 14 

11. Pointer Arithmetic
    ------------------
    (1) Incrementing/Decrementing a pointer
        type *ptr;
        ptr++;  /* ptr = ptr+sizeof(type) */
        ptr--;  /* ptr = ptr-sizeof(type) */

    (2) General pointer arithmetic
        int n;
        type *ptr, *ptr1, *ptr2;
        ... ptr+n ...  /* ptr+n*sizeof(type) */
        ... ptr-n ...  /* ptr-n*sizeof(type) */
        ... ptr1-ptr2  /* (ptr1-ptr2)/sizeof(type) */

    (3) Table of Operators in Order of Decreasing Precedence
        ----------------------------------------------------
             Operator                                   Associativity
         (1) ++(postfix) --(postfix) () []              left to right
         (2) ++(prefix) --(prefix) +(unary) -(unary) !  right to left
             sizeof (type)(all unary)
             *(dereference) &(address)
         (3) * / %                                      left to right
         (4) +(binary) -(binary)                        left to right
         (5) < > <= >=                                  left to right
         (6) == !=                                      left to right
         (7) &&                                         left to right
         (8) ||                                         left to right
         (9) ?:(trinary operator)                       left to right
        (10) = *= /= %= += -=                           right to left
        (11) ,(comma operator)                          left to right

    (4) Note
        (a) The name of an array is the starting address of the array.
        (b) You can use the increment or decrement operators for pointer
            variables but not for address constants, such as array
            names.
            Example:
            int arr[3];
            int *ptr;
            arr++;      /* not allowed */
            ptr = arr;
            ptr++;      /* okay */
        (c) You can find the difference between two pointers.  Normally,
            you do this for two pointers to elements that are in the
            same array to find out how far apart the elements are.
        (d) The computer does not keep track of whether a pointer still
            points to an array element.

12. Example 10.8
    ------------
    Program:
    /* ptrarith.c -- shows pointer arithmetic */
    #include <stdio.h>
    int main(void)
    {
      int n;
      int arr[] = {11, 13, 15, 17, 19};
      int *ptr, *ptr1, *ptr2;

      /* incrementing/decrementing a pointer */
      printf("Incrementing/Decrementing a Pointer\n");
      printf("arr = %p, *arr = %d\n", arr, *arr);
      ptr = arr;
      printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
      ptr++;  /* ptr = ptr+sizeof(int) */
      printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
      ptr--;  /* ptr = ptr-sizeof(int) */
      printf("ptr = %p, *ptr = %d\n", ptr, *ptr);

      /* general pointer arithmetic */
      printf("General Pointer Arithmetic\n");
      printf("arr = %p, *arr = %d\n", arr, *arr);
      ptr1 = arr+4;   /* ptr1 = arr+4*sizeof(int) */
      printf("ptr1 = %p, *ptr1 = %d\n", ptr1, *ptr1);
      ptr2 = ptr1-2;  /* ptr2 = ptr1-2*sizeof(int) */
      printf("ptr2 = %p, *ptr2 = %d\n", ptr2, *ptr2); 
      n = ptr1-ptr2;  /* n = (ptr1-ptr2)/sizeof(int) */
      printf("n = %d\n", n);

      /* the computer does not keep track of whether a pointer still
         points to an array element */
      printf("No Run-Time Array Bounds Checking\n");
      ptr = arr+5;
      printf("ptr = %p, *ptr = %d\n", ptr, *ptr);
      return 0;
    }

    Trace:
           arr
        addr value
        0100  11
        0104  13
        0108  15
        010C  17
        0110  19
     1) ptr = arr = 0100(hex)
        ptr++, ptr = ptr+sizeof(int) = 0100(hex)+4(dec) = 0104(hex)
        ptr--, ptr = ptr-sizeof(int) = 0104(hex)-4(dec) = 0100(hex)
     2) ptr1 = arr+4 = arr+4*sizeof(int)
             = 0100(hex)+4(dec)*4(dec) = 0110(hex)
        ptr2 = ptr1-2 = ptr1-2*sizeof(int)
             = 0110(hex)-2(dec)*4(dec) = 0108(hex)
        n = ptr1-ptr2 = (ptr1-ptr2)/sizeof(int)
          = (0110(hex)-0108(hex))/4(dec) = 2(dec)
     3) ptr = arr+5 = arr+5*sizeof(int)
            = 0100(hex)+5(dec)*4(dec) = 0114(hex)
    
    Output:
    Incrementing/Decrementing a Pointer
    arr = 0100, *arr = 11
    ptr = 0100, *ptr = 11
    ptr = 0104, *ptr = 13
    ptr = 0100, *ptr = 11
    General Pointer Arithmetic
    arr = 0100, *arr = 11
    ptr1 = 0110, *ptr1 = 19
    ptr2 = 0108, *ptr2 = 15
    n = 2
    No Run-Time Array Bounds Checking
    ptr = 0114, *ptr = 0
      
13. Example 10.9
    ------------
    Program:
    /* ptrprec.c -- shows precedence in pointer operations */
    #include <stdio.h>
    int main(void)
    {
      double n1, n2;
      double arr[] = {1.5, 3.5, 5.5};
      double *ptr1, *ptr2, *ptr3;

      ptr1 = arr;
      printf("ptr1 = %p\n", ptr1);
      n1 = *++ptr1;
      printf("ptr1 = %p, n1 = %.2lf\n", ptr1, n1);

      ptr2 = arr;
      printf("ptr2 = %p\n", ptr2);
      n2 = *ptr2++;
      printf("ptr2 = %p, n2 = %.2lf\n", ptr2, n2);

      ptr3 = arr;
      printf("ptr3 = %p, *ptr3 = %.2lf\n", ptr3, *ptr3);
      (*ptr3)++;
      printf("ptr3 = %p, *ptr3 = %.2lf\n", ptr3, *ptr3);
      return 0;
    }

    Trace:
           arr
        addr value
        0100  1.5
        0108  3.5
        0110  5.5
     1) ptr1 = arr = 0100(hex)
        n1 = *++ptr1
        ++ptr1, n1 = *ptr1
        ptr1++, ptr1 = ptr1+sizeof(double)
                     = 0100(hex)+8(dec) = 0108(hex)
        n1 = *ptr1 = *0108 = 3.5
     2) ptr2 = arr = 0100(hex)
        n2 = *ptr2++
        n2 = *ptr, ptr2++
        n2 = *ptr = *0100 = 1.5
        ptr2++, ptr2 = ptr2+sizeof(double)
                     = 0100(hex)+8(dec) = 0108(hex)
     3) ptr3 = arr = 0100(hex)
        *ptr3 = *0100 = 1.5
        (*ptr3)++
        (*ptr3) = (*ptr3)+1
        0100 = (*0100)+1 = 1.5+1 = 2.5

    Output:
    ptr1 = 0100
    ptr1 = 0108, n1 = 3.50
    ptr2 = 0100
    ptr2 = 0108, n2 = 1.50
    ptr3 = 0100, *ptr3 = 1.50
    ptr3 = 0100, *ptr3 = 2.50

14. Pointers and Arrays
    -------------------
    Array notation is a disguised use of pointers.

    Declaration:
    type arr[SIZE];

    Code:
    (1) arr -- the starting address of the array
    (2) Array Notation    Pointer Notation
        address  value    address  value
        &arr[i]  arr[i]   arr+i    *(arr+i)

15. Example 10.10
    -------------
    Program:
    /* arrptr.c -- compares array and pointer notation */
    #include <stdio.h>
    #define SIZE 4
    int main(void)
    {
      int i;
      int arr[SIZE] = {11, 13, 15, 17};

      /* array notation */
      printf("Array Notation\n");
      for (i = 0; i < SIZE; i++)
        printf("&arr[%d] = %p, arr[%d] = %d\n", i, &arr[i], i, arr[i]);

      /* pointer notation */
      printf("Pointer Notation\n");
      for (i = 0; i < SIZE; i++)
        printf("arr+%d = %p, *(arr+%d) = %d\n", i, arr+i, i, *(arr+i));
      return 0;
    }

    Memory:
    Array Notation   Pointer Notation         Memory
    address  value   address  value     address     value
                                                 ------------
    &arr[0]  arr[0]  arr      *arr        0100   |       11 |
                                                 ------------
    &arr[1]  arr[1]  arr+1    *(arr+1)    0104   |       13 |
                                                 ------------
    &arr[2]  arr[2]  arr+2    *(arr+2)    0108   |       15 |
                                                 ------------
    &arr[3]  arr[3]  arr+3    *(arr+3)    010C   |       17 |
                                                 ------------

    Output:
    Array Notation
    &arr[0] = 0100, arr[0] = 11
    &arr[1] = 0104, arr[1] = 13
    &arr[2] = 0108, arr[2] = 15
    &arr[3] = 010C, arr[3] = 17
    Pointer Notation
    arr+0 = 0100, *(arr+0) = 11
    arr+1 = 0104, *(arr+1) = 13
    arr+2 = 0108, *(arr+2) = 15
    arr+3 = 010C, *(arr+3) = 17


16. Example 10.11
    -------------
    Problem:
    Write a program that prints an array.

    Program #1:
    /* arrprn1.c -- array notation */
    #include <stdio.h>
    #define SIZE 3
    int main(void)
    {
      int i;
      int arr[SIZE] = {11, 13, 15};

      printf("This program prints an array.\n");
      printf("Array\n");
      for (i = 0; i < SIZE; i++)
        printf("%d ", arr[i]);
      putchar('\n');
      return 0;
    }

    Output #1:
    This program prints an array.
    Array
    11 13 15 

    Program #2:
    /* arrprn2.c -- converts array notation to pointer notation */
    #include <stdio.h>
    #define SIZE 3
    int main(void)
    {
      int i;
      int arr[SIZE] = {11, 13, 15};

      printf("This program prints an array.\n");
      printf("Array\n");
      for (i = 0; i < SIZE; i++)
        printf("%d ", *(arr+i));
      putchar('\n');
      return 0;
    }

    Output #2:
    This program prints an array.
    Array
    11 13 15 

    Program #3:
    /* arrprn3.c -- improved pointer solution */
    #include <stdio.h>
    #define SIZE 3
    int main(void)
    {
      int i;
      int arr[SIZE] = {11, 13, 15};
      int *ptr;

      printf("This program prints an array.\n");
      printf("Array\n");
      for (i = 0, ptr = arr; i < SIZE; i++, ptr++)
        printf("%d ", *ptr);
      putchar('\n');
      return 0;
    }

    Output #3:
    This program prints an array.
    Array
    11 13 15 

    Program #4:
    /* arrprn4.c -- pointer solution without counter */
    #include <stdio.h>
    #define SIZE 3
    int main(void)
    {
      int arr[SIZE] = {11, 13, 15};
      int *ptr, *end;

      printf("This program prints an array.\n");
      printf("Array\n");
      for (ptr = arr, end = arr+SIZE; ptr < end; ptr++)
        printf("%d ", *ptr);
      putchar('\n');
      return 0;
    }

    Output #4:
    This program prints an array.
    Array
    11 13 15

17. Functions, Arrays, and Pointers Review
    --------------------------------------
    (1) C does not allow arrays to be passed as function arguments.
    (2) When you use an array name as a function argument, you pass the
        starting address of the array to the function.  The function
        then uses a pointer set to that address to access the original
        array in the calling program.
    (3) When you declare a formal argument in C,
            type arr[];
        and
            type *arr;
        are exactly equivalent.  Both state that arr is a pointer-to-
        type.
    (4) Because you pass a pointer instead of the array, the same
        function can be used for different sized arrays.  If a function
        needs to know the array size, the array size must also be passed
        as an argument.

18. Example 10.12
    -------------
    Program:
    /* arrfun.c -- passing an array name as a function argument */
    #include <stdio.h>
    #define SIZE 4
    void func(int ar[], int n);
    int main(void)
    {
      int i;
      int arr[SIZE] = {11, 13, 15, 17};
  
      printf("main():\n");
      printf("arr = %p, sizeof(arr) = %d\n", arr, sizeof(arr));
      /* array notation */
      printf("Array Notation\n");
      for (i = 0; i < SIZE; i++)
        printf("&arr[%d] = %p, arr[%d] = %d\n", i, &arr[i], i, arr[i]);
      /* pointer notation */
      printf("Pointer Notation\n");
      for (i = 0; i < SIZE; i++)
        printf("arr+%d = %p, *(arr+%d) = %d\n", i, arr+i, i, *(arr+i));

      printf("\nfunc(arr, %d):\n", SIZE);
      func(arr, SIZE);
      return 0;
    }

    void func(int ar[], int n)
    {
      int i;

      printf("&ar = %p, ar = %p, sizeof(ar) = %d\n", &ar, ar,
        sizeof(ar));
      /* array notation */
      printf("Array Notation\n");
      for (i = 0; i < n; i++)
        printf("&ar[%d] = %p, ar[%d] = %d\n", i, &ar[i], i, ar[i]);
      /* pointer notation */
      printf("Pointer Notation\n");
      for (i = 0; i < n; i++)
        printf("ar+%d = %p, *(ar+%d) = %d\n", i, ar+i, i, *(ar+i));
    }

    Memory:
    (1) main():
        Array Notation   Pointer Notation         Memory
        address  value   address   value    address     value
                                                     ------------
        &arr[0]  arr[0]  arr       *arr       0100   |       11 |
                                                     ------------
        &arr[1]  arr[1]  arr+1     *(arr+1)   0104   |       13 |
                                                     ------------
        &arr[2]  arr[2]  arr+2     *(arr+2)   0108   |       15 |
                                                     ------------
        &arr[3]  arr[3]  arr+3     *(arr+3)   010C   |       17 |
                                                     ------------
    (2) func(arr, 4):
          Notation            Memory
        address value  address     value
                                ------------
          &ar    ar      0200   | 00000100 |
                                ------------

    Output:
    main():
    arr = 0100, sizeof(arr) = 16
    Array Notation
    &arr[0] = 0100, arr[0] = 11
    &arr[1] = 0104, arr[1] = 13
    &arr[2] = 0108, arr[2] = 15
    &arr[3] = 010C, arr[3] = 17
    Pointer Notation
    arr+0 = 0100, *(arr+0) = 11
    arr+1 = 0104, *(arr+1) = 13
    arr+2 = 0108, *(arr+2) = 15
    arr+3 = 010C, *(arr+3) = 17

    func(arr, 4):
    &ar = 0200, ar = 0100, sizeof(ar) = 4
    Array Notation
    &ar[0] = 0100, ar[0] = 11
    &ar[1] = 0104, ar[1] = 13
    &ar[2] = 0108, ar[2] = 15
    &ar[3] = 010C, ar[3] = 17
    Pointer Notation
    ar+0 = 0100, *(ar+0) = 11
    ar+1 = 0104, *(ar+1) = 13
    ar+2 = 0108, *(ar+2) = 15
    ar+3 = 010C, *(ar+3) = 17

19. Example 10.13
    -------------
    Problem:
    Write a function that reads an array and a function that prints an
    array.

    Program:
    /* arrio2.c -- reads and prints array using pointer notation */
    #include <stdio.h>
    #define SIZE 5
    int read_array(double *ar, int max);
    void show_array(double *ar, int n);
    int main(void)
    {
      int n;
      double arr[SIZE];

      printf("This program reads and prints an array.\n");
      n = read_array(arr, SIZE);
      printf("Array\n");
      show_array(arr, n);
      return 0;
    }
    
    int read_array(double *ar, int max)
    {
      double *ptr, *end;

      printf("Please enter %d numbers.  Type q to quit.\n", max);
      for (ptr = ar, end = ar+max; ptr < end && scanf("%lf", ptr) == 1;
        ptr++);
      return ptr-ar;
    }

    void show_array(double *ar, int n)
    {
      double *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
        printf("%.2lf ", *ptr);
      putchar('\n');
    }

    Screen:
    Output: This program reads and prints an array.
    Output: Please enter 5 numbers.  Type q to quit.
    Input:  1.5 3.5 5.5 q
    Output: Array
    Output: 1.50 3.50 5.50 

20. Example 10.14
    -------------
    Problem:
    Write a function that multiplies each element of an array by a
    number.

    Program:
    /* arrmult2.c -- multiplies each element of an array by a number
                     using pointer notation */
    #include <stdio.h>
    #define SIZE 3
    void multiply_array(double *ar, int n, double num);
    void show_array(double *ar, int n);
    int main(void)
    {
      double arr[SIZE] = {1.5, 3.5, 5.5};

      printf("This program multiplies each element of an array by a "
        "number.\n");
      printf("Original Array\n");
      show_array(arr, SIZE);
      multiply_array(arr, SIZE, 2.5);
      printf("Array after Multiplying each Element by 2.5\n");
      show_array(arr, SIZE);
      return 0;
    }

    void multiply_array(double *ar, int n, double num)
    {
      double *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
        *ptr *= num;
    }

    void show_array(double *ar, int n)
    {
      double *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
        printf("%.2lf ", *ptr);
      putchar('\n');
    }

    Output:
    This program multiplies each element of an array by a number.
    Original Array
    1.50 3.50 5.50 
    Array after Multiplying each Element by 2.5
    3.75 8.75 13.75 

21. Example 10.15
    -------------
    Problem:
    Write a function that appends one array to another array.

    Program:
    /* arrapp2.c -- appends one array to another using pointer
                    notation */
    #include <stdio.h>
    #define SIZE 10
    int append_array(double *ar1, int n1, double *ar2, int n2);
    void show_array(double *ar, int n);
    int main(void)
    {
      int n1;
      double arr1[SIZE] = {1.5, 3.5};
      double arr2[] = {2.5, 4.5, 6.5};

      printf("This program appends one array to another.\n");
      printf("First Array\n");
      show_array(arr1, 2);
      printf("Second Array\n");
      show_array(arr2, 3);
      n1 = append_array(arr1, 2, arr2, 3);
      printf("First Array after Appending Second Array\n");
      show_array(arr1, n1);
      return 0;
    }

    /* appends the second array to the first array */
    int append_array(double *ar1, int n1, double *ar2, int n2)
    {
      double *ptr1, *ptr2, *end2;

      for (ptr1 = ar1+n1, ptr2 = ar2, end2 = ar2+n2; ptr2 < end2;
           ptr1++, ptr2++)
        *ptr1 = *ptr2;
      return ptr1-ar1;
    }

    void show_array(double *ar, int n)
    {
      double *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
        printf("%.2lf ", *ptr);
      putchar('\n');
    }

    Output:
    This program appends one array to another.
    First Array
    1.50 3.50 
    Second Array
    2.50 4.50 6.50 
    First Array after Appending Second Array
    1.50 3.50 2.50 4.50 6.50 

22. Example 10.16
    -------------
    Problem:
    Write a function that finds a number in an array.

    Program:
    /* arrfind2.c -- finds a number in an array using array notation */
    #include <stdio.h>
    #define SIZE 5
    int find_array(int ar[], int n, int num);
    void show_array(int ar[], int n);
    int main(void)
    {
      int num, pos;
      int arr[SIZE] = {13, 17, 15, 19, 11};

      printf("This program finds a number in an array.\n");
      printf("Array\n");
      show_array(arr, SIZE);
      while (1)
      {
        printf("\nPlease enter an integer.  Type q to quit.\n");
        if (scanf("%d", &num) != 1)
          break;
        pos = find_array(arr, SIZE, num);
        if (pos == -1)
          printf("Number %d not found.\n", num);
        else
          printf("Number %d found at position %d counting from 0.\n",
            num, pos);
      }
      return 0;
    }

    int find_array(int *ar, int n, int num)
    {
      int *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
      {
        if (*ptr == num)
          return ptr-ar;
      }
      return -1;
    }

    void show_array(int *ar, int n)
    {
      int *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
        printf("%d ", *ptr);
      putchar('\n');
    }

    Screen:
    Output: This program finds a number in an array.
    Output: Array
    Output: 13 17 15 19 11 
    Output:
    Output: Please enter an integer.  Type q to quit.
    Input:  15
    Output: Number 15 found at position 2 counting from 0.
    Output:
    Output: Please enter an integer.  Type q to quit.
    Input:  12
    Output: Number 12 not found.
    Output:
    Output: Please enter an integer.  Type q to quit.
    Input:  q

23. Example 10.17
    -------------
    Problem:
    Write a function that deletes all occurrences of a number from an
    array.

    Program:
    /* arrdel2.c -- deletes all occurrences of a number from an array
                    using pointer notation */
    #include <stdio.h>
    #define SIZE 6
    int delete_array(int *ar, int n, int num);
    void show_array(int *ar, int n);
    int main(void)
    {
      int n;
      int arr[SIZE] = {15, 12, 15, 15, 14, 15};

      printf("This program deletes all occurrences of a number from an "
        "array.\n");
      printf("Original Array\n");
      show_array(arr, SIZE);
      n = delete_array(arr, SIZE, 15);
      printf("Array after Deleting all Occurrences of 15\n");
      show_array(arr, n);
      return 0;
    }

    int delete_array(int *ar, int n, int num)
    {
       int *ptr1, *end1, *ptr2;

       for (ptr1 = ar, end1 = ar+n, ptr2 = ar; ptr1 < end1; ptr1++)
       {
         if (*ptr1 != num)
           *ptr2++ = *ptr1;
       }
       return ptr2-ar;
    }

    void show_array(int *ar, int n)
    {
      int *ptr, *end;

      for (ptr = ar, end = ar+n; ptr < end; ptr++)
        printf("%d ", *ptr);
      putchar('\n');
    }

    Output:
    This program deletes all occurrences of a number from an array.
    Original Array
    15 12 15 15 14 15 
    Array after Deleting all Occurrences of 15
    12 14 

24. Two-Dimensional Arrays
    ----------------------
    Form:
    (1) Declaration
        type name[n1][n2];
            where type = the type of each element in the array
                  name = the name of the array
                  n1   = the number of rows in the array
                  n2   = the number of columns in the array

    (2) Executable Code
        ... name[i][j] ...
            where name = the name of the array
                  i    = the row position in the array
                  j    = the column position in the array

    Meaning:
    (1) Diagram
        arr[0][0]    arr[0][1]    arr[0][2]    ... arr[0][n2-1]
        arr[1][0]    arr[1][1]    arr[1][2]    ... arr[1][n2-1]
        arr[2][0]    arr[2][1]    arr[2][2]    ... arr[2][n2-1]
        ...          ...          ...          ... ...
        arr[n1-1][0] arr[n1-1][1] arr[n1-1][2] ... arr[n1-1][n2-1]

    (2) Declaration
                         Memory
                         -------
        name[0][0]       |     |
                         -------
        name[0][1]       |     |
                         -------
        name[0][2]       |     |
                         -------
        ...                ...
                         -------
        name[0][n2-1]    |     |
                         -------
        name[1][0]       |     |
                         -------
        name[1][1]       |     |
                         -------
        name[1][2]       |     |
                         -------
        ...                ...
                         -------
        name[1][n2-1]    |     |
                         -------
        name[2][0]       |     |
                         -------
        name[2][1]       |     |
                         -------
        name[2][2]       |     |
                         -------
        ...                ...
                         -------
        name[2][n2-1]    |     |
                         -------
        ...                ...
                         -------
        name[n1-1][0]    |     |
                         -------
        name[n1-1][1]    |     |
                         -------
        name[n1-1][2]    |     |
                         -------
        ...                ...
                         -------
        name[n1-1][n2-2] |     |
                         -------

    (3) Executable Code
                       Memory
        ...              ...
                      ---------
        name[i][j]    | value |
                      ---------
        ...              ...
        (a) If name[i][j] appears in an expression it means get the
            value stored at row i and column j in the name array.
        (b) If name[i][j] appears on the left-side of an assignment
            statement it means store the value at row i and column j in
            the name array.

    Note:
    (1) Array number of rows and columns must be int or long constants
        known at compile time.
    (2) (a) Array row and column positions must be type int or long.
        (b) Array row and column positions can be a constant, variable,
            or expression.
        (c) Array row positions start at 0 and go to n1-1.
            Array column positions start at 0 and go to n2-1.
    (3) C does not do run-time array bounds checking.
    (4) (a) The same rules that apply to the initialization of
            one-dimensional arrays apply to the initialization of
            two-dimensional arrays.
        (b) In a two-dimensional array initialization list braces can be
            used to mark the beginning and ending of a row.

25. Example 10.18
    -------------
    (1) Declaration:
        (a) /* the number of items in an array initialization list
               should match the number of rows and columns in the
               array */
            double arr[3][5] = { 2.5, 3.0, 1.0, 7.2, 8.3,
                                 3.5, 7.0, 6.1, 2.9, 6.7,
                                 2.3, 5.1, 8.9, 9.1, 5.6 };
        (b) /* the number of items in an array initialization list
               should match the number of rows and columns in the
               array */
            double arr[3][5] = { {2.5, 3.0, 1.0, 7.2, 8.3},
                                 {3.5, 7.0, 6.1, 2.9, 6.7},
                                 {2.3, 5.1, 8.9, 9.1, 5.6} };

        Memory:
        arr[0][0] = 2.5
        arr[0][1] = 3.0
        arr[0][2] = 1.0
        arr[0][3] = 7.2
        arr[0][4] = 8.3
        arr[1][0] = 3.5
        arr[1][1] = 7.0
        arr[1][2] = 6.1
        arr[1][3] = 2.9
        arr[1][4] = 6.7
        arr[2][0] = 2.3
        arr[2][1] = 5.1
        arr[2][2] = 8.9
        arr[2][3] = 9.1
        arr[2][4] = 5.6

    (2) Declaration:
        (a) /* too few initializers - extra elements are initialized to
               zero */
            double arr[3][5] = { 2.5, 3.0, 1.0, 7.2, 8.3,
                                 3.5, 7.0, 6.1, 2.9, 6.7 };
        (b) /* too few rows - extra rows are initialized to zero */
            double arr[3][5] = { {2.5, 3.0, 1.0, 7.2, 8.3},
                                 {3.5, 7.0, 6.1, 2.9, 6.7} };

        Memory:
        arr[0][0] = 2.5
        arr[0][1] = 3.0
        arr[0][2] = 1.0
        arr[0][3] = 7.2
        arr[0][4] = 8.3
        arr[1][0] = 3.5
        arr[1][1] = 7.0
        arr[1][2] = 6.1
        arr[1][3] = 2.9
        arr[1][4] = 6.7
        arr[2][0] = 0.0
        arr[2][1] = 0.0
        arr[2][2] = 0.0
        arr[2][3] = 0.0
        arr[2][4] = 0.0

    (3) Declaration:
        /* too few columns - extra columns are initialized to zero */
        double arr[3][5] = { {2.5, 3.0, 1.0},
                             {3.5, 7.0, 6.1},
                             {2.3, 5.1, 8.9} };

        Memory:
        arr[0][0] = 2.5
        arr[0][1] = 3.0
        arr[0][2] = 1.0
        arr[0][3] = 0.0
        arr[0][4] = 0.0
        arr[1][0] = 3.5
        arr[1][1] = 7.0
        arr[1][2] = 6.1
        arr[1][3] = 0.0
        arr[1][4] = 0.0
        arr[2][0] = 2.3
        arr[2][1] = 5.1
        arr[2][2] = 8.9
        arr[2][3] = 0.0
        arr[2][4] = 0.0

    (4) Declaration:
        /* too few initializers - extra elements are initialized to
           zero */
        double arr[3][5] = {0};

        Memory:
        arr[0][0] = 0.0
        arr[0][1] = 0.0
        arr[0][2] = 0.0
        arr[0][3] = 0.0
        arr[0][4] = 0.0
        arr[1][0] = 0.0
        arr[1][1] = 0.0
        arr[1][2] = 0.0
        arr[1][3] = 0.0
        arr[1][4] = 0.0
        arr[2][0] = 0.0
        arr[2][1] = 0.0
        arr[2][2] = 0.0
        arr[2][3] = 0.0
        arr[2][4] = 0.0

    (5) Declaration:
        /* too many initializers - compiler issues an error message */
        double arr[3][5] = { 2.5, 3.0, 1.0, 7.2, 8.3,
                             3.5, 7.0, 6.1, 2.9, 6.7,
                             2.3, 5.1, 8.9, 9.1, 5.6,
                             0.0, 0.0, 0.0, 0.0, 0.0 };

        Syntax Error:
        Too many initializers.

    (6) Declaration:
        /* too many rows - compiler issues an error message */
        double arr[3][5] = { {2.5, 3.0, 1.0},
                             {7.2, 8.3, 3.5},
                             {7.0, 6.1, 2.9},
                             {6.7, 2.3, 5.1},
                             {8.9, 9.1, 5.6} };

        Syntax Error:
        Too many initializers.

    (7) Declaration:
        /* too many columns - compiler issues an error message */
        double arr[3][5] =
          { {2.5, 3.0, 1.0, 7.2, 8.3, 3.5, 7.0, 6.1, 2.9, 6.7},
            {2.3, 5.1, 8.9, 9.1, 5.6} };

        Syntax Error:
        Too many initializers.

26. Example 10.19
    -------------
    Problem:
    Write a program that computes the row averages, the column averages,
    and the total average of a two-dimensional array.

    Program:
    /* arravg.c -- computes the row averages, the column averages, and
                   the total average of a two-dimensional array */
    #include <stdio.h>
    #define ROWS 3
    #define COLS 5
    int main(void)
    {
      int i, j, sum;
      int rows = 2, cols = 4;
      int arr[ROWS][COLS] = { {11, 12, 14, 18},
                              {22, 23, 25, 29} };

      printf("This program computes the row averages, the column "
             "averages,\n");
      printf("and the total average of a two-dimensional array.\n");

      /* print the array */
      printf("Array\n");
      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          printf("%2d ", arr[i][j]);
        putchar('\n');
      }

      /* compute the row averages */
      for (i = 0; i < rows; i++)
      {
        for (j = 0, sum = 0; j < cols; j++)
          sum += arr[i][j];
        printf("Row %d Average = %.2lf\n", i+1,
          (double)sum/(double)cols);
      }

      /* compute the column averages */
      for (j = 0; j < cols; j++)
      {
        for (i = 0, sum = 0; i < rows; i++)
          sum += arr[i][j];
        printf("Column %d Average = %.2lf\n", j+1,
          (double)sum/(double)rows);
      }

      /* compute the total average */
      for (i = 0, sum = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          sum += arr[i][j];
      }
      printf("Total Average = %.2lf\n",
        (double)sum/(double)(rows*cols));
      return 0;
    }

    Output:
    This program computes the row averages, the column averages,
    and the total average of a two-dimensional array.
    Array
    11 12 14 18 
    22 23 25 29 
    Row 1 Average = 13.75
    Row 2 Average = 24.75
    Column 1 Average = 16.50
    Column 2 Average = 17.50
    Column 3 Average = 19.50
    Column 4 Average = 23.50
    Total Average = 19.25

27. Pointers and Two-Dimensional Arrays
    -----------------------------------
    Declaration:
    type arr[ROWS][COLS];

    Code:
    (1) Array notation - arr
        Type  - pointer to a COLS-element array of the given type
        Value - starting address of the array
    (2) Array notation - arr[i]
        Type  - pointer to a value of the given type
        Value - starting address of row i+1
    (3) Array notation - arr[i][j]
        Type  - value of the given type
        Value - value at row i+1 and column j+1
    
28. Example 10.20
    -------------
    Program:
    /* arrays.c -- shows two-dimensional array values */
    #include <stdio.h>
    #define ROWS 4
    #define COLS 2
    int main(void)
    {
      int i, j;
      int arr[ROWS][COLS] = { {11, 12},
                              {21, 22},
                              {31, 32},
                              {41, 42} };

      printf("arr = %p\n", arr);

      for (i = 0; i < ROWS; i++)
        printf("arr[%d] = %p\n", i, arr[i]);

      for (i = 0; i < ROWS; i++)
      {
        for (j = 0; j < COLS; j++)
          printf("&arr[%d][%d] = %p, arr[%d][%d] = %d\n", i, j,
            &arr[i][j], i, j, arr[i][j]);
      }
      return 0; 
    }

    Memory:
       Array Notation            Memory
     address      value     address    value
                                    ------------
    arr arr[0]  arr[0][0]     0100  |       11 |
                                    ------------
                arr[0][1]     0104  |       12 |
                                    ------------
        arr[1]  arr[1][0]     0108  |       21 |
                                    ------------
                arr[1][1]     010C  |       22 |
                                    ------------
        arr[2]  arr[2][0]     0110  |       31 |
                                    ------------
                arr[2][1]     0114  |       32 |
                                    ------------
        arr[3]  arr[3][0]     0118  |       41 |
                                    ------------
                arr[3][1]     011C  |       42 |
                                    ------------

    Table:
        Array      Type         Value  Comment
        Notation
    (1) arr        ->int[COLS]  0100   starting address of array
    (2) arr[0]     ->int        0100   starting address of row 1
        arr[1]     ->int        0108   starting address of row 2
        arr[2]     ->int        0110   starting address of row 3
        arr[3]     ->int        0118   starting address of row 4
    (3) arr[0][0]  int          11
        arr[0][1]  int          12
        arr[1][0]  int          21
        arr[1][1]  int          22
        arr[2][0]  int          31
        arr[2][1]  int          32
        arr[3][0]  int          41
        arr[3][1]  int          42

    Output:
    arr = 0100
    arr[0] = 0100
    arr[1] = 0108
    arr[2] = 0110
    arr[3] = 0118
    &arr[0][0] = 0100, arr[0][0] = 11
    &arr[0][1] = 0104, arr[0][1] = 12
    &arr[1][0] = 0108, arr[1][0] = 21
    &arr[1][1] = 010C, arr[1][1] = 22
    &arr[2][0] = 0110, arr[2][0] = 31
    &arr[2][1] = 0114, arr[2][1] = 32
    &arr[3][0] = 0118, arr[3][0] = 41
    &arr[3][1] = 011C, arr[3][1] = 42

29. Functions and Two-Dimensional Arrays
    ------------------------------------
    (1) Call: two-dimensional array
        Function: two-dimensional array

        Example:
        #include <stdio.h>
        #define ROWS  3
        #define COLS  5
        void func(int arr[][COLS], int rows, int cols);
          /* function prototype */
        int main(void)
        {
          int rows, cols;
          int arr1[ROWS][COLS];    /* array declaration */
          int arr2[ROWS][6];
          ...
          func(arr1, rows, cols);  /* function call */
          func(arr2, ROWS, COLS);  /* incorrect results */
          ...
          return 0;
        }
        void func(int arr[][COLS], int rows, int cols)
          /* function declaration */
        {
          int i, j;
          ...
          for (i = 0; i < rows; i++)
          {
            for (j = 0; j < cols; j++)
              ... arr[i][j] ...
          }
          ...
        }

        Note:
        When using a n-dimensional array as a formal argument in a
        function, you must provide dimensions for all but the left-most
        set of brackets.  Then any array passed as an actual argument
        to the function must have matching dimensions in all by the
        left-most set of brackets.  Both of these conditons must be met
        for the function to access the calling array's elements
        properly.

    (2) Call: two-dimensional array
        Function: one-dimensional array with two-dimensional algorithm

        Example:
        #include <stdio.h>
        #define ROWS 3
        #define COLS 5
        void func(int arr[], int max_cols, int rows, int cols);
          /* function prototype */
        int main(void)
        {
          int rows, cols;
          int arr[ROWS][COLS];             /* array declaration */
          ...
          func(arr[0], COLS, rows, cols);  /* function call */
          ...
          return 0;
        }
        void func(int arr[], int max_cols, int rows, int cols)
          /* function definition */
        {
          int i, j;

          for (i = 0; i < rows; i++)
          {
            for (j = 0; j < cols; j++)
              ... arr[i*max_cols+j] ...
          }
        }

30. Example 10.21
    -------------
    Program:
    /* arr1.c -- two-dimensional array passed to two-dimensional
                 array */
    #include <stdio.h>
    #define COLS 5
    void show_array(int arr[][COLS], int rows, int cols);
    int main(void)
    {
      int arr1[3][5] = { {11, 12, 13, 14, 15},
                         {21, 22, 23, 24, 25},
                         {31, 32, 33, 34, 35} };
      int arr2[3][4] = { {11, 12, 13, 14},
                         {21, 22, 23, 24},
                         {31, 32, 33, 34} };

      printf("This program prints a two-dimensional array.\n");

      printf("arr1: 2,4 of 3,5\n");
      show_array(arr1, 2, 4);

      /*** error ***/
      /* all two-dimensional arrays passed to the function must have the
         same second dimension */
      printf("arr2: 2,4 of 3,4\n");
      show_array(arr2, 2, 4);
      return 0;
    }

    void show_array(int arr[][COLS], int rows, int cols)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          printf("%2d ", arr[i][j]);
        putchar('\n');
      }
    }

    Trace:
    (1) Call:
        show_array(arr1, 2, 4)

        Memory:         Diagram:
        show_array()    main()        Memory    show_array()
        arr  rows cols  name        addr value  name
        0100  2    4    arr1[0][0]  0100  11    arr[0][0]
                        arr1[0][1]  0104  12    arr[0][1]
                        arr1[0][2]  0108  13    arr[0][2]
                        arr1[0][3]  010C  14    arr[0][3]
                        arr1[0][4]  0110  15
                        arr1[1][0]  0114  21    arr[1][0]
                        arr1[1][1]  0118  22    arr[1][1]
                        arr1[1][2]  011C  23    arr[1][2]
                        arr1[1][3]  0120  24    arr[1][3]
                        arr1[1][4]  0124  25
                        arr1[2][0]  0128  31
                        arr1[2][1]  012C  32
                        arr1[2][2]  0130  33
                        arr1[2][3]  0134  34
                        arr1[2][4]  0138  35

    (2) Call:
        show_array(arr2, 2, 4)

        Memory:         Diagram:
        show_array()    main()        Memory    show_array()
        arr  rows cols  name        addr value  name
        0200  2    4    arr2[0][0]  0200  11    arr[0][0]
                        arr2[0][1]  0204  12    arr[0][1]
                        arr2[0][2]  0208  13    arr[0][2]
                        arr2[0][3]  020C  14    arr[0][3]
                        arr2[1][0]  0210  21    arr[0][4]
                        arr2[1][1]  0214  22    arr[1][0]
                        arr2[1][2]  0218  23    arr[1][1]
                        arr2[1][3]  021C  24    arr[1][2]
                        arr2[2][0]  0220  31    arr[1][3]
                        arr2[2][1]  0224  32    arr[1][4]
                        arr2[2][2]  0228  33
                        arr2[2][3]  022C  34

    Output:
    This program prints a two-dimensional array.
    arr1: 2,4 of 3,5
    11 12 13 14 
    21 22 23 24 
    arr2: 2,4 of 3,4
    11 12 13 14 
    22 23 24 31 

31. Example 10.22
    -------------
    Program:
    /* arr2.c -- two-dimensional array passed to one-dimensional array
                 with two-dimensional algorithm */
    #include <stdio.h>
    void show_array(int arr[], int max_cols, int rows, int cols);
    int main(void)
    {
      int arr1[3][5] = { {11, 12, 13, 14, 15},
                         {21, 22, 23, 24, 25},
                         {31, 32, 33, 34, 35} };
      int arr2[3][4] = { {11, 12, 13, 14},
                         {21, 22, 23, 24},
                         {31, 32, 33, 34} };

      printf("This program prints a two-dimensional array.\n");

      printf("arr1: 2,4 of 3,5\n");
      show_array(arr1[0], 5, 2, 4);

      printf("arr2: 2,4 of 3,4\n");
      show_array(arr2[0], 4, 2, 4);
      return 0;
    }

    void show_array(int arr[], int max_cols, int rows, int cols)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          printf("%2d ", arr[i*max_cols+j]);
        putchar('\n');
      }
    }

    Trace:
    (1) Call:
        show_array(arr1[0], 5, 2, 4);

        Memory:         Diagram:
        show_array()    main()        Memory    show_array()
        arr   max_cols  name        addr value  name
        0100     5      arr1[0][0]  0100  11    arr[0] =arr[0*5+0]
                        arr1[0][1]  0104  12    arr[1] =arr[0*5+1]
        rows  cols      arr1[0][2]  0108  13    arr[2] =arr[0*5+2]
         2     4        arr1[0][3]  010C  14    arr[3] =arr[0*5+3]
                        arr1[0][4]  0110  15
                        arr1[1][0]  0114  21    arr[5] =arr[1*5+0]
                        arr1[1][1]  0118  22    arr[6] =arr[1*5+1]
                        arr1[1][2]  011C  23    arr[7] =arr[1*5+2]
                        arr1[1][3]  0120  24    arr[8] =arr[1*5+3]
                        arr1[1][4]  0124  25
                        arr1[2][0]  0128  31
                        arr1[2][1]  012C  32
                        arr1[2][2]  0130  33
                        arr1[2][3]  0134  34
                        arr1[2][4]  0138  35

    (2) Call:
        show_array(arr2[0], 4, 2, 4);

        Memory:         Diagram:
        show_array()    main()        Memory    show_array()
        arr   max_cols  name        addr value  name
        0200     4      arr2[0][0]  0200  11    arr[0] =arr[0*4+0]
                        arr2[0][1]  0204  12    arr[1] =arr[0*4+1]
        rows  cols      arr2[0][2]  0208  13    arr[2] =arr[0*4+2]
         2     4        arr2[0][3]  020C  14    arr[3] =arr[0*4+3]
                        arr2[1][0]  0210  21    arr[4] =arr[1*4+0]
                        arr2[1][1]  0214  22    arr[5] =arr[1*4+1]
                        arr2[1][2]  0218  23    arr[6] =arr[1*4+2]
                        arr2[1][3]  021C  24    arr[7] =arr[1*4+3]
                        arr2[2][0]  0220  31
                        arr2[2][1]  0224  32
                        arr2[2][2]  0228  33
                        arr2[2][3]  022C  34

    Output:
    This program prints a two-dimensional array.
    arr1: 2,4 of 3,5
    11 12 13 14 
    21 22 23 24 
    arr2: 2,4 of 3,4
    11 12 13 14 
    21 22 23 24 

32. Example 10.23
    -------------
    Problem:
    Write a function that multiplies each element of a two-dimensional
    array by a number.  Pass a two-dimensional array to a two-
    dimensional array.

    Program:
    /* arrmult.c -- multiplies each element of a two-dimensional array
                    by a number */
    #include <stdio.h>
    #define ROWS 3
    #define COLS 5
    void multiply_array(double arr[][COLS], int rows, int cols,
      double num);
    void show_array(double arr[][COLS], int rows, int cols);
    int main(void)
    {
      int rows = 2, cols = 4;
      double arr[ROWS][COLS] = { {1.5, 2.5, 3.5, 4.5},
                                 {5.5, 6.5, 7.5, 8.5} };

      printf("This program multiplies each element of a two-"
        "dimensional\n");
      printf("array by a number.\n");
      printf("Array\n");
      show_array(arr, rows, cols);
      multiply_array(arr, rows, cols, 2.5);
      printf("Array Multiplied by 2.5\n");
      show_array(arr, rows, cols);
      return 0;
    }

    void multiply_array(double arr[][COLS], int rows, int cols,
      double num)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          arr[i][j] *= num;
      }
    }

    void show_array(double arr[][COLS], int rows, int cols)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          printf("%5.2lf ", arr[i][j]);
        putchar('\n');
      }
    }

    Output:
    This program multiplies each element of a two-dimensional
    array by a number.
    Array
     1.50  2.50  3.50  4.50 
     5.50  6.50  7.50  8.50 
    Array Multiplied by 2.5
     3.75  6.25  8.75 11.25 
    13.75 16.25 18.75 21.25 

33. Example 10.24
    -------------
    Problem:
    Write a function that finds a number in a two-dimensional array.
    Pass a two-dimensional array to a two-dimensional array.

    Program:
    /* arrfind.c -- finds a number in a two-dimensional array */
    #include <stdio.h>
    #define ROWS 3
    #define COLS 5
    void find_array(int arr[][COLS], int rows, int cols, int num,
      int *p_row, int *p_col);
    void show_array(int arr[][COLS], int rows, int cols);
    int main(void)
    {
      int row, col;
      int rows = 2, cols = 4;
      int arr[ROWS][COLS] = { {11, 12, 13, 14},
                              {21, 22, 23, 24} };

      printf("This program finds a number in a two-dimensional "
       "array.\n");
      printf("Array\n");
      show_array(arr, rows, cols);

      find_array(arr, rows, cols, 23, &row, &col);
      if (row == -1)
        printf("Number 23 not found.\n");
      else
        printf("Number 23 found at row %d and column %d counting "
          "from 0.\n", row, col);

      find_array(arr, rows, cols, 15, &row, &col);
      if (row == -1)
        printf("Number 15 not found.\n");
      else
        printf("Number 15 found at row %d and column %d counting "
          "from 0.\n", row, col);
      return 0;
    }

    void find_array(int arr[][COLS], int rows, int cols, int num,
      int *p_row, int *p_col)
    {
      int i, j;

      *p_row = *p_col = -1;
      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
        {
          if (arr[i][j] == num)
          {
            *p_row = i;
            *p_col = j;
            break;
          }
        }
      }
    }

    void show_array(int arr[][COLS], int rows, int cols)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          printf("%2d ", arr[i][j]);
        putchar('\n');
      }
    }

    Output:
    This program finds a number in a two-dimensional array.
    Array
    11 12 13 14 
    21 22 23 24 
    Number 23 found at row 1 and column 2 counting from 0.
    Number 15 not found.

34. Example 10.25
    -------------
    Problem:
    Write the following functions:
    (1) appends a row to a two-dimensional array
    (2) appends a column to a two-dimensional array
    Pass a two-dimensional array to a one-dimensional array with a
    two-dimensional algorithm.

    Program:
    /* arrapp.c -- appends a row to a two-dimensional array and a column
                   to a two-dimensional array */
    #include <stdio.h>
    #define ROWS 4
    #define COLS 6
    int row_append(double arr[], int max_cols, int rows, int cols,
      double row[]);
    int column_append(double arr[], int max_cols, int rows, int cols,
      double column[]);
    void show_array(double arr[], int max_cols, int rows, int cols);
    int main(void)
    {
      int rows1 = 3, cols1 = 4;
      int rows2 = 3, cols2 = 4;
      double arr1[ROWS][COLS] = { { 1.5,  2.5,  3.5,  4.5},
                                  { 5.5,  6.5,  7.5,  8.5},
                                  { 9.5, 10.5, 11.5, 12.5} };
      double row[COLS] = {21.5, 22.5, 23.5, 24.5};
      double arr2[ROWS][COLS] = { {31.5, 32.5, 33.5, 34.5},
                                  {35.5, 36.5, 37.5, 38.5},
                                  {39.5, 40.5, 41.5, 42.5} };
      double col[ROWS] = {51.5,
                          52.5,
                          53.5};

      printf("This program appends a row to a two-dimensional array\n");
      printf("and a column to a two-dimensional array.\n");

      printf("First Array\n");
      show_array(arr1[0], COLS, rows1, cols1);
      printf("Row\n");
      show_array(row, COLS, 1, cols1);
      rows1 = row_append(arr1[0], COLS, rows1, cols1, row);
      printf("First Array with Row Appended\n");
      show_array(arr1[0], COLS, rows1, cols1);

      printf("Second Array\n");
      show_array(arr2[0], COLS, rows2, cols2);
      printf("Column\n");
      show_array(col, 1, rows2, 1);
      cols2 = column_append(arr2[0], COLS, rows2, cols2, col);
      printf("Second Array with Column Appended\n");
      show_array(arr2[0], COLS, rows2, cols2);
      return 0;
    }

    int row_append(double arr[], int max_cols, int rows, int cols,
      double row[])
    {
      int j;

      for (j = 0; j < cols; j++)
        /* arr[rows][j] = row[j] */
        arr[rows*max_cols+j] = row[j];
      return rows+1;
    }

    int column_append(double arr[], int max_cols, int rows, int cols,
      double column[])
    {
      int i;

      for (i = 0; i < rows; i++)
        /* arr[i][cols] = column[i]; */
        arr[i*max_cols+cols] = column[i];
      return cols+1;
    }

    void show_array(double arr[], int max_cols, int rows, int cols)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          /* printf("%5.2lf ", arr[i][j]); */
          printf("%5.2lf ", arr[i*max_cols+j]);
        putchar('\n');
      }
    }

    Output:
    This program appends a row to a two-dimensional array
    and a column to a two-dimensional array.
    First Array
     1.50  2.50  3.50  4.50 
     5.50  6.50  7.50  8.50 
     9.50 10.50 11.50 12.50 
    Row
    21.50 22.50 23.50 24.50 
    First Array with Row Appended
     1.50  2.50  3.50  4.50 
     5.50  6.50  7.50  8.50 
     9.50 10.50 11.50 12.50 
    21.50 22.50 23.50 24.50 
    Second Array
    31.50 32.50 33.50 34.50 
    35.50 36.50 37.50 38.50 
    39.50 40.50 41.50 42.50 
    Column
    51.50 
    52.50 
    53.50 
    Second Array with Column Appended
    31.50 32.50 33.50 34.50 51.50 
    35.50 36.50 37.50 38.50 52.50 
    39.50 40.50 41.50 42.50 53.50 

35. Example 10.26
    -------------
    Problem:
    Write the following functions:
    (1) computes the row average of a 2-dimensional array
    (2) computes the column average of a 2-dimensional array
    (3) computes the total average of a 2-dimensional array
    Pass a two-dimensional array to a one-dimensional array with a
    two-dimensional algorithm.

    Program:
    /* arravg.c -- computes the row averages, the column averages, and
                   the total average of a two-dimensional array */
    #include <stdio.h>
    #define ROWS 3
    #define COLS 5
    double row_average(int arr[], int max_cols, int row, int cols);
    double column_average(int arr[], int max_cols, int rows, int col);
    double total_average(int arr[], int max_cols, int rows, int cols);
    void show_array(int arr[], int max_cols, int rows, int cols);
    int main(void)
    {
      int i, j;
      int rows = 2, cols = 4;
      int arr[ROWS][COLS] = { {11, 12, 14, 18},
                              {22, 23, 25, 29} };

      printf("This program computes the row averages, the column "
             "averages,\n");
      printf("and the total average of a two-dimensional array.\n");

      /* print the array */
      printf("Array\n");
      show_array(arr[0], COLS, rows, cols);

      /* compute the row averages */
      for (i = 0; i < rows; i++)
        printf("Row %d Average = %.2lf\n", i+1,
          row_average(arr[0], COLS, i, cols));

      /* compute the column averages */
      for (j = 0; j < cols; j++)
        printf("Column %d Average = %.2lf\n", j+1,
          column_average(arr[0], COLS, rows, j));

      /* compute the total average */
      printf("Total Average = %.2lf\n",
        total_average(arr[0], COLS, rows, cols));
      return 0;
    }

    double row_average(int arr[], int max_cols, int row, int cols)
    {
       int j, sum;

       for (j = 0, sum = 0; j < cols; j++)
         /* sum += arr[row][j]; */
         sum += arr[row*max_cols+j];
       return (double)sum / (double)cols;
    }

    double column_average(int arr[], int max_cols, int rows, int col)
    {
       int i, sum;

       for (i = 0, sum = 0; i < rows; i++)
         /* sum += arr[i][col]; */
         sum += arr[i*max_cols+col];
       return (double)sum / (double)rows;
    }

    double total_average(int arr[], int max_cols, int rows, int cols)
    {
      int i, j, sum;

      for (i = 0, sum = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          /* sum += arr[i][j]; */
          sum += arr[i*max_cols+j];
      }
      return (double)sum / (double)(rows*cols);
    }
  
    void show_array(int arr[], int max_cols, int rows, int cols)
    {
      int i, j;

      for (i = 0; i < rows; i++)
      {
        for (j = 0; j < cols; j++)
          /* printf("%2d ", arr[i][j]); */
          printf("%2d ", arr[i*max_cols+j]);
        putchar('\n');
      }
    }

    Output:
    This program computes the row averages, the column averages,
    and the total average of a two-dimensional array.
    Array
    11 12 14 18 
    22 23 25 29 
    Row 1 Average = 13.75
    Row 2 Average = 24.75
    Column 1 Average = 16.50
    Column 2 Average = 17.50
    Column 3 Average = 19.50
    Column 4 Average = 23.50
    Total Average = 19.25
 



6



