Laboratory Training 5

Use of Arrays

1 Training Tasks

1.1 Sum of the Minimum and Maximum Items

Write a program that calculates the sum of the minimum and maximum items of an array of double precision floating point values. Use two separate functions.

1.2 Multiplication of Matrices

Implement a program for filling two two-dimensional arrays (matrices) of the required length with pseudorandom numbers, finding the product of matrices and displaying the result on the screen.

1.3 Individual Assignment

You should create a program that defines and initializes a two-dimensional array of integer items and then implements following activities:

  • transformation of the source array according to step one of the individual assignment
  • creation and filling of a new (one-dimensional) array of double precision floating point type items according to step two of the individual assignment
  • output of both array items

The program should signal errors if transformation or filling are not possible.

Index of variant
(from students list)
Rule of a source array transformation (step one) Rule of filling of a new array using items of transformed source array (step two).
Resulting array should contain:
Row count
m
Column count
n
1
All items with odd values should be doubled Square roots of minimal positive items of rows
4
3
2
All items with even values should be replaced with their squares Cubic roots of minimal items of columns
3
5
3
All items with null value should be replaced with ones Natural logarithms of maximum positive items of rows
3
4
4
All items with even values should be doubled Natural logarithms of minimal positive items of columns
4
5
5
All items should be replaced with their absolute magnitudes Minimal items of columns
5
4
6
All items with even values should be tripled Cubic roots of diagonal items
3
3
7
All positive items should be replaced with integer parts of their Briggs (base ten) logarithms Sums of negative items of columns
4
5
8
All negative items should be replaced with their squares Square roots of diagonal items
4
4
9
All positive items should be replaced with integer parts of their Napierian (natural) logarithms Products of negative items of rows
5
4
10
All positive items should be replaced with integer parts of their square roots Maximum positive items of rows
3
5
11
All positive items with even values should be doubled Cubic roots of maximum items of columns
5
4
12
All negative items with odd values should be tripled Square roots of minimal positive items of columns
3
4
13
All negative items with odd values should be doubled Sums of Briggs (base ten) logarithms of positive items of rows
4
3
14
All positive items with even values should be tripled The result of division of maximal positive items of columns by their Briggs (base ten) logarithms
3
5

To calculate standard mathematical functions you should include cmath header file.

1.4 Sorting an Array using the Selection Method (Additional Task)

Write a program that implements the sorting items of an array of integers using the Selection method.

2 Instructions

2.1 Definition of One-Dimensional Arrays

2.1.1 Concept of Arrays

A very important part of the programmers' work is related to so-called collections. A collection is a data structure of one or different types, which can be accessed as a whole, and also allows work with individual items. In most cases, collection contains objects of the same type. There are different methods of storing and accessing items.

An array in the general sense is a data structure that provides access to an item through a specific key. For example, in so-called associative arrays, the key can be any object, for example, a number, letter, string, structure, etc.

The simplest form of an array is the so-called indexed array. This is an array that supports only numeric indices: integers in a certain range. The items of such an array are located sequentially in memory. Next we will work with the simplest form by the array.

An array is actually the simplest collection. An array is a data structure that meets the following characteristics:

  • the array contains items of the same type;
  • all items of the array occupy a continuous block of memory;
  • access to the items is carried out by determining the index (number) of the item in the array.

Arrays can be one-dimensional and multidimensional. In programming, one-dimensional arrays are used to store a large number of identical variables. Items can be individual numbers (measurements of temperature, voltage, number of days in months, number of classes on different days of the week, number of passengers in cars, etc.), strings (surnames, names of cities, countries, etc.) or complex objects.

Two-dimensional arrays are used, for example, to work with matrices or other rectangular tables. It is much less common to create arrays with more dimensions.

Work with arrays is implemented in almost all programming languages. There are syntactic differences in the mechanisms for addressing items. Usually, items are referred to by specifying the index in parentheses or square brackets. In C++, the index is specified in square brackets.

Array items in most languages are numbered starting from zero. This makes it easier to access items. Items are located sequentially in memory

a[0]
a[1]
...
a[n - 1]

