Массивы. Перебор элементов массива
Что такое массив?
К счастью, структуры не являются единственным агрегированным типом данных в языке C++. Есть еще массив — совокупный тип данных, который позволяет получить доступ ко всем переменным одного и того же типа данных через использование одного идентификатора.
Рассмотрим случай, когда нужно записать результаты тестов 30 студентов в классе. Без использования массива нам придется выделить 30 почти одинаковых переменных!
|
1
2
3
4
5
6
|
// Выделяем 30 целочисленных переменных (каждая с разным именем)
intrestresultstudent1 ;
intrestresultstudent2 ;
intrestresultstudent3 ;
// ...
int testResultStudent30;
|
С использованием массива всё гораздо проще. Следующая строка эквивалентна коду, приведенному выше:
|
1
|
int testResult[30]; // выделяем 30 целочисленных переменных, используя фиксированный массив
|
В объявлении переменной массива мы используем квадратные скобки [], чтобы сообщить компилятору, что это переменная массива (а не обычная переменная), а в скобках — количество выделяемых элементов (это называется длиной или размером массива).
В примере, приведенном выше, мы объявили фиксированный массив с именем testResult и длиной 30. Фиксированный массив (или «массив фиксированной длины») представляет собой массив, размер которого известен во время компиляции. При создании testResult, компилятор выделит 30 целочисленных переменных.
Элементы массива
Каждая из переменных в массиве называется элементом. Элементы не имеют своих собственных уникальных имен. Вместо этого для доступа к ним используется имя массива вместе с оператором индекса [] и параметром, который называется индексом, и который сообщает компилятору, какой элемент мы хотим выбрать. Этот процесс называется индексированием массива.
В вышеприведенном примере первым элементом в нашем массиве является testResult[0], второй — testResult[1], десятый — testResult[9], последний — testResult[29]. Хорошо, что уже не нужно отслеживать и помнить кучу разных (хоть и похожих) имен переменных — для доступа к разным элементам нужно изменять только индекс.
Важно: В отличие от повседневной жизни, отсчет в программировании и в языке С++ всегда начинается с 0, а не с 1!
В массиве длиной N элементы массива будут пронумерованы от 0 до N-1! Это называется диапазоном массива.
Пример программы с использованием массива
Здесь мы можем наблюдать как определение, так и индексирование массива:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#include <iostream>
int main()
{
int array[5]; // массив из пяти чисел
array[0] = 3; // индекс первого элемента - 0 (нулевой элемент)
array[1] = 2;
array[2] = 4;
array[3] = 8;
array[4] = 12; // индекс последнего элемента - 4
std::cout << "The array element with the smallest index has the value " << array[0] << "\n";
std::cout << "The sum of the first 5 numbers is " << array[0] + array[1] + array[2] + array[3] + array[4] << "\n";
return 0;
}
|
Результат выполнения программы:
The array element with the smallest index has the value 3
The sum of the first 5 numbers is 29
Типы данных и массивы
Массив может быть любого типа данных. Например, объявляем массив типа double:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#include <iostream>
int main()
{
double array[3]; // выделяем 3 переменные типа double
array[0] = 3.5;
array[1] = 2.4;
array[2] = 3.4;
std::cout << "The average is " << (array[0] + array[1] + array[2]) / 3 << "\n";
return 0;
}
|
Результат выполнения программы:
The average is 3.1
Массивы также можно сделать из структур, например:
|
1
2
3
4
5
6
|
struct Rectangle
{
int length;
int width;
};
Rectangle rects[4]; // объявляем массив с 4-мя прямоугольниками
|
Чтобы получить доступ к члену структуры из элемента массива, сначала нужно выбрать элемент массива, затем использовать оператор выбора члена структуры, а затем требуемый член структуры:
|
1
|
rects[0].length = 15;
|
Индексы массивов
В языке C++ индексы массивов всегда должны быть интегрального типа данных (т.е. типа char, short, int, long, long long, bool и т.д.). Эти индексы могут быть либо константными значениями, либо неконстантными значениями. Например:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
int array[4]; // объявляем массив длиной 4
// Используем литерал (константу) в качестве индекса
array[2] = 8; // хорошо
// Используем перечисление (константу) в качестве индекса
enum Animals
{
ANIMAL_CAT = 3
};
array[ANIMAL_CAT] = 5; // хорошо
// Используем переменную (не константу) в качестве индекса
short index = 4;
array[index] = 8; // хорошо
|
Объявление массивов фиксированного размера
При объявлении массива фиксированного размера, его длина (между квадратными скобками) должна быть константой типа compile-time (которая определяется во время компиляции). Вот несколько разных способов объявления массивов с фиксированным размером:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
// Используем литерал
int array[7]; // хорошо
// Используем макрос-объект с текст_замена в качестве символьной константы
#define ARRAY_WIDTH 4
int array[ARRAY_WIDTH]; // синтаксически хорошо, но не делайте этого
// Используем символьную константу
const int arrayWidth = 7;
int array[arrayWidth]; // хорошо
// Используем перечислитель
перечисление ArrayElements
{
MIN_ARRAY_WIDTH = 3
};
int array[MIN_ARRAY_WIDTH]; // хорошо
// Используем неконстантную переменную
int ширина;
std::cin >>>> > ширина;
int array[width]; // плохо: width должна быть константой типа compile-time!
// Используем константную переменную типа runtime
int temp = 8;
const int width = temp;
int array[width]; // плохо: здесь width является константой типа runtime, но должна быть константой типа compile-time!
|
Обратите внимание, в двух последних случаях мы должны получить ошибку, так как длина массива не является константой типа compile-time. Некоторые компиляторы могут разрешить использование таких массивов, но они являются некорректными в соответствии со стандартами языка C++ и не должны использоваться в программах, написанных на C++.
Чуть-чуть о динамических массивах
Поскольку массивам фиксированного размера память выделяется во время компиляции, то здесь мы имеем два ограничения:
Массивы фиксированного размера не могут иметь длину, основанную на любом пользовательском вводе или другом значении, которое вычисляется во время выполнения программы (runtime).
Фиксированные массивы имеют фиксированную длину, которую нельзя изменить.
Во многих случаях эти ограничения являются проблематичными. К счастью, C++ поддерживает еще один тип массивов, известный как динамический массив. Размер такого массива может быть установлен во время выполнения программы и его можно изменить. Однако создание динамических массивов несколько сложнее фиксированных, поэтому мы поговорим об этом несколько позже.
Заключение
Фиксированные массивы обеспечивают простой способ выделения и использования нескольких переменных одного типа данных до тех пор, пока размер массива известен во время компиляции.
На следующем уроке мы рассмотрим больше тем, связанных с фиксированными массивами.