Review - Call-by-Reference Parameters
To return more than one value from a function.
e.g.:
void get_two_symbols(char& sym1, char& sym2)
{
cout << "Please input two characters: ";
cin >> sym1 >> sym2;
return;
}
How would we use this?
int main()
{
char symbol1, symbol2;
get_two_symbols (symbol1, symbol2);
cout << "The characters you entered are: "
<< symbol1 << " and " << symbol2
<< "." << endl;
return 0;
}
Review - Call-by-Value vs. Call-by-Reference
Reminder:
Formal parameter is the name that the function associates with its argument (i.e.
sym1 and sym2 below).void get_two_symbols (char& sym1, char& sym2);
Argument is the variable supplied for the formal parameter (i.e.
symbol1 and symbol2 below).get_two_symbols(symbol1, symbol2);
Arrays - Introduction
An array is a data structure that allows you to group together a collection of items of the same type. Let us say we need a collection of 5 items. We may declare an array called
value to hold them:int value[5];
int
is said to be the base type of the array value. The 5 tells the compiler how many items we have and is referred to as the index or (subscript) of the array.Note:
#include <iostream.h>
int square(int n);
// returns n*n
int main()
{
int i, value[5]; // value[0], value[1], ..., value[4]
cout << "Enter 5 integers: ";
cin >> value[0] >> value[1] >> value[2]
>> value[3] >> value[4];
cout << "\nYou entered:\n"
<< "\t#0: " << value[0] << endl
<< "\t#1: " << value[1] << endl
<< "\t#2: " << value[2] << endl
<< "\t#3: " << value[3] << endl
<< "\t#4: " << value[4] << endl
cout << "Which one do you want to square? ";
cin >> i;
cout << "\nSquare of #"<< i << " is: " << square(value[i])";
return 0;
}
int square(int n)
{
return n*n;
}
The compiler reserves enough contiguous space in memory to hold five variables of type
int.The address of the array
value is the address of the first indexed variable value[0]. Since all values in an array must be of the same type, then the address of any particular entry in the array may be readily determined from the address of the first entry.Let us say the block of memory allocated to array
value starts at memory location 1023. Since integers are stored using two bytes:In general, for some value
i, value[i] is stored in the two byte memory location starting at 1023 + 2*i. So, if i=4, then since 1023+2*4 =1031, value[4] is in 1031 and 1032.
Index out of range problem
Consider the previous example. The array
value has been declared to have 5 integers and so memory locations 1023 to 1032 have been reserved for this array.Q: What if we inadvertently attempt to access
value [6] that is some memory location beyond 1032???A: Some versions of C++ will give you an out of range message, most will try to find the location of the bogus indexed variable
value[6]. It does this by computing the address of value[6]as an offset of the address for value[0]. That is, memory location 1035. Whatever is at that memory location will be accessed!!!
Warning:
For the above example, memory location 1035 could belong to some other program or, even worse, it may represent the instructions of some program (including the rogue program). If that memory location is altered then the effect will be unpredictable.
Out of range errors are particularly hard to debug. Make sure that you never let an array go out of bounds. Your code should be so structured that it checks bounds before accessing/storing array values.
Initializing Arrays
We can initialize an array in two ways:
Individually:
int cats_age[3];
cats_age[0] = 9;
cats_age[1] = 8;
cats_age[2] = 4;
As a group:
int cats_age[3] = {8,7,3};
Note: C++ will initialize entries specified and leave the others un-initialized (hence containing garbage).
Initializing Arrays
A for-loop may be used to initialize a large array:
int scores[35], i, numbers[10];
for (i =0; i < 35; i++)
scores[i] = 0;
for (i =0; i < 10; i++)
numbers[i] = i;
As for an ordinary variable, you should initialize the array to a known value before using it. Never assume that an array is automatically initialized by the compiler!
Arrays in Functions
You can use both indexed variables (one element of an array) and entire arrays as arguments to functions. Since an indexed variable can be used anywhere that a variable of its type is expected, we can use it as the argument to a function.
e.g. Compute the sum of squares: num[0]2+num[1]2+ ...
#include <iostream.h>
const int MAX = 5;
int square (int n);
// This function takes an integer n and returns n*n
int main ()
{
int i, num[MAX], root_sum = 0;
cout << "Please enter " << MAX << " integers: ";
for (i = 0; i < MAX; i++)
cin >> num[i];
for (i = 0; i < MAX; i++)
root_sum += square(num[i]);
cout << endl;
for (i = 0; i < MAX; i++)
cout << "\t#" << i << " = " << num[i] << endl;
cout << "\nThe sum of the squares of the number is: "
<< root_sum << "\n\n";
return 0;
}
int square (int n)
{
return (n*n);
}
Arrays in Functions
It is possible to use entire arrays as the argument to functions. Recall that a call-by-value parameter to a function has the value for the argument copied into what amounts to a local variable in the function.
A call-by-reference parameter gives the address of its variable to the function and all changes to the formal parameter will result in changes to the original variable.
A function can have a formal parameter for an entire array. Such a parameter is known as an array parameter. The array parameter behaves very much like a call-by-reference variable but it does not require an & adjacent to the type.
void enter_integers(int num[], int size)
{
cout << "Enter " << size << " integers: ";
for (i = 0; i < size; i++)
cin >> num[i];
return;
}
This function has two arguments:
Note: Remember that an array parameter is like a call-by-reference variable, changes made to the array are reflected in the original array.
Note:
Think of an array parameter as a weak form of call-by-reference. We know everything about the array that's passed except the number of indexed entries in the array. One benefit of this is that the same function can be used on any array of a given type regardless of its size.
The
const parameter modifierWe've seen that when you use an array as a parameter to the function then any changes to the array in the function will be reflected in the array that was passed as an argument.
If we do not need to modify the array we may use the modifier
const.e.g: a function that outputs the entries of an array:
void output_array(const int number[], int size)
{
int i;
for (i = 0; i < size; i++)
cout << "\t#" << i << " = " << number[i] << endl;
}
Note:
If you use
const in the definition of a function then you have to make sure that you use it in every function called within this function definition.e.g: Suppose that we also wanted to output the sum of the array elements in our output_array function.
int compute_sum(int num[], int size)
{
int i,sum=0;
for (i = 0; i < size; i++)
sum += num[i];
return sum;
}
Now, change
output_array so that it calls compute_sum:void output_array(const int number[], int size)
// prints out the content of the array[]
{
int i;
for (i = 0; i < size; i++)
cout << "\t#" << i << " = " << number[i]
<< endl;
cout << "The sum is: " << compute_sum(number[], size);
}
output_array
(which has const int number[]) calls compute_sum which does not place the const restriction on the array parameter resulting in an error.We can now re-write the program to compute the sum of squares:
#include <iostream.h>
const int MAX = 5;
int square (int n);
// This function takes an integer n and returns n*n
void ask_numbers(int number[], int size);
// Asks the user to input the values in number[]
int sum_of_squares(int number[], int size);
// returns the sum of the squares in number[]
void output_array(int number[], int size);
// prints out the content of the array[]
int main ()
{
int num[MAX], square_sum = 0;
ask_numbers(num, MAX);
square_sum = sum_of_squares(num, MAX);
cout << endl;
output_array(num, MAX);
cout << "\nThe sum of the squares of the number is: "
<< square_sum << "\n\n";
return 0;
}
void ask_numbers(int number[], int size)
// Asks the user to input the values in number[]
{
int i;
cout << "Please enter " << size << " integers: ";
for (i = 0; i < size; i++)
cin >> number[i];
}
int sum_of_squares(const int number[], int size)
// returns the sum of the squares in number[]
{
int i, sq_sum = 0;
for (i = 0; i < size; i++)
sq_sum += square(number[i]);
return sq_sum;
}
void output_array(const int number[], int size)
// prints out the content of the array[]
{
int i;
for (i = 0; i < size; i++)
cout << "\t#" << i << " = " << number[i] << endl;
}
int square (int n)
{
return (n*n);
}
Programming with arrays
See pages 535 - 548 of the text.