CSC 115.005/006 Sonoma State University Spring 2022
Scribbler 2
CSC 115.005/006:
Programming I
Scribbler 2
Instructor: Henry M. Walker

Lecturer, Sonoma State University
Professor Emeritus of Computer Science and Mathematics, Grinnell College


Course Home References Course Details: Syllabus, Schedule, Deadlines, Topic organization MyroC Documentation Project Scope/
Acknowledgments

Notes:

Reading on Two-dimensional Arrays

Overview

This laboratory exercise provides practice with the declaration and use of 2-dimensional arrays.


Introduction

The previous class session introduced a struct to combine several different pieces of data within one logical unit.

In contrast, [one-dimensional] arrays provide a mechanism to access a sequence of data using a single index, such as item[0], item[1], item[2], ....


Some Basics of two-dimensional arrays

Expanding upon the concept of an array, C supports the organization of data in a table by specifying a row and a column.

As with one-dimensional arrays, two-dimensional arrays can contain data of any type, although each entry in a table must have the same type. Also, the size of a two-dimensional array must be declared when it is first defined:

   int table [5][10];

When using a two-dimensional array as a parameter, the declaration of a procedure header must know the number of columns in the table (so the computer knows when one row stops and the next starts). As with 1-dimensional arrays, a procedure header does not need to specify the number of rows in the table. Thus, if the above table were passed to a printArray procedure, the header of printArray might be given as follows:

   void printArray (int arr[][10])

The following example illustrates how to work with 2-dimensional arrays that conceptually store data of the same type within a table.

2 dimensional array

Example: Daily Precipitation for Six Cities

Consider a table that presents the amount of precipitation for six cities over an eight day period: December 18-25, 2014.

Chicago Denver Des Moines Phoenix San Jose Seattle
Date Illinois Colorado Iowa Arizona California Washington
 
Dec. 18 0.00 0.00 0.00 0.00 0.00 0.51
Dec. 19 0.00 0.00 0.00 0.00 0.19 0.12
Dec. 20 0.00 0.00 0.00 0.00 0.06 0.77
Dec. 21 0.00 0.00 0.00 0.00 0.00 0.00
Dec. 22 0.28 0.14 0.34 0.00 0.00 0.00
Dec. 23 0.13 0.00 0.34 0.00 0.02 0.81
Dec. 24 0.12 0.00 0.09 0.00 0.04 0.21
Dec. 25 0.00 0.21 0.00 0.00 0.00 0.00
 
Totals 0.53 0.35 0.77 0.00 0.31 2.42

This type of table arises frequently:

Annotated Program

Program city-precipitation.c stores the precipitation data for this table in a two-dimensional array and prints the table.


/* Program to print and process precipitation in six cities,
   based on totals recorded during the eight days December 18-25, 2014.
*/

#include <stdio.h>

/* function returns total rainfall for the city with the given number */
double computeCityPrecip (double rain [8][6], int cityNum);