If addr_0 is the address of the zero (initial) item of the array, and sizeof(item) is the number of bytes for storing one item of the array, the address of the item with index i (addr_i) can be easily calculated by the formula

addr_i = addr_0 + i * sizeof(item)

As can be seen from this formula, items can be accessed almost as quickly as individual variables. In no case, to select an item by index, it is not necessary to sequentially traversal through the items.

2.1.2 Creation of One-Dimensional Arrays

The following syntax is used to create a one-dimensional array in C++:

item_type array_name[number_of_items];

The array name is an identifier constructed according to general rules. If it is difficult to determine the physical meaning of the array, you can use a, b, c, or arr. The number of items is determined by a constant. The number of array items is called its size, as well as its length.

For example, you can create an array of ten items of the type double:

double a[10];

In our example, the compiler allocates a block of memory in which 10 numbers of double type can be placed. Since each such number occupies 8 bytes, the compiler reserves 80 consecutive bytes of memory.

In the C++ code, to obtain a separate item of the array, the subscript operation ([]) is used. In our example, a[0] refers to the initial item. The last index should be one less than the number of items. In our case, the last item can be obtained as follows: a[9].

You can use constants (constant expressions) to determine the size of the array. You cannot use constants that cannot be computed at compile time, as well as variables:

const int n = 10;      // explicit constant
int firstArr[n];       // OK
const int n1 = n + 3;  // constant expression
int secondArr[n1 + 2]; // OK: the size can be calculated by the compiler
// The following constant cannot be calculated by the compiler:
const int m = std::pow(3, 3) / 3;
int thirdArr[m];       // compile error
int m1 = 4;            // variable
int fourthArr[m1];     // compile error

C++ has no mechanism for resizing an array that has already been created. The only way is to create a new array of another length and copy the existing items there.

2.1.3 Initialization of Arrays

You can initialize a simple array, when you first declare this array. After the array name, you can put an equal sign (=) and a list of comma-separated values enclosed in braces. For example,

int integerArray[5] = { 1, 2, 3, 4, 5 };

declares integerArray to be an array of five integers. It assigns integerArray[0] the value 1, integerArray[1] the value 2, and so forth.

If you omit the size of the array, an array just big enough to hold the initialization is created. This definition is the same as previous one:

int integerArray[] = { 1, 2, 3, 4, 5 };

You cannot initialize more items than you've declared for the array. Therefore,

int integerArray[5] = { 1, 2, 3, 4, 5, 6 };

generates a compiler error. It is legal, however, to write

int integerArray[5] = { 1, 2 };

Although uninitialized array members have no guaranteed values, actually, aggregates will be initialized to 0. If you do not initialize an array member, its value will be set to 0.

2.2 Using Arrays

2.2.1 Working with Array Items

Individual items of arrays are accessed using the array subscript operator ([]). The value of the index is set using a constant, variable or expression, if it can be reduced to an integer type:

int i = 0;
integerArray[i] = 11;
k = integerArray[2];
integerArray[k % 10 + 1] = 0;

A for loop is usually used to perform typical operations on array items. If n is the number of the array items, then in order to go through all the items, we create the following loop:

const int n = 5;
int a[n];
for (int i = 0; i < n; i++)
    // work with individual items

For example, in this way, you can write the value 0 in all items of an array of integers:

const int n = 5;
int a[n];
for (int i = 0; i < n; i++)
{
    a[i] = 0;
}

A typical mistake of beginners is to organize the loop including n:

const int n = 5;
int a[n];
for (int i = 0; i <= n; i++) // i cannot be equal to n
{
    a[i] = 0; // error at the last step of the loop
}

The reaction may be different depending on the compiler and its version . For example, there may be an error message when running a program, but sometimes the values of other variables are eventually changed.

It is also possible to read arrays from the keyboard and display the array on the screen only in a loop. This is how you can read items from the keyboard:

const int n = 6;
double a[n];
for (int i = 0; i < n; i++)
{
    cin >> a[i];
}

This is how all items can be displayed on the screen:

for (int i = 0; i < n; i++)
{
    cout << a[i] << " ";
}
cout << endl;.

In the above example, the items to be output are separated by spaces. You can also use tab or new line characters if needed.

You cannot assign one array to another. This expression generates syntax error.

const int n = 4;
double a[n]; 
double b[n] = { 11, 72, 4, 18 };
a = b; // syntax error

You should create a special cycle to copy one array into another:

const int n = 4;
double a[n]; 
double b[n] = { 11, 72, 4, 18 };
for (int i = 0; i < n; i++)
{
    a[i] = b[i];
}

Within the block in which the array is defined, its length can be obtained using the expression sizeof(array_name)/sizeof(item_type). Example:

const int n = 6;
double a[n];
for (int i = 0; i < sizeof(a)/sizeof(double); i++)
{
    cin >> a[i];
}

2.2.2 Using Range-Based Loops

You cannot create an array of references, but you can declare a reference to any particular item of an array:

double a[] = { 1, 2, 4, 8 };
double& y = a[3];
y = 16; // a[3] = 16

You can also create a reference to the entire array and use it as an array:

int (&b)[4] = a;
b[0] = 3;

To iterate array items without using index, a new version of C++ language (starting from C++11) offers an alternative cycle construction: range-based for loop:

for (item_type &variable: array)
    looping_body

Within a loop body, you can use a variable as the current item of an array. For example, this way you can assign ones to all the items of an array:

int arr[4];
for (int& k : arr)
{
    k = 1;
}

If no modification of items is provided in the body of the loop, it is better to describe a reference to a constant object:

int arr[] = { 1, 2, 3 };
for (const int &k : arr)
{
    std::cout << k << " ";
}

You cannot use an index or bypass part of an array in the body of the loop.

Unfortunately, a range-based for statement can only be used for arrays within the blocks in which those arrays are defined.

2.2.3 Examples of Tasks Related to Arrays

Typical actions with arrays of numbers are, for example, finding sums, products, items with the largest, smallest value, etc. In the following example, we calculate the product of the array items:

#include <iostream>
using namespace std;

int main()
{
    double a[] = { 1, 2, 3, 4 };
    double product = 1;
    for (const double& elem : a)
    {
        product *= elem;
    }
    cout << product; // 24
    return 0;
}

If the actions do not involve the involvement of all items, you should not use a loop built on a range. This is how you can find the sum of array items with even indices:

#include <iostream>
using namespace std;

int main()
{
    const int n = 6;
    double a[n] = { 1, 2, 3, 2, 1, 6 };
    double sum = 0;
    for (int i = 0; i < n; i += 2)
    {
        sum += a[i];
    }
    cout << sum; // 5
    return 0;
}

In the example 3.2, the index of the maximum item of the array is searched.

A separate group of actions is changing the arrangement of items, in particular, sorting by some criterion. In the example below, neighboring items are swapped:

#include <iostream>
using namespace std;

void swap(int& x, int& y)
{
    int z = x;
    x = y;
    y = z;
}

int main()
{
    const int n = 5;
    int a[n] = { 1, 2, 3, 2, 10 };
    for (int i = 0; i < n - 1; i += 2)
    {
        swap(a[i], a[i + 1]);
    }
    for (const int& item : a)
    {
        cout << item << " "; // 2 1 2 3 10
    }
    return 0;
}

The last item remains in its place, because it has no partner.

The program that implements sorting by the bubble method is shown in the example 3.3.

2.3 One-Dimensional Arrays as Function Parameters

Array names can be used as actual arguments of a function. Array name without square brackets is essentially an address of the first item of an array. A copy of this address is assigned to the corresponding parameter. The function can use this address to access the array items. For example, the function calculates and returns the sum of the items of an array of length n:

#include <iostream>
using namespace std;

const int n = 5;

double sum(double arr[])
{
    double result = 0;
    for (int i = 0; i < n; i++)
    {
        result += arr[i];
    }
    return result;
}

int main()
{
    double a[] = { 1, 2, 4, 8, 16 };
    double y = sum(a);
    cout << y << endl; // 31
    return 0;
}

Note: it is not possible to use a loop built on a range in the body of a sum() function, because the array is created in another function.

There is no way to get the actual number of array items inside the function. Therefore, if we want the size of the array, we pass it as a separate parameter:

#include <iostream>
using namespace std;

double sum(double arr[], int n)
{
    double result = 0;
    for (int i = 0; i < n; i++)
    {
        result += arr[i];
    }
    return result;
}

int main()
{
    double a[] = { 1, 2, 4, 8, 16 };
    double y = sum(a, 5);
    cout << y << endl; // 31
    return 0;
}

Since in the function we receive the address of the array, we work with the same array. Therefore, changes made to the items remain in the calling function. For example,

#include <iostream>
using namespace std;

void spoil(double arr[])
{
    arr[0] = 0;
}

int main()
{
    const int n = 4;
    double a[] = {1, 2, 4, 8};
    for (int i = 0; i < n; i++)
    {
        cout << a[i] << ' '; //1 2 4 8
    }
    cout << endl;
    spoil(a);
    for (int i = 0; i < n; i++)
    {
        cout << a[i] << ' '; //0 2 4 8
    }
    cout << endl;
    return 0;
}

In order to avoid accidentally changing the values of the array items in the function, the parameter can be passed with the const modifier:

void f(const double arr[])
{
... // the compiler will not allow changing the values of items
}

2.4 Filling Arrays with Random Numbers

When debugging and testing programs involving arrays, filling arrays with random or pseudo-random numbers is often used. Random and pseudo-random numbers were discussed earlier. Pseudorandom numbers can be used to debug the program.

The following program fills an array of five integers with pseudo-random numbers from 0 to 19, inclusive:

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
    const int n = 5;
    int randomArr[n];
    for (int& item : randomArr)
    {
        item = rand() % 20;
    }
    for (const int& item : randomArr)
    {
        cout << item << " "; // 1 7 14 0 9
    }
    return 0;
}

After each start results will be the same.

To obtain random numbers, we use the time(0) function (ctime header file). Now the program will look like this:

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int main()
{
    const int n = 5;
    int randomArr[n];
    srand(time(0));
    for (int& item : randomArr)
    {
        item = rand() % 20;
    }
    for (const int& item : randomArr)
    {
        cout << item << " "; // random numbers from 0 to 19 inclusive
    }
    return 0;
}

Random numbers should be used for testing rather than for debug.

2.5 Multidimensional Arrays

It is possible to create arrays of more than one dimension. Each dimension is represented as a subscript in the array. Therefore, a two-dimensional array has two subscripts; a three-dimensional array has three subscripts; and so on. Arrays can have any number of dimensions, however most of the arrays you create will be of one or two dimensions.

If the program contains such a definition,

// Previously, integer constants m and n were defined
double a[m][n];

the compiler will create an array of floating point numbers from m rows and n columns, which represents a rectangular table (matrix):

a[0][0]
a[0][1]
...
a[0][n - 1]
a[1][0]
a[1][1]
...
a[1][n - 1]
...
...
...
...
a[m - 1][0]
a[m - 1][1]
...
a[m - 1][n - 1]

Physically, such an array will be located in m × n sequentially arranged memory cells:

a[0][0]
a[0][1]
...
a[0][n - 1]
a[1][0]
a[1][1]
...
a[1][n - 1]
...
a[m - 1][0]
a[m - 1][1]
...
a[m - 1][n - 1]

In fact, in memory we work with a one-dimensional array. Such an array can be created explicitly:

double b[m * n];
b[i * n + j] = 0; // for a two-dimensional array a[i][j] = 0;

Using a two-dimensional array is more comfortable for the programmer.

You can initialize multidimensional arrays. You assign the list of values to array items in order, with the last array subscript changing while each of the former holds steady. Therefore, if you have an array

int theArray[5][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };

the first three items go into theArray[0]; the next three into theArray[1]; and so forth.

For the sake of clarity, you could group the initializations with braces. For example,

int theArray[5][3] = { { 1,  2,  3 },
                       { 4,  5,  6 },
                       { 7,  8,  9 },
                       {10, 11, 12 },
                       {13, 14, 15 } };

The compiler ignores the inner braces, which make it easier to understand how the numbers are distributed. Each value must be separated by a comma, without regard to the braces. The entire initialization set must be within braces, and it must end with a semicolon.

Only the first pair of brackets can be empty:

int theArray[][3] = { { 1,  2,  3 },
                      { 4,  5,  6 },
                      { 7,  8,  9 },
                      {10, 11, 12 },
                      {13, 14, 15 } };

In this case, compiler counts first size automatically.

As with one-dimensional arrays, items whose values ​​are missing from the list are filled with zeros (default values ​​for a certain type). For example, the values of all array items will be set to zeros:

const int m = 4;
const int n = 3;
int arr[m][n] = { };

Nested loops are usually used to work with items of a multidimensional array. For example, this is how we can write into items the sum of their indices:

for (int i = 0; i < m; i++)
{
    for (int j = 0; j < n; j++)
    {
        arr[i][j] = i + j;
    }
}

Using i index for the row number and j index for the column number is optional, but is traditional for working with two-dimensional arrays.

You can apply range-based loops to multidimensional arrays. For example, this is how we can put ones into all array items:

for (auto& row : arr)
{
    for (int& item : row)
    {
        item = 1;
    }
    cout << endl;
}

This is how we can display the items of a two-dimensional array line by line:

for (const auto &row : arr)
{
    for (const int &item : row)
    {
        cout << item << "\t";
    }
    cout << endl;
}

The use auto here has reason, as otherwise the loop header would be more complex:

for (const int(&row)[n] : arr)

There is a problem with a transferring of multidimensional arrays to the functions. In fact, it is necessary to create separate functions, clearly indicating the second, third and other dimensions (except for the first). For example:

double f(double a[][3])
{
    return a[1][1];
}

This function can be invoked:

int main()
{
    double arr[][3] = { { 1, 2, 3 },
                        { 4, 5, 6 } };
    cout << f(arr);
    return 0;
}

A similar approach is usually not used and bypass the problem through the use of pointers.

3 Sample Programs

3.1 Sum of Items

Suppose you need to find the sum of items of a one-dimensional array of integers. The program can be as follows:

#include <iostream>
using namespace std;

int main()
{
    double a[] = { 1, 2, 3, 4 };
    double s = 0;
    for (int i = 0; i < sizeof(a)/sizeof(double); i++)
    {
        s += a[i];
    }
    cout << s << endl; // 10;
    return 0;
}

It is possible to propose the implementation of the program by creating a separate sum() function that calculates and returns the sum of the array items. The advantage of this solution is the ability to calculate the sum of different arrays, as well as to find the sum of part of items:

#include <iostream>
using namespace std;

double sum(double arr[], int n)
{
    double s = 0;
    for (int i = 0; i < n; i++)
    {
        s += arr[i];
    }
    return s;
}

int main()
{
    double a[] = { 1, 2, 3, 4 };
    cout << sum(a, 4) << endl; // 10;
    cout << sum(a, 3) << endl; // 6;
    return 0;
}

3.2 Maximal Item

It is necessary write a program that finds maximal item of an integer array.

#include <iostream>

using namespace std;

int main()
{
    const int n = 4;
    int a[] = { 1, 2, 4, 8 };
    int indexOfMax = 0;
    for (int i = 1; i < n; i++)
    {
        if (a[i] > a[indexOfMax])
        {
            indexOfMax = i;
        }
    }
    cout << indexOfMax << ' ' << a[indexOfMax];
    return 0;
}

3.3 Sorting

It is necessary to write a program that sorts items of double array in ascending order using Bubble sort algorithm.

#include<iostream>
using namespace std;

void sort(double a[], int size)
{
    bool mustSort; // We must repeat sorting
                   // if mustSort is equal true
    do
    {
        mustSort = false;
        for (int i = 0; i < size - 1; i++)
        {
            if (a[i] > a[i + 1])
            {
                double temp = a[i];
                a[i] = a[i + 1];
                a[i + 1] = temp;
                mustSort = true;
            }
        }
    } while (mustSort);
}

int main()
{
    const int n = 5;
    double a[] = { 11, 2.5, 4, 3, 5 };
    sort(a, n);
    for (double &item : a)
    {
        cout << item << ' ';
    }
    return 0;
}

3.4 Finding the Sum of Matrices

Two-dimensional arrays are often used to perform operations on mathematical matrices. The following program demonstrates finding the sum of matrices. The source matrices are filled with pseudorandom numbers.

#include <cstdio>
#include <iostream>
using namespace std;

// The function returns a valid value between 0 and 100
double nextRandom()
{
    return (rand() % 10000) / 100.;
}

int main()
{
    const int m = 3;
    const int n = 4;
// Create and fill array a:
    double a[m][n] = {};
    for (auto& row : a)
    {
        for (double& item : row)
        {
            item = nextRandom();
        }
    }
    for (const auto& row : a)
    {
        for (const double& item : row)
        {
            cout << item << "\t";
        }
        cout << endl;
    }
    cout << endl;
// Create and fill array b:
    double b[m][n] = {};
    for (auto& row : b)
    {
        for (double& item : row)
        {
            item = nextRandom();
        }
    }
    for (const auto& row : b)
    {
        for (const double& item : row)
        {
            cout << item << "\t";
        }
        cout << endl;
    }
    cout << endl;
// Calculate and output the sum of matrices:
    double c[m][n] = {}; 
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            c[i][j] = a[i][j] + b[i][j];
        }
    }
    for (const auto& row : c)
    {
        for (const double& item : row)
        {
            cout << item << "\t";
        }
        cout << endl;
    }
    return 0;
}

As you can see from the code, a range-bsed loop can be used only if we do not use index values.

3.5 Sum of Products

It is necessary write a program that declares two-dimensional array and finds the sum of products of its rows.

#include<iostream>
using namespace std;

int main()
{
    const int  m = 4;
    const int  n = 3;
    int a[m][n] = { { 1, 2, 3 },
                    { 2, 3, 4 },
                    { 0, 1, 2 },
                    { 1, 1, 12} };
    int sum = 0;
    for (const auto &row : a)
    {
        int product = 1;
        for (const int &item : row)
        {
            product *= item;
        }
        sum += product;
    }
    cout << sum;
    return 0;
}

3.6 Replacement

It is necessary to write a program that replaces all negative items of two-dimensional array with zeros.

#include<iostream>
using namespace std;

int main()
{
    const int m = 3;
    const int n = 3;
    double a[][n] = { { 1,  -2,  3 },
                      { 2.1, 3, -4 },
                      { 0,-0.5, 11 } };
    for (auto& row : a)
    {
        for (double& item : row)
        {
            if (item < 0)
            {
                item = 0;
            }
        }
    }
    for (const auto& row : a)
    {
        for (const double& item : row)
        {
            cout << '\t' << item;
        }
        cout << endl;
    }
    return 0;
}

4 Exercises

  1. Write a program that reads unsigned short integers and prints their binary representation in reverse order.
  2. Write a program that calculates sum of positive items of an array of doubles.
  3. Write a program that defines an array of doubles and calculates sum of items with odd indices.
  4. Write a program that defines an array of integers and calculates sum of even items.
  5. Write a program that declares two-dimensional array and calculates the product of the maximal items of its columns.

5 Quiz

  1. What is an array? Where are arrays used?
  2. What ensures the efficiency of access to array elements?
  3. What is subscript operator?
  4. What is starting index of an array?
  5. Can you use variables to determine the length of an array?
  6. Can you change the size of an array after creation?
  7. How to add a new item to the end of the array?
  8. How to enter array elements from the keyboard?
  9. How to display the elements of the array in the console window?
  10. How to copy values of items from one array to another?
  11. How to get the array length at runtime?
  12. How to create an array of references and array references?
  13. What is range-based loop?
  14. What are the restrictions on using range-based loops?
  15. How to transfer arrays to functions?
  16. How to get the length of an array inside the function where this array is passed?
  17. How to fill an array with random numbers?
  18. What are multidimensional arrays used for?
  19. How to determine the number of columns in a two-dimensional array?
  20. How to initialize two-dimensional array?
  21. How to apply range-based loop for 2D arrays?
  22. How to pass a multidimensional array to a function?

 

up