Planning a Program

I l @ ve RuBoard

Planning a Program

Now that you've seen the mechanics of writing array functions, let's try a more programming-oriented example. Our self-appointed task is to write a program that reads numbers into an array, prints the entered numbers, and reports the average. To make the program more realistic, require that it allow the user to terminate input, if desired, before the array is filled. This will enable the program to process any number of items up to a maximum determined by the array size . Also, you want to avoid calculating the average if no numbers are entered.

General Plan

Conceptually, the program should perform three major tasks : reading in a set of numbers, printing the set of numbers, and calculating the average. Now that you know how to process arrays with functions, let's use functions to modularize the work. As a first pass, you can visualize the program as shown in Listing 10.18.

Listing 10.18 The draft1.c program.
 /* draft1.c -- first draft of program skeleton */ #include <stdio.h> #define MAX 25 void read_array(double ar[]); void show_array(const double ar[]); double mean(const double ar[]); int main(void) {   double data[MAX];   read_array(data);   show_array(data);   printf("The average is %.2lf.\n", mean(data));   return 0; } 

Now you have a modular program, but this draft doesn't handle data communication well. For instance, the read_array() function should know the maximum number of items that it is allowed to read, so it should also take MAX as an argument. Incidentally, the fact that data is a pointer means that the read_array() function will modify the data array in main() directly, which is exactly what you want for this function.

Similarly, the show_array() and mean() functions should know how big an array they are using, so they each need an additional argument. In general, this argument should not be MAX because the user might enter fewer numbers. You can use a variable size to represent the actual number of items entered; it can be the second argument to these two functions. Neither of these functions should modify the array, so the parameter is declared as const .

This raises a new problem: How does main() know what size is? One solution is to have the read_array() function return that value. That is, it takes as arguments the array to be filled and the maximum number of values that the array holds. It then reads data into the array and returns the actual number of items read. If this number is zero, you can skip the rest of the program. This line of thought leads to a second draft for the skeleton, which is shown in Listing 10.19.

Listing 10.19 The draft2.c program.
 /* draft2.c -- second top-level draft for the program */ #include <stdio.h> #define MAX 25 int read_array(double ar[], int limit); void show_array(const double ar[], int n); double mean(const double ar[], int n); int main(void) {   double data[MAX];   int size;   double average;   size = read_array(data, MAX);   if (size == 0)        printf("No data. Bye.\n");   else   {        printf("The following numbers were entered:\n\n");        show_array(data, size);        printf("\nThe average of these values is %.2f.\n",             mean(data, size));   }   return 0; } 

Note that we changed the prototype for read_array() to reflect that it now has a return value. Now you have the overall design for the program and its data flow, and you can turn to the individual functions.

The read_array() Function

The read_array() function is the most ambitious of the three. It should read in values until the array is filled or until the user wants to stop, whichever occurs first. The main question is how to let the user inform the program that he or she is finished. You can use the properties of scanf() to help here. Recall that scanf() returns the number of values successfully read. Non-numeric input or end of file causes it to return or EOF , respectively. Therefore, you can terminate input if scanf() doesn't return the value 1 . Also, you can use a counter to keep track of the number of entries so that you can terminate input if the counter exceeds the size of the array. Here's one approach:

 int read_array(double ar[], int limit) {   int i = 0;   printf("Enter up to %d numbers. To terminate\n", limit);   printf("earlier, enter a letter or EOF.\n");   while (i < limit && scanf("%lf", &ar[i]) == 1)        i++;   return i; } 

This approach looks simple enough, but there are two subtle points to note. The first is that the test i < limit comes first. Recall that the && operator guarantees that the second operand is not evaluated if the first operand is false. This means that if i equals limit , the expression scanf("%lf", &ar[i]) == 1 is not evaluated. This, in turn, means that the scanf() function is not called, which is good. Suppose you had used the opposite order:

 while ( scanf("%lf", &ar[i]) == 1 && i < limit) 

In this case, scanf() reads a value into ar[limit] before finding out that it has gone too far. Remember, because array numbering begins with 0, ar[limit] is one position past the end of the array. You don't want to put data there!

The second subtle point is that the loop increments i after reading a value into ar[i] . This makes i one greater than the index of the last array element filled. Because indexing begins with 0, i at that point equals the number of array items, not the array index. This is convenient because the number of array items is the value you want to return.

If you like, you can use pointers more explicitly. For instance, you could use the following input loop:

 while (i < limit && scanf("%lf", ar++) == 1)      i++; 

Recall that scanf() requires the address of the location that is to receive the data. Initially, ar holds the address of the first element of the array, so the first time through the loop, scanf() places a number in the first element of the array. Then the increment operator increases ar so that it points to the next element of the array, thus preparing for the next loop cycle.

The show_array() Function

Next, you want a function to display the array values. We already have written one for Listing 10.10. A problem with that function, however, is that it prints everything on one line. Here you have more data, so you would like to insert some newline characters .

One scheme is to use a for loop as before and to print a newline after every sixth value. You can do this by using the modulus operator ( % ):

 void show_array(const double ar[], int n) {   int i;   for (i = 0; i < n; i++)   {        printf("%10.2f ", ar[i]);        if (i % 6 == 5)             putchar('\n');   }   if (i % 6 != 0)        putchar('\n'); } 

Because i starts at 0, i % 6 first becomes 5 after six values have been printed. The expression subsequently becomes 5 after each additional six values have been printed.

The if (i % 6 != 0) test causes a newline to be printed after all the values have been printed, unless the last value printed was already at the end of a line ”in which case the loop itself prints a newline. If i % 6 is 5 inside the loop, the i++ operation at loop's end causes i % 6 to be 0 after leaving the loop.

The mean() Function

Finding the mean is a simple problem. You can use a for loop to sum the numbers and then divide by the total number of items to get the average:

 double mean(const double ar[], int n) {   int i;   double total = 0;   for (i = 0; i < n ; i++)        total += ar[i];   return (total / n); } 

The only potential trouble spot is if n is 0 because dividing by 0 is a no-no. The main() function shields mean() from this possibility.

The Result

Putting the parts together results in the program shown in Listing 10.20.

Listing 10.20 The mean.c program.
 /* mean.c -- finds the mean of a set of numbers */ #include <stdio.h> #define MAX 25 int read_array(double ar[], int limit); void show_array(const double ar[], int n); double mean(const double ar[], int n); int main(void) {   double data[MAX];   int size;   size = read_array(data, MAX);   if (size == 0)        printf("No data. Bye.\n");   else   {        printf("The following numbers were entered:\n\n");        show_array(data, size);        printf("\nThe average of these values is %.2f.\n",             mean(data, size));   }   return 0; } int read_array(double ar[], int limit) {   int i = 0;   printf("Enter up to %d numbers. To terminate\n", limit);   printf("earlier, enter a letter or EOF.\n");   while (i < limit  && scanf("%lf", &ar[i]) == 1)        i++;   return i; } void show_array(const double ar[], int n) {   int i;   for (i = 0; i < n; i++)   {        printf("%10.2f ", ar[i]);        if (i % 6 == 5)             putchar('\n');   }   if (i % 6 != 0)        putchar('\n'); } double mean(const double ar[], int n) {   int i;   double total = 0;   for (i = 0; i < n ; i++)        total += ar[i];   return (total/n); } 

Here's a sample run:

 Enter up to 25 numbers. To terminate earlier, enter a letter or EOF. 1 2 3 4 5 6 7 8 9 10 q The following numbers were entered:       1.00       2.00       3.00       4.00       5.00       6.00       7.00       8.00       9.00      10.00 The average of these values is 5.50. 
I l @ ve RuBoard


C++ Primer Plus
C Primer Plus (5th Edition)
ISBN: 0672326965
EAN: 2147483647
Year: 2000
Pages: 314
Authors: Stephen Prata

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net