int main ()
{

Program Notes


  char * cities [6] = {"Chicago", "Denver", "Des Moines", 
                       "Phoenix", "San Jose", "Seattle"};
  char * states [6] = {"Illinois", "Colorado", "Iowa",
                       "Arizona", "California", "Washington"};

  double precip [8][6] = { 
            /* Dec. 18 */  { 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.51 }, 
            /* Dec. 19 */  { 0.00 , 0.00 , 0.00 , 0.00 , 0.19 , 0.12 }, 
            /* Dec. 20 */  { 0.00 , 0.00 , 0.00 , 0.00 , 0.06 , 0.77 },
            /* Dec. 21 */  { 0.00 , 0.00 , 0.00 , 0.00 , 0.00 , 0.00 },  
            /* Dec. 22 */  { 0.28 , 0.14 , 0.34 , 0.00 , 0.00 , 0.00 },  
            /* Dec. 23 */  { 0.13 , 0.00 , 0.34 , 0.00 , 0.02 , 0.81 },  
            /* Dec. 24 */  { 0.12 , 0.00 , 0.09 , 0.00 , 0.04 , 0.21 },   
            /* Dec. 25 */  { 0.00 , 0.21 , 0.00 , 0.00 , 0.00 , 0.00 }   
                         };
/* source: 
    http://www.accuweather.com/en/us/chicago-il/60608/weather-forecast/348308 
    and similar pages from accuweather, accessed December 27, 2014.
*/

The city-recitation array has 8 rows (for 8 dates), with each row having data for 6 cities. This array size is reflected in the declaration

double precip [8][6]

  int row, col;
  /* print titles */
  printf ("Precipitation at six cities over eight days in December 2014\n");
  printf ("         ");
  for (col = 0; col < 6; col++)
    printf ("%-11s", cities[col]);
  printf ("\n");
  printf ("  Date   ");
  for (col = 0; col < 6; col++)
    printf ("%-11s", states[col]);
  printf ("\n\n");

  /* print precipitation table */
  for (row = 0; row < 8; row++)
    {
      printf ("Dec. %2d", row+18);
      for (col = 0; col < 6; col++)
        {
          printf ("   %5.2lf   ", precip[row][col]);
        }
      printf ("\n");
    }
  printf ("\n");

  /* print total precipitation for each city */
  printf ("Totals ");
  for (col = 0; col < 6; col++)
    {
      printf ("   %5.2lf   ", computeCityPrecip (precip, col));
    }
      printf ("\n\n");
 
  return 0;
}

/* function returns total rainfall for the city with the given number */
double computeCityPrecip (double rain [8][6], int cityNum)
{
  int k;
  double sum = 0.0;
  for (k = 0; k < 8; k++)
    sum += rain [k][cityNum];
  return sum;
}

Altogether, two dimensional arrays are a wonderful way to store lots of data which would otherwise require many arrays!


2D Array Storage: Row-major Order

Now that we have some basic experience with two-dimensional arrays, we need to examine more closely how these arrays are stored in main memory. Suppose an array is declared:

 table [row][col];

where row and col have been previously specified as integer values. A schematic of the array is shown to the right.

In main memory, the two-dimensional array table is stored row-by-row. First, row 0 is stored, then row 1, then row 2, etc. Such a storage configuration is called row-major order. Note that no extra memory is used to separate one row from another; the elements of one row immediately follow the elements of the previous row.

array storage

More about 2-dimensional Arrays in C

The storage of 2-dimensional arrays in row-major order reflects several underlying concepts within C, including

The following notes explore each of these topics.

C's View of a 2-dimensional Array as an Array of 1-dimensional Arrays

In the initial introduction of 1-dimensional arrays, an array declaration a[10] specified several elements.

This same perspective carries over to two-dimensional arrays. For the array double table[8][6],

In summary: given a 2-dimensional array table[8][6]

In particular, for this example, table[0] specifies a base address and represents a 1-dimensional array.

Calculating the Location of an Array Element

Based upon this organization of main memory, the location of any array element can be computed very quickly. Suppose the variable row designates the number of rows for a 2-dimensional array, and suppose col designates the number of columns. To locate element table[i][j], one proceeds as follows:

Altogether, the element table[i][j] may be found at address table + i*col + j. That is, the element itself may be referenced with the computation

element = *(table + i*col + j);

2-dimensional Arrays as Function Parameters

One consequence of this computation is that the compiler must know how many columns are in a two-dimensional array into order to determine where an array element might be. In particular, the signature of a procedure involving a two-dimensional array must include the number of columns. As with one-dimensional arrays, the number of rows need not be specified, as the computation of an element is valid for any i and j, as long as the number col is known.

In practice, column information may be included in a procedure header in either of two ways:

The layout of a table in memory requires the computer to know the width of a table.



created 2 August 2011 by Erik Opavsky
revised 8 August 2011 by Erik Opavsky
modest editing 23 October 2011 by Dilan Ustek and Henry M. Walker
modest reformatting 6 November 2011 by Henry M. Walker
minor editing 25 October 2013 by Henry M. Walker
reformatting, modest editing, discussion of 2D storage 1-2 February 2014 by Henry M. Walker
readings added 19 September 2014 by Henry M. Walker
lab reworked 28 December 2014 by Henry M. Walker
Valid HTML 4.01! Valid CSS!
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu.