Массивы


Предыдущая страница
Следующая страница  

Язык D предоставляет структуру данных, называемую массивом, которая хранит последовательную коллекцию элементов фиксированного размера одинакового типа. Массив используется для хранения коллекции данных. Часто бывает полезно думать о массиве, как о коллекции переменных одинакового типа.

Вместо объявления отдельных переменных, таких как number0, number1, ... и number99, вы объявляете одну переменную массива, такую как numbers, и используете нотацию numbers[0], numbers[1], и ..., numbers[99], которая представляет отдельные переменные. К конкретному элементу массива обращение производится по индексу.

Все массивы состоят из смежных областей памяти. Нижний адрес соответствует первому элементу, а высший адрес – последнему элементу.

Объявление массивов

Чтобы на языке D объявить массив, программист указывает тип элементов и их количество, требуемое для массива, следующим образом:

тип имя_массива [ размер_массива ];

Это называется одномерным массивом. размер_массива должен быть целочисленной константой больше нуля, а тип может быть любым допустимым типом данных языка D. Например, чтобы объявить 10-элементный массив типа double с именем balance, используйте такой оператор:

double balance[10]; 

Инициализация массивов

В языке D вы можете инициализировать элементы массива по одному, или сразу все с помощью одного оператора следующим образом:

double balance[5] = [1000.0, 2.0, 3.4, 7.0, 50.0];

Количество значений между квадратными скобками [ ] с правой стороны не может быть больше числа элементов, которое вы объявляете для размера массива между квадратными скобками [ ] слева.

Если вы опускаете размер массива, будет создан массив, достаточно большой для хранения инициализирующих значений. Поэтому, если вы пишете

double balance[] = [1000.0, 2.0, 3.4, 7.0, 50.0]; 

то вы создадите точно такой же массив, как в предыдущем примере.

balance[4] = 50.0; 

Вышеприведенный оператор присваивает элементу массива номер 5 значение 50.0. Массив с индексом 4 будет пятым, т.е. последним элементом, потому что все массивы имеют 0 в качестве индекса своего первого элемента, который также называется базовым индексом. На следующем изображении показан тот же массив, о котором мы говорили выше:

Array Presentation

Доступ к элементам массива

Доступ к элементу осуществляется через индексацию имени массива. Это делается путём размещения индекса элемента в квадратных скобках после имени массива. Например:

double salary = balance[9];

Вышеприведенный оператор принимает 10-й элемент из массива и присваивает значение переменной salary. Следующий пример реализует объявление, присваивание и доступ к массиву:

import std.stdio;  
void main() { 
   int n[ 10 ]; // n - это массив из 10 целых чисел  
   
   // инициализация элементов массива 
   for ( int i = 0; i < 10; i++ ) { 
      n[ i ] = i + 100; // Установить элемент, расположенный по индексу i, в значение i + 100 
   }
   
   writeln("Элемент \t Значение");
   
   // вывод каждого из значений элементов массива 
   for ( int j = 0; j < 10; j++ ) { 
      writeln(j, " \t ", n[j]); 
   } 
}

Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:

Элемент	 Значение
0 	 100
1 	 101
2 	 102
3 	 103
4 	 104
5 	 105
6 	 106
7 	 107
8 	 108
9 	 109

Статические массивы и динамические массивы

Если длина массива задана во время написания программы, такой массив является статическим массивом. Когда длина может меняться во время выполнения программы, такой массив является динамическим массивом.

Определение динамических массивов проще, чем определение массивов фиксированной длины, поскольку при отсутствии длины создаётся динамический массив:

int[] dynamicArray; 

Свойства массивов

Вот список свойств массивов:

Свойство и Описание
1

.init

Статический массив возвращает литерал массива, у которого каждый элемент установлен в значение литерала, являющегося свойством .init типа элемента массива.

2

.sizeof

