Массивы
Ступенчатые массивы
В ступенчатых массивах количество элементов в разных строках может быть различным. В памяти ступенчатый массив хранится в виде массива массивов. Структура ступенчатого массива:
Объявление ступенчатого массива:
тип [][] имя_массива;
Например:
int [][]a;
Фактически мы объявили одномерный массив ссылок на целочисленные одномерные массивы. При таком описании потребуется не только выделять память под одномерный массив ссылок, но и под каждый из целочисленных одномерных массивов. Такое распределение памяти позволяет определять произвольную длину каждой строки массива (отсюда и произошло название массива - ступенчатый). Например:
int [][] a= new int [3][]; // Создаем три строки a[0]=new int [2]; // 0-ая строка ссылается на 2-х элементый одномерный массив a[1]=new int [3]; // 1-ая строка ссылается на 3-х элементый одномерный массив a[2]=new int [10]; // 2-ая строка ссылается на 10-ти элементый одномерный массив
Другой способ выделения памяти:
int [][] a= {new int [2], new int [3], new int [10]};
Так как каждая строка ступенчатого массива фактически является одномерным массивом, то с каждой строкой можно работать как с экземпляром класса Array. Это является преимуществом ступенчатых массивов перед двумерными массивами.
Пример:
class Program { static void Main() { try { int[][] MyArray; Console.Write("Ввведите количество строк: "); int n = int.Parse(Console.ReadLine()); MyArray = new int[n][]; for (int i = 0; i < MyArray.Length; i++) { Console.Write("введите количество элементов в {0} строке: ", i); int j = int.Parse(Console.ReadLine()); MyArray[i] = new int[j]; for (j = 0; j < MyArray[i].Length; j++) { Console.Write("a[{0}][{1}]= ", i, j); MyArray[i][j] = int.Parse(Console.ReadLine()); } } PrintArray("исходный массив:", MyArray); for (int i = 0; i < MyArray.Length; i++) Array.Sort(MyArray[i]); PrintArray("измененный массив", MyArray); } catch (FormatException) { Console.WriteLine("неверный формат ввода данных"); } catch (OverflowException) { Console.WriteLine("переполнение"); } catch (OutOfMemoryException) { Console.WriteLine("недостаточно памяти для создания нового объекта"); } } static void PrintArray(string a, int[][] mas) { Console.WriteLine(a); for (int i = 0; i < mas.Length; i++) { for (int j = 0; j < mas[i].Length; j++) Console.Write("{0} ", mas[i][j]); Console.WriteLine(); } } }
Оператор foreach и его использование при работе с массивами
Оператор foreach применяется для перебора элементов в специальным образом организованной группе данных, в том числе и в массиве. Удобство этого вида цикла заключается в том, что нам не требуется определять количество элементов в группе и выполнять перебор по индексу - мы просто указываем на необходимость перебрать все элементы группы. Синтаксис оператора:
foreach (<тип> <имя> in <группа>) <тело цикла>
где имя определяет локальную по отношению к циклу переменную, которая будет по очереди принимать все значения из указанной группы, а тип соответствует базовому типу элементов группы.
Ограничением оператора foreach является то, что с его помощью можно только просматривать значения элементов в группе данных, но нельзя их изменять.
Рассмотрим несколько примеров использования оператора foreach:
- для работы с одномерными массивами:
static void PrintArray(string a, int [] mas) { Console.WriteLine(a); foreach (int x in mas)Console.Write("{0} ", x); Console.WriteLine(); }
- для работы с двумерными массивами:
static int Sum (int [,] mas) { int s=0; foreach (int x in mas) s += x; return s; }
- для работы со ступенчатыми массивами:
static void PrintArray3(string a, int[][] mas) { Console.WriteLine(a); for (int i = 0; i < mas.Length; i++) { foreach (int x in mas[i]) Console.Write("{0} ", x); Console.WriteLine(); } }