CIS 1057. Computer Programming in C

Chapter 7. Arrays

 

For complicated applications, simple data types are usually not enough. Often it is desired to organize multiple values into a data structure. An array is such a data structure.

1. Declaring and refencencing arrays

An array is a collection of data items, called array elements, of the same type, and stored in adjacent memory cells. All data in an array is associated with a particular symbolic name.

As other data types, an array needs to be declared before it can be used.

The declaration "double x[8];" instructs the compiler to associate eight memory cells, each can hold a double value, with the name x.

Variables in an array are not named individually, but though the array name and an index, or subscript, value, which is a serial number starting at 0. For example, the subscripted variable x[0] (read as "x sub zero") may be used to refer to the first element in the array x, x[1] the next one, and so on. In C, if an array is declared to contain n elements, the range of valid index values is from 0 to n-1. For example, FIGURE 7.1:

After declaration, each element in the above array can be used as a normal double value.

An array can be initialized in the same statement as it is declared, such as

  int squares[] = {0, 1, 4, 9};
Please note that in this kind of declaration the size of the array is implied by the number of the initial values. Also, this format can only be used in initialization, but not in any assignment after it.

 

2. Array subscripts

It is important to understand the relation and difference between a subscript of an array and the associated value stored in the corresponding memory cell.

A subscript can either be a constant integer, or a variable or expression that has an integer value. See Table 7.2 for examples.

 

3. Using for loops for sequential access

To process elements in an array one by one, a for loop is usually used, with its control variable as subscript of the array.

For example, the following loop will produce the same array squares as in the previous example:

  int size = 4;
  int squares[size];
  for (i = 0; i < size; i++)
    squares[i] = i * i;
A more complicated example is in FIGURE 7.2, which uses three loops for input, calculation, and output, respectively.

 

4. Using array elements as function arguments

In the previous example, x[i] is used as an argument for functions scanf and printf. The actual value (for an input argument) or reference (for an output argument) used depends on the value of i when the function is called.

 

5. Array arguments

An array as a whole can be used as an argument of a function.

For example, the program in FIGURE 7.4 assign the same value to every element of an array up to a specified index.

An array is always passed by reference, that is, the changes the function makes will happen in the original copy, not a local copy of the function. It is like how an address is passed in the previous examples, except that no '&' is needed in the function call, and in the formal parameter list, '*', is not used, neither.

Declaration "int list[]" in a formal parameter list can be replaced by "int *list", though this format may cause misunderstanding.

In a formal parameter list, the size of an array is not specified, and another parameter is used to specify the size.

A reserved word "const" informs the compiler that a certain array is intended to be used as input only, so any attempt to change its value will trigger an error message. For example, see FIGURE 7.6.

In C, it is illegal for an array to be used by a function as its return value. Instead, such an array should be declared as an output parameter in the parameter list. For example, see FIGURE 7.8. Since arrays are always passed by reference, the "address_of" operator '&' is not used here.

An array can be partially filled. In that case, a counter is often used to record the number of values in the array, which cannot be larger than the size of the array. For example, see the function in FIGURE 7.11 and the driver in FIGURE 7.12.

A stack is a data structure in which only the top (the most recently added) element can be accessed. The program in FIGURE 7.13 implements a stack in an array, with the stack operations push and pop defined.

 

6. Searching and sorting an array

Searching a data structure is an operation that find an element in the data structure that containing a given target value.

For an array, linear search means to go through the array from one end to the other, and to compare with each element on the way with the target. Such a function is in FIGURE 7.14.

Sorting means to arrange the values in an array by order.

There are many ways to sort an array. Selection sort works by selecting the current smallest (or largest) value in each pass, then switch it to the beginning (or end) of the sub-array to be sorted, so as to reduce the sub-array by one element. For example, FIGURE 7.15:

Such a function is in FIGURE 7.16.

On a sorted array, a more efficient search algorithm is binary search. In this process, the target is compared with the element in the middle, then the left half or right half of the array is searched in the same way.

 

7. Parallel arrays and enumerated types

Parallel arrays have the same number of elements, where all array elements at subscript i contain data for the ith object in this group of objects.

For example, the program in FIGURE 7.17 uses two arrays to store the ID and GPA of students.

In many programming languages, there are ways to define new data types.

If somewhere in a program a variable has a constant set of possible values, ANSI C allows the variable to be declared to be of an enumerated type defined in the program.

In general, an enumerated type is defined as the following:

typedef enum
    {value_0, value_1, ..., value_n}
type_name;
where value_i (0 <= i <= n) must be an identifier (rather than a number, a character, or a string), and it is internally coded by integer i. An identifier used in an enumerated type cannot be used for other purpose.

For example, the program in FIGURE 7.18 defines enumerated type expense_t, and uses a switch statement to process each case.

Values of an enumerated type can be treated as int values by the comparison and arithmetic operators. For example:

  for ( today = monday;  today <= friday;  ++today)  {  
         .  .  .  
 }  

 

8. Multidimentional arrays

Multidimensional arrays are arrays of arrays.

For example, a Tic-tac-toe board is a two-dimensional array, also called a matrix. In C, it can be declared as "char tictac[3][3]", where the first value is the number of rows, and the second the number of columns. For example, FIGURE 7.20:

A multidimensional array is used similar to an (one-dimensional) array. For example, the program in FIGURE 7.21 uses a double for loop to check if the board is filled, i.e., without any space left.

When a formal parameter of a function is a multidimensional array, in the declaration the size of the first dimension is usually not specified, while the sizes of the other dimensions are required.

The following line initialize the board:

char tictac[3][3] = { {' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '} };
FIGURE 7.22 shows a three-dimensional array declared as "int enroll[MAXCRS][5][4]", where the three dimensions correspond to course, campus, and year, respectively:

 

9. Array processing illustrated

As an example of array usage, the following data is processed, which is not identical but similar to the one in FIGURE 7.23:

.

The main function of the program is in FIGURE 7.24, input and initialize functions are in FIGURE 7.25, and the output functions are in FIGURE 7.26.

 

10. Common programming errors

The most common error in using arrays in subscript-range error, which happens at run time when an out-of-range subscript is used.

When an array is passed as a parameter, remember not to apply the "address of" (&) operator. However, the operator may be needed if an array element is passed as an output parameter.