Статический массив возвращает длину массива, умноженную на количество байтов в элементе массива, в то время как динамические массивы возвращают размер ссылки на динамический массив, который равен 8 в 32-битных сборках и 16 на 64-битных сборках.

3

.length

Статический массив возвращает количество элементов в массиве, тогда как в динамических массивах свойство используется для получения/установки количества элементов в массиве. Длина имеет тип size_t.

4

.ptr

Возвращает указатель на первый элемент массива.

5

.dup

Создаёт динамический массив такого же размера и копирует в него содержимое исходного массива.

6

.idup

Создаёт динамический массив такого же размера и копирует в него содержимое исходного массива. Тип копии является immutable (неизменяемый).

7

.reverse

Обращает на месте порядок элементов в массиве. Возвращает массив.

8

.sort

Сортирует на месте элементы в массиве. Возвращает массив.

Пример

В следующем примере разъясняются различные свойства массива:

import std.stdio;

void main() {
   int n[ 5 ]; // n - это массив из 5 целых чисел 
   
   // инициализация элементов массива n 
   for ( int i = 0; i < 5; i++ ) { 
      n[ i ] = i + 100; // Установить элемент, расположенный по индексу i, в значение i + 100  
   }
   
   writeln("Инициализированное значение:", n.init); 
   
   writeln("Длина: ", n.length); 
   writeln("Размер в байтах: ", n.sizeof); 
   writeln("Указатель:", n.ptr); 
   
   writeln("Дубликат массива: ", n.dup); 
   writeln("Неизменяемый дубликат массива: ", n.idup);
   
   n = n.reverse.dup; 
   writeln("Перевёрнутый массив: ", n);
   
   writeln("Сортированный массив: ", n.sort); 
}

Когда вы скомпилируете и выполните эту программу, она возвратит результат, похожий на это:

Инициализированное значение:[0, 0, 0, 0, 0]
Длина: 5
Размер в байтах: 20
Указатель:7FFF632BDA38
Дубликат массива: [100, 101, 102, 103, 104]
Неизменяемый дубликат массива: [100, 101, 102, 103, 104]
Перевёрнутый массив: [104, 103, 102, 101, 100]
Сортированный массив: [100, 101, 102, 103, 104]

Многомерные массивы в D

В D допустимы многомерные массивы. Вот общая форма объявления многомерного массива:

тип имя[размер1][размер2]...[размерN];

Пример

В следующем объявлении создаётся трехмерный массив целых чисел размером 5x10x4:

int threedim[5][10][4];

Двумерные массивы в D

Простейшей формой многомерного массива является двумерный массив. Двумерным массивом является, по существу, список одномерных массивов. Чтобы объявить двумерный массив с размером [x, y], вы должны описать его следующим образом:

тип имя_массива [ x ][ y ];

Где тип может быть любым допустимым типом данных языка D, а имя_массива должно быть действительным идентификатором языка D.

Двумерный массив можно рассматривать как таблицу, в которой есть x строк и y столбцов. Двумерный массив a, содержащий три строки и четыре столбца, показан ниже:

Two Dimensional Arrays

Таким образом, каждый элемент в массиве a идентифицируется как a[ i ][ j ], где a – это имя массива, а i и j – это индексы, которые однозначно идентифицируют каждый элемент в a.

Инициализация двумерных массивов

Многомерные массивы можно инициализировать с помощью задания значений в скобках для каждой строки. Следующий массив состоит из 3 строк, и в каждой строке 4 столбца.

int a[3][4] = [   
   [0, 1, 2, 3] ,   /*  инициализация строки с индексом 0 */ 
   [4, 5, 6, 7] ,   /*  инициализация строки с индексом 1 */ 
   [8, 9, 10, 11]   /*  инициализация строки с индексом 2 */ 
];

Вложенные фигурные скобки, которые указывают на предполагаемую строку, являются необязательными. Следующая инициализация эквивалентна предыдущему примеру:

int a[3][4] = [0,1,2,3,4,5,6,7,8,9,10,11];

Доступ к элементам двумерного массива

