Методы и свойства класса 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