In the previous article, we had a simple but functional program to compute the arithmetic mean of five numbers. The program design is not ideal however: it mixes input, output, and computation making it difficult to re-run the program an even a slightly different set of data. In this article we separate the computational part, so that changing inputs does not come close to affecting the part of the program which does the important work.
Here is the improved version:
// mean_v3.cpp
// Bojan Nikolic <bojan@bnikolic.co.uk>
// Do not mix input, computation, and output
#include <iostream>
double cmean( const double * data,
size_t n)
{
double sum =0;
for (size_t i =0 ; i < n ; ++i )
{
sum += data[i];
}
return (sum/n);
}
int main(void)
{
const double data[] = { 1,2,3,4,5};
const size_t n = 5;
std::cout<<"The mean is: "<< cmean(data, n) <<std::endl;
}
The change is that I have separated the computation of the mean to a separate function called cmean, while the input and output code remains in the function main.
The declaration of the function starts with the following lines:
double cmean( const double * data,
size_t n)
The elements of this declaration have the following meaning:
The rest of the function is the same as what was in the previous article in the function main.
This version improves the readability since it shows exactly where and how the mean is computed. It also allows computation of the mean of more then one set of data, or of several means. For example:
int main(void)
{
const double data[] = { 1,2,3,4,5};
const size_t n = 5;
std::cout<<"The mean is: "<< cmean(data, n) <<std::endl;
std::cout<<"The mean of all but last number is: "<< cmean(data, n-1) <<std::endl;
}
Computes both the mean and the mean with the last element of the data array excluded.
This version of the mean program introduces the key concept of pointers. A pointer to a type T is declared as T *. In the above example, the declaration in the function parameter list is:
const double * data
and so this is a pointer to a const double value.
Yet, within the function cmean however, we use this pointer value data in exactly the same way as we used the array variable data of the previous versing of this program. This is an important relationship and can cause some confusion. The reason for interchangeable use is that arrays and pointers are very closely related in C++.
The secret is in the operator []. For arrays, if you call it with i as the parameter, it returns the i+1-th element of the array (the +1 due to the zero-based counting of elements). That is, for example:
const double data[] = { 1,2,3,4,5};
std::cout<< data[3];
Prints the fourth element, which is 4.
For pointers, the same call with i as the parameter returns the value of the variable that is sequentially the i+1-th variable away in the memory. But elements of arrays are stored sequentially in memory, so this also returns the i+1-th element of the array. In an example:
const double data[] = { 1,2,3,4,5};
const double * pdata = data;
std::cout<< pdata[3];
Also returns the number 4.
This version of the mean program simplifies it by separating computation from input and output. It also introduces the concept pointers, which will come up a number of times in this series of articles. The next article makes a further improvement to readability and maintainability of this program.