Доступ к элементу в двумерном массиве осуществляется через индексы, по индексу строки и индексу столбца массива. Например:

int val = a[2][3];

Этот оператор принимает четвёртый элемент из третьей строки массива. Вы можете проверить это в приведенной выше таблице.

import std.stdio; 
  
void main () { 
   // массив с 5-ю строками и 2-мя колонками. 
   int a[5][2] = [ [0,0], [1,2], [2,4], [3,6],[4,8]];  
   
   // Выводит значение каждого элемента массива                      
   for ( int i = 0; i < 5; i++ ) for ( int j = 0; j < 2; j++ ) {
      writeln( "a[" , i , "][" , j , "]: ", a[i][j]); 
   }
}

Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:

a[0][0]: 0 
a[0][1]: 0 
a[1][0]: 1 
a[1][1]: 2 
a[2][0]: 2 
a[2][1]: 4 
a[3][0]: 3 
a[3][1]: 6 
a[4][0]: 4 
a[4][1]: 8

Общие операции с массивами в D

Вот различные операции, выполняемые на массивах:

Срезы массивов

Мы часто используем часть массива, и выделение среза массива бывает весьма полезно. Ниже приведен простой пример выделения среза массива.

import std.stdio;
  
void main () { 
   // массив из 5 элементов. 
   double a[5] = [1000.0, 2.0, 3.4, 17.0, 50.0]; 
   double[] b;
   
   b = a[1..3]; 
   writeln(b); 
}

Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:

[2, 3.4]

Элемент массива, расположенный по индексу – верхней границе среза, в срез не включается (в отличие от нижней границы). Поэтому срез a[1..3] вернул массив из двух элементов. – прим. пер.

Копирование массива

Мы также применяем копирование массива. Ниже приведен простой пример для копирования массивов.

import std.stdio;

void main () { 
   // массив из 5 элементов. 
   double a[5] = [1000.0, 2.0, 3.4, 17.0, 50.0]; 
   double b[5]; 
   writeln("Массив a:",a); 
   writeln("Массив b:",b);  
   
   b[] = a;      // 5 элементов из a[5] копируются в b[5] 
   writeln("Массив b:",b);  
   
   b[] = a[];   // 5 элементов из a[5] копируются в b[5] 
   writeln("Массив b:",b); 
   
   b[1..2] = a[0..1]; // тоже, что b[1] = a[0] 
   writeln("Массив b:",b); 
   
   b[0..2] = a[1..3]; // тоже, что b[0] = a[1], b[1] = a[2]
   writeln("Массив b:",b); 
}

Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:

Массив a:[1000, 2, 3.4, 17, 50]
Массив b:[nan, nan, nan, nan, nan]
Массив b:[1000, 2, 3.4, 17, 50]
Массив b:[1000, 2, 3.4, 17, 50]
Массив b:[1000, 1000, 3.4, 17, 50]
Массив b:[2, 3.4, 3.4, 17, 50]

Присвоение значений массиву

Ниже приведен простой пример для присвоения значения в массиве.

import std.stdio;

void main () { 
   // массив из 5 элементов.  
   double a[5]; 
   a[] = 5; 
   writeln("Массив a:",a); 
}

Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:

Массив a:[5, 5, 5, 5, 5]

Соединение массивов (конкатенация)

Ниже приведен простой пример соединения двух массивов.

import std.stdio;

void main () { 
   // массив из 5 элементов.  
   double a[5] = 5; 
   double b[5] = 10; 
   double [] c; 
   c = a~b; 
   writeln("Массив c: ",c); 
}

Когда вы скомпилируете и выполните эту программу, она возвратит следующий результат:

Массив c: [5, 5, 5, 5, 5, 10, 10, 10, 10, 10] 

Результат этой операции лучше присваивать динамическому массиву (как в этом примере), иначе легко можно нарваться на ошибку выхода за границы массива – прим. пер.


Предыдущая страница
Следующая страница