Part F - Refinements

Two-Dimensional Arrays

Connect procedures using pass-by-value and pass-by-address semantics to build a complete program
Design data collections using arrays and structures to manage information efficiently

"In C, a two-dimensional array is really a one-dimensional array, each of whose elements is an array" (Kernighan and Ritchie, 1988)

Two-Dimensional Syntax | Array of Strings | Exercises



A simple data structure for organizing tabular data is the two-dimensional array.  The C language supports multi-dimensional arrays.  The C compiler treats a two-dimensional array as an array of arrays.  An obvious application of this data structure is an array of character strings. 

This chapter introduces two-dimensional arrays, describing their syntax and their organization in memory.  This chapter includes sample code snippets related to arrays of character strings. 


Two-Dimensional Syntax

A table is a useful analogy for describing a two-dimensional array.  An entry in a table is identified by its row and column positions.  Consider the row and column indices in the figure below.  The first index refers to the row and the second index refers to the column.

rows and columns

To identify an element of a two-dimensional array we use two pairs of brackets.  The index within the left pair identifies the row, while the index within the right pair identifies the column: 

 array[ row ][ column ]

Indexing is 0-based for both rows and columns.

Definition

The definition of a two-dimensional array takes the form

 type identifier[ r ][ c ] = init;

where r is the number of rows in the array and c is the number of columns.  r and c are integer constants or constant integer expressions.  The total number of elements in the array is r * cinit is a braces-enclosed, comma-separated list of initial values.  The assigment operator together with init are optional.  If we add an initialization list, we may omit the value of r.  If r * c exceeds the number of initial values, the compiler initializes the remaining elements to 0.  If we omit the initialization list, we must specify r.  We must always specify c

For example,

 int a[4][5] = {11, 12, 13, 14, 15,
                21, 22, 23, 24, 25,
                31, 32, 33, 34, 35,
                41, 42, 43, 44, 45}; 

To improve clarity, we may enclose each subset of initial values for each row in additional braces: 

 int a[4][5] = {{11, 12, 13, 14, 15},
                {21, 22, 23, 24, 25},
                {31, 32, 33, 34, 35},
                {41, 42, 43, 44, 45}}; 

Order

The C language stores the elements of a two-dimensional array in row-major order: the first row, column-element by column-element, then the second row, column-element by column-element, then the third row, etc.. 

For example, the elements of the array

 int a[4][5];

are stored as follows

 a[0][0] a[0][1] a[0][2] a[0][3] a[0][4]
 a[1][0] a[1][1] a[1][2] a[1][3] a[1][4]
 a[2][0] a[2][1] a[2][2] a[2][3] a[2][4]
 a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] 

some programming languages store two-dimensional arrays in column-major order.

Passing to a Function

We pass a two-dimensional array to a function in the same way that we pass a one-dimensional array.  We specify the name of the array as an argument in the function call.  The corresponding function parameter receives the value of this argument as the address of the array.  The parameter declaration identifies the array as two-dimensional by two pairs of brackets.  The parameter declaration includes the array's column dimension - the column dimension must be included. 

For example,

 // Two-Dimensional Arrays
 // pass2DArray.c

 #include <stdio.h>

 #define NCOLS 3
 void foo(int a[][NCOLS], int r, int c);

 int main(void)
 {
         int a[2][NCOLS] = {{11, 12, 13}, {21, 22, 23}};

         foo (a, 2, 3);
 }

 void foo(int a[][NCOLS], int r, int c)
 {
         int i, j;

         for (i = 0; i < r; i++) {
                 for (j = 0; j < c; j++)
                         printf("%d ", a[i][j]);
                 printf("\n");
         }
 }





















 11 12 13
 21 22 23


The compiler needs the column dimension (NCOLS) to determine the start of each row within the array.  As with one-dimensional arrays the first dimension does not need to be included. 

Passing a Specific Row of an Array

A two-dimensional C array is an array of one-dimensional arrays:

 a[0][0] a[0][1] a[0][2] a[0][3] a[0][4] first row
 a[1][0] a[1][1] a[1][2] a[1][3] a[1][4] second row
 a[2][0] a[2][1] a[2][2] a[2][3] a[2][4] third row
 a[3][0] a[3][1] a[3][2] a[3][3] a[3][4] fourth row 

A reference to an entire row of a two-dimensional array takes the form of the name of the array followed by the row number within brackets:

 array[ row ]

To pass a specific row to a function, we identify the row as part of the argument in the function call.  For example,

 // Two-Dimensional Arrays
 // passRow.c

 #include <stdio.h>

 #define NCOLS 3
 void foo(int a[], int c);

 int main(void)
 {
         int a[2][NCOLS] = {{11, 12, 13}, {21, 22, 23}};

         foo (a[0], NCOLS); // pass first row
         foo (a[1], NCOLS); // pass second row
 }

 void foo(int a[], int c)
 {
         int i;

         for (i = 0; i < c; i++)
                 printf("%d ", a[i]);
         printf("\n");
 }





















 11 12 13
 21 22 23

a[0] points to the first row of a and holds the address of the first element of that row.  a[1] points to the second row of a and holds the address of the first element of that row. 


Arrays of Character Strings

An array of strings is a two-dimensional array.  The row index refers to a particular character string, while the column index refers to a particular character within a character string. 

Definition

The definition of an array of character strings takes the form

 char identifier[NO_OF_STRINGS][MAX_NO_OF_BYTES_PER_STRING];

To declare an array of 5 names with each name holding up to 30 characters, we write

 char name[5][31];

Note that the number of names ([5]) precedes the maximum number of characters in a name ([31]).

Initialization

Initialization of an array of character strings takes the form

 char identifier[NO_OF_STRINGS][MAX_NO_OF_BYTES_PER_STRING] = {
                    initializer_1, initializer_2, ... };

For example,

 char name[5][31] = {"Harry", "Jean", "Jessica", "Irene", "Jim"}; 

A String within an Array of Strings

To refer to a string within an array of strings, we follow the array identifier with a single pair of brackets.  The index within the pair of brackets identifies the string within the array. 

The address of a string in an array of strings takes the form

 identifer[index]

For example,

 name[1]

identifies the second string in name.

Address of a Character

To refer to a character within a string, we follow the array identifier with two pairs of brackets, the first containing the index that identifies the string and the second containing the index that identifies the character within that string.

For example,

 name[1][2]

identifies the third character within the second string of name.

 &name[1][2]

identifies the address of the third character within the second string of name.

Input and Output

Input

To accept input for a list of 5 names, we write

 char name[5][31];

 for (i = 0; i < 5; i++)
         scanf(" %[^\n]", name[i]); 

The space in the format string skips leading whitespace before accepting the string.

Output

To display the third string in name, we write

 char name[5][31] = {"Harry", "Jean", "Jessica", "Irene", "Jim"}; 

 printf("%s", name[2]);

Functions

Arguments

To pass a list of names to a function, we write

 char name[5][31];

 foo(name, n);

Parameters

To receive the address of this array of strings in a function parameter, we write

 void foo(char name[][31], int n) 
 {
          // ...
 }

Exercises




   Printer Friendly Version of this Page print this page     Top  Go Back to the Top of this Page
Previous Reading  Previous: Pointers, Arrays and Structures Next: Algorithms   Next Reading


  Designed by Chris Szalwinski   Copying From This Site   

Creative Commons License