Методы и свойства класса Array

Программирование с использованием МНОГОМЕРНЫХ массивов

Цель лабораторной работы: освоить использование многомерных, динамических и ступенчатых массивов, изучить свойства компонента dataGridView.

3.1. Массивы в С#

Массив задает способ организации данных. Массивом называют упорядоченную совокупность элементов одного типа. Каждый элемент массива имеет индексы, определяющие порядок элементов. Число индексов характеризует размерность массива. В языке C#, как и во многих других языках, индексы задаются целочисленным типом. В других языках, например, в языке Паскаль, индексы могут принадлежать счетному конечному множеству, на котором определены функции, задающие следующий и предыдущий элемент.

К сожалению, не снято ограничение 0-базируемости, означающее, что нижняя граница массивов C# фиксирована и равна нулю. Т.е. индексирование элементов всегда начинается с нуля.

Объявление одномерных массивов

Объявление одномерного массива выглядит следующим образом:

<тип>[] <объявители>;

В отличие от языка C++ квадратные скобки приписаны не к имени переменной, а к типу. Они являются неотъемлемой частью определения типа, так что запись T[] следует понимать как тип, задающий одномерный массив с элементами типа T.

Как и в случае объявления простых переменных, каждый объявитель может быть именем или именем с инициализацией. В первом случае речь идет об отложенной инициализации. Нужно понимать, что при объявлении с отложенной инициализацией сам массив не формируется, а создается только ссылка на массив, имеющая неопределенное значение. Поэтому пока массив не будет реально создан и его элементы инициализированы, использовать его в вычислениях нельзя.

Варианты описания массива:

тип[] имя;

тип[] имя = new тип [ размерность ];

тип[] имя = { список_инициализаторов };

тип[] имя = new тип [] { список_инициализаторов };

тип[] имя = new тип [ размерность ] { список_инициализаторов };

Примеры описаний:

int[] a; // 1 элементов нет

int[] b = new int[4]; // 2 элементы равны 0

int[] c = { 61, 2, 5, -9 }; // 3 new подразумевается

int[] d = new int[] { 61, 2, 5, -9 }; // 4 размерность

вычисляется, избыточное описание

int[] e = new int[4] { 61, 2, 5, -9 }; // 5 избыточное описание

Динамические массивы

Во всех вышеприведенных примерах объявлялись статические массивы, поскольку нижняя граница равна нулю по определению, а верхняя всегда задавалась в этих примерах константой. Статические массивы скорее исключение, а на практике в основном используются динамические массивы.

Чисто синтаксически нет существенной разницы в объявлении статических и динамических массивов. Выражение, задающее границу изменения индексов, в динамическом случае содержит переменные. Единственное требование - значения переменных должны быть определены в момент объявления. Это ограничение в C# выполняется, поскольку C# контролирует инициализацию переменных.

Рассмотрим пример, в котором описана работа с динамическим массивом:

static void TestDynAr() {

//объявление динамического массива A1

Console.WriteLine("Введите число элементов массива A1");

int size = int.Parse(Console.ReadLine());

int[] A1 = new int[size];

Arrs.CreateOneDimAr(A1);

Arrs.PrintAr1("A1",A1);

}

Здесь верхняя граница массива определяется пользователем.

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

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

Размерность массива это характеристика типа. Синтаксически размерность массива задается за счет использования запятых. Вот как выглядит объявление многомерного массива в общем случае:

<тип>[, … ,] <объявители>;

Число запятых, увеличенное на единицу, и задает размерность массива. Что касается объявителей, то все, что сказано для одномерных массивов, справедливо и для многомерных. Можно лишь отметить, что хотя явная инициализация с использованием многомерных константных массивов возможна, но применяется редко из-за громоздкости такой структуры. Проще инициализацию реализовать программно, но иногда она все же применяется:

int[,]matrix = {

{1,2},

{3,4}

};

Чаще всего в программах используются двумерные массивы. Варианты описания двумерного массива:

тип[,] имя;

тип[,] имя = new тип [ разм_1, разм_2 ];

тип[,] имя = { список_инициализаторов };

тип[,] имя = new тип [,] { список_инициализаторов };

тип[,] имя = new тип [ разм_1, разм_2 ] { список_инициализаторов };

Примеры описаний (один пример на каждый вариант описания):

int[,] a; // 1 элементов нет

int[,] b = new int[2, 3]; // 2 элементы равны 0

int[,] c = {{1, 2, 3}, {4, 5, 6}}; // 3 new подразумевается

int[,] c = new int[,] {{1, 2, 3}, {4, 5, 6}}; // 4 размерность вычисляется, избыточно

int[,] d = new int[2,3] {{1, 2, 3}, {4, 5, 6}};// 5 избыточное описание

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

a[1, 4];

b[i, j];

b[j, i];

Ступенчатые массивы

Еще одним видом массивов C# являются массивы массивов, называемые также ступенчатыми массивами (jagged arrays). Такой массив массивов можно рассматривать как одномерный массив, его элементы являются массивами, элементы которых, в свою очередь снова могут быть массивами, и так может продолжаться до некоторого уровня вложенности. Эти массивы могут применяться для представления деревьев, у которых узлы могут иметь произвольное число потомков. Таковым может быть, например, генеалогическое дерево. Вершины первого уровня - Fathers, представляющие отцов, могут задаваться одномерным массивом, так что Fathers[i] - это i-й отец. Вершины второго уровня представляются массивом массивов - Children, так что Children[i] - это массив детей i-го отца, а Children[i][j] - это j-й ребенок i-го отца. Для представления внуков понадобится третий уровень, так что GrandChildren [i][j][k] будет представлять к-го внука j-го ребенка i-го отца.

Есть некоторые особенности в объявлении и инициализации таких массивов. Если при объявлении типа многомерных массивов для указания размерности использовались запятые, то для изрезанных массивов применяется более ясная символика - совокупности пар квадратных скобок; например, int[][] задает массив, элементы которого - одномерные массивы элементов типа int.

Сложнее с созданием самих массивов и их инициализацией. Здесь нельзя вызвать конструктор new int[3][5], поскольку он не задает изрезанный массив. Фактически нужно вызывать конструктор для каждого массива на самом нижнем уровне. В этом и состоит сложность объявления таких массивов.

//массив массивов - формальный пример

//объявление и инициализация

int[][] jagger = new int[3][] {

new int[] {5,7,9,11},

new int[] {2,8},

new int[] {6,12,4}

};

Массив jagger имеет всего два уровня. Можно считать, что у него три элемента, каждый из которых является массивом. Для каждого такого массива необходимо вызвать конструктор new, чтобы создать внутренний массив. В данном примере элементы внутренних массивов получают значение, будучи явно инициализированы константными массивами.

Оператор foreach

Оператор foreach применяется для перебора элементов в специальным образом организованной группе данных. Массив является именно такой группой. Удобство этого вида цикла заключается в том, что нам не требуется определять количество элементов в группе и выполнять их перебор по индексу: мы просто указываем на необходимость перебрать все элементы группы. Синтаксис оператора:

foreach ( тип имя in выражение ) тело_цикла

Имя задает локальную по отношению к циклу переменную, которая будет по очереди принимать все значения из массива выражение (в качестве выражения чаще всего применяется имя массива или другой группы данных). В простом или составном операторе, представляющем собой тело цикла, выполняются действия с переменной цикла. Тип переменной должен соответствовать типу элемента массива. Например, пусть задан массив:

int[] a = { 24, 50, 18, 3, 16, -7, 9, -1 };

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

foreach ( int x in a ) Console.WriteLine( x );

Этот оператор выполняется так: на каждом проходе цикла очередной элемент массива присваивается переменной х и с ней производятся действия, записанные в теле цикла.

Методы и свойства класса Array

При обработке массивов могут быть полезными методы и свойства класса Array. Некоторые элементы этого класса показаны в таблице:

Элемент Вид Описание
Length Свойство Количество элементов массива (по всем размерностям)
BinarySearch Статический метод Двоичный поиск в отсортированном массиве
Clear Статический метод Присваивание элементам массива значений по умолчанию
Copy Статический метод Копирование заданного диапазона элементов одного массива в другой массив
GetValue Метод Получение значения элемента массива
IndexOf Статический метод Поиск первого вхождения элемента в одномерный массив
Reverse Статический метод Изменение порядка следования элементов на обратный
Sort Статический метод Упорядочивание элементов одномерного массива

3.1.7. Пример кода использующего многомерные массивы:

// объявление и инициализация двухмерного массива

int[,] array2D = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };

// Объявление такого массива с указанием размерности (кол-во строки столбцов)

int[,] array2Da = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };

// Объявление двухмерного массива элементами, которого являются строки

string[,] array2Db = new string[3, 2] { { "one", "two" }, { "three", "four" },

{ "five", "six" } };

// Объявление трехмерного массива

int[, ,] array3D = new int[,,] { { { 1, 2, 3 }, { 4, 5, 6 } },

{ { 7, 8, 9 }, { 10, 11, 12 } } };

// Объявление трехмерного массива с указанием размерности

int[, ,] array3Da = new int[2, 2, 3] { { { 1, 2, 3 }, { 4, 5, 6 } },

{ { 7, 8, 9 }, { 10, 11, 12 } } };

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

System.Console.WriteLine(array2D[0, 0]);

System.Console.WriteLine(array2D[0, 1]);

System.Console.WriteLine(array2D[1, 0]);

System.Console.WriteLine(array2D[1, 1]);

System.Console.WriteLine(array2D[3, 0]);

System.Console.WriteLine(array2Db[1, 0]);

System.Console.WriteLine(array3Da[1, 0, 1]);

System.Console.WriteLine(array3D[1, 1, 2]);

// Результаты работы программы (выводятся в консоль):

// 1

// 2

// 3

// 4

// 7

// three

// 8

// 12

Наши рекомендации