Previous: A Compound Data Type --- array
Up: 7 Arrays
Next: 7.3 Arrays, Pointers, Pointer Arithmetic
Previous Page: 7.1.2 Character Strings as Arrays
Next Page: 7.3 Arrays, Pointers, Pointer Arithmetic
We have now seen two examples of the use of arrays - to hold numeric data such as test scores, and to hold character strings. We have also seen two methods for determining how many cells of an array hold useful information - storing a count in a separate variable, and marking the end of the data with a special character. In both cases, the details of array processing can easily obscure the actual logic of a program - processing a set of scores or a character string. It is often best to treat an array as an abstract data type with a set of allowed operations on the array which are performed by functional modules. Let us return to our exam score example to read and store scores in an array and then print them, except that we now wish to use functions to read and print the array.
LIST1: Read an array and print a list of scores using functional modules.
The algorithm is very similar to our previous task, except that the details of reading and printing the array is hidden by functions. The function, read_intaray(), reads scores and stores them, returning the number of scores read. The function, print_intaray(), prints the contents of the array. The refined algorithm for main() can be written as:
print title, etc. n = read_intaray(exam_scores, MAX); print_intaray(exam_scores, n);Notice we have passed an array, exam_scores, and a constant, MAX (specifying the maximum size of the proposed list), to read_intarray() and expect it to return the number of scores placed in the array. Similarly, when we print the array using print_intarray, we give it the array to be printed and a count of elements it contains. We saw in Chapter that in order for a called function to access objects in the calling function (such as to store elements in an array) we must use indirect access, i.e. pointers. So, read_intaray() must indirectly access the array, exam_scores, in main(). One unique feature of C is that array access is always indirect; thus making it particularly easy for a called function to indirectly access elements of an array and store or retrieve values. As we will see in later sections, array access by index value is interpreted as an indirect access, so we may simply use array indexing as indirect access.
We are now ready to implement the algorithm for main() using functions to read data into the array and to print the array. The code is shown in Figure 7.5.
The function calls in main() pass the name of the array, exam_scores, as an argument because the name of an array in an expression evaluates to a pointer to the array. In other words, the expression, exam_scores, is a pointer to (the first element of) the array, exam_scores. Its type is, therefore, int *, and a called function uses this pointer (passed as an argument) to indirectly access the elements of the array. As seen in the Figure, for both functions, the headers and the prototypes show the first formal parameter as an integer array without specifying the size. In C, this syntax is interpreted as a pointer variable; so scores is declared aa an int * variable. We will soon discuss how arrays are accessed in C; for now, we will assume that these pointers may be used to indirectly access the arrays.
The second formal parameter in both functions is lim which specifies the maximum number of items. For read_intaray(), this may be considered the maximum number of scores that can be read so that it does not read more items than the size of the array allows ( MAX). The function returns the actual number of items read which is saved in the variable, n, in main(). For the function, print_intaray(), lim represents the fact that it must not print more than n items. Again, since arrays in C are accessed indirectly, these functions are able to access the array which is defined and allocated in main(). A sample session for this implementation of the task would be identical to the one shown earlier.
Similarly, we can modify the program, string.c, to use functions to read and print strings. The task and the algorithm are the same as defined for STRING0 in the last section, except that the program is terminated when an empty string is read. The code is shown in Figure 7.6.
The driver calls read_str() and print_str() repeatedly until an empty string is read (detected when s is zero, i.e. NULL). The argument passed to read_str() and print_str() is str, a pointer to (the first element of) a character array, i.e. a char *. The function, read_str(), reads characters until a newline is read and indirectly stores the characters into the string, s. The function, print_str(), prints characters from the string, s until NULL is reached and terminates the output with a newline. Notice we have declared the formal parameter, s as a char *, rather than as an array: char s. As we will see in the next section, C treats the two declarations exactly the same.