static void Main(){ int[] myArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int i; for (i = 0; i < 10; ++i) Console.WriteLine(myArray[i]);}
Задание. Измените программу так, чтобы числа выводились в строчку.
static void Main(){ int[] myArray = new int[10]; int i; for (i = 0; i < 10; i++) myArray[i] = i * i; for (i = 0; i < 10; i++) Console.WriteLine(myArray[i]);}
Задание. Измените программу так, чтобы обрабатывался массив из n чисел.
Хотя при инициализации массива нет необходимости использовать операцию new, все же массив можно инициализировать следующим образом:
int [ ] myArray = new int [ ] { 99, 10, 100, 18, 78, 23, 163, 9, 87, 49 };
Несмотря на избыточность, данная форма инициализации массива может оказаться полезной в том случае, когда уже существующей ссылке на одномерный массив присваивается ссылка на новый массив. Например:
static void Main(){ int[] myArray = { 0, 1, 2, 3, 4, 5}; int i; for (i = 0; i < 10; i++) Console.Write(" "+myArray[i]); Console.WriteLine("\nНовый массив: "); myArray = new int[] { 99, 10, 100, 18, 78, 23, 163, 9, 87, 49 }; // 1 for (i = 0; i < 10; i++) Console.Write(" " + myArray[i]);}
Следует отметить, что первоначально переменная myArray ссылалась на 6-ти элементный массив. В строке 1 переменной myArray была присвоена ссылка на новый 10-элементный массив, в результате чего исходный массив оказался неиспользуемым, т.к. на него теперь не ссылается ни один объект. Поэтому он автоматически будет удален сборщиком мусора.
Выход за границы массива в C# расценивается как ошибка, в ответ на которую генерируется исключение - IndexOutOfRangeException.
Рассмотрим следующий пример:
static void Main(){ int[] myArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int i; try { for (i = 0; i <= 10; i++) Console.WriteLine(myArray[i]); } catch (IndexOutOfRangeException) { Console.WriteLine("Exception: Выход за границу диапазона"); }}
Задание. Добавьте в программу обработчики исключений FormatException и OutOfMemoryException. Вспомните, что они контролируют.
8.2 Массив как параметр
Так как имя массива фактически является ссылкой, то он передается в метод по ссылке и, следовательно, все изменения элементов массива, являющегося формальным параметром, отразятся на элементах соответствующего массива, являющимся фактическим параметром.
Рассмотрим пример передачи массива как параметра:
class Program{ static void Print(int n, int[] a) //n - размерность массива, а - ссылка на массив { for (int i = 0; i < n; i++) Console.Write("{0} ", a[i]); Console.WriteLine(); } static void Change(int n, int[] a) { for (int i = 0; i < n; i++) if (a[i] > 0) a[i] = 0; // изменяются элементы массива } static void Main() { int[] myArray = { 0, -1, -2, 3, 4, 5, -6, -7, 8, -9 }; Print(10, myArray); Change(10, myArray); Print(10, myArray); }}
Задание. Измените программу так, чтобы метод Change удваивал значения положительных элементов массива.
8.3 Массив как объект
Мы уже говорили о том, что массивы в С# реализованы как объекты. Если говорить более точно, то они реализованы на основе базового класса Array, определенного в пространстве имен System. Данный класс содержит различные свойства и методы. Например, свойство Length позволяет определять количество элементов в массиве. Преобразуем предыдущий пример:
class Program{ static void Print(int[] a) // передаем только ссылку на массив { for (int i = 0; i < a.Length; i++) Console.Write("{0} ", a[i]); Console.WriteLine(); } static void Change(int[] a) { for (int i = 0; i < a.Length; i++) if (a[i] > 0) a[i] = 0; } static void Main() { int[] myArray = { 0, -1, -2, 3, 4, 5, -6, -7, 8, -9 }; Print(myArray); Change(myArray); Print(myArray); }}
Другие свойства и методы класса Array приведены в следующей таблице:
Элемент
Вид
Описание
Length
свойство
Количество элементов массива (по всем размерностям)
BinarySearch
статический метод
Двоичный поиск в отсортированном массиве
Clear
статический метод
Присваивание элементам массива значений по умолчанию
Copy
статический метод
Копирование заданного диапазона элементов одного массива в другой
CopyTo
экземплярный метод
Копирование всех элементов текущего одномерного массива в другой массив
GetValue
экземплярный метод
Получение значения элемента массива
IndexOf
статический метод
Поиск первого вхождения элемента в одномерный массив
LastIndexOf
статический метод
Поиск последнего вхождения элемента в одномерный массив
Reverse
статический метод
Изменение порядка следования элементов на обратный
SetValue
экземплярный метод
Установка значения элемента массива
Sort
статический метод
Упорядочивание элементов одномерного массива
Вызов статических методов происходит через обращение к имени класса, например, Array.Sort(myArray). В данном случае мы обращаемся к статическому методу Sort класса Array и передаем данному методу в качестве параметра объект myArray - экземпляр класса Array.
Обращение к свойству или вызов экземплярного метода производится через обращение к экземпляру класса, например, myArray.Length или myArray.GetValue(i).
Пример:
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("a[{0}]=",i); MyArray[i] = int.Parse(Console.ReadLine()); } PrintArray("исходный массив:", MyArray); Array.Sort(MyArray); PrintArray("массив отсортирован по возрастанию", MyArray); Array.Reverse(MyArray); 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++) Console.Write("{0} ", mas[i]); Console.WriteLine(); }}}
Задание. Добавьте в программу метод InputArray, предназначенный для ввода с клавиатуры элементов массива. Продемонстрируйте работу данного метода.
8.4 Многомерные массивы
Многомерные массивы имеют более одного измерения. Чаще всего используются двумерные массивы, которые представляют собой таблицы. Каждый элемент массива имеет два индекса, первый определяет номер строки, второй - номер столбца, на пересечении которых находится элемент. Нумерация строк и столбцов начинается с нуля.
Объявить двумерный массив можно одним из предложенных способов:
тип [,] имя__массива;тип [,] имя__массива = new тип [размер1, размер2];тип [,] имя__массива={{элементы 1-ой строки}, … , {элементы n-ой строки}};тип [,] имя__массива= new тип [,]{{элементы 1-ой строки}, … ,{элементы n-ой строки}};строки}};
Например:
int [,] a; int [,] a= new int [3, 4];int [,] a={{0, 1, 2}, {3, 4, 5}};int [,] a= new int [,]{{0, 1, 2}, {3, 4, 5}};
Замечания.
Как и в случае с одномерными массивами, последние два описания являются избыточными.
При работе с многомерными массивами можно использовать приемы, которые мы рассмотрели для одномерных массивов.
При обращении к свойству Length для двумерного массива мы получим общее количество элементов в массиве. Чтобы получить количество строк нужно обратиться к методу GetLength с параметром 0. Чтобы получить количество столбцов - к методу GetLength с параметром 1.
Пример:
class Program { static void PrintArray(string a, int[,] mas) { Console.WriteLine(a); for (int i = 0; i < mas.GetLength(0); i++) { for (int j = 0; j < mas.GetLength(1); j++) Console.Write("{0} ", mas[i, j]); Console.WriteLine(); } } static void Change(int[,] mas) { for (int i = 0; i < mas.GetLength(0); i++) for (int j = 0; j < mas.GetLength(1); j++) if (mas[i, j] % 2 == 0) mas[i, j] = 0; } static void Main() { try { int[,] MyArray ={ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; PrintArray("исходный массив:", MyArray); Change(MyArray); PrintArray("итоговый массив", MyArray); } catch (FormatException) { Console.WriteLine("неверный формат ввода данных"); } catch (OverflowException) { Console.WriteLine("переполнение"); } catch (OutOfMemoryException) { Console.WriteLine("недостаточно памяти для создания нового объекта"); } } }
Задания.
Добавьте в программу метод InputArray, предназначенный для ввода с клавиатуры элементов массива. Продемонстрируйте работу данного метода.
Измените метод Change так, чтобы он вычислял сумму четных элементов двумерного массива.
8.5 Ступенчатые массивы
В ступенчатых массивах количество элементов в разных строках может быть различным. В памяти ступенчатый массив хранится в виде массива массивов. Структура ступенчатого массива:
Массив
a
a[0]
a[0][0]
a[0][1]
…
a[1]
…
a[1][0]
a[1][1]
…
a[n]
a[n][0]
a[n][1]
…
Объявление ступенчатого массива:
тип [][] имя_массива;
Например:
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(); } }}
Задание. Добавьте в программу метод MakeArray, предназначенный для создания ступенчатого массива, в котором количество элементов в каждой строке больше номера строки в два раза. А сам элемент равен сумме номеров строки и столбца, в котором он находится. Продемонстрируйте работу данного метода.
8.6 Оператор foreach и его использование при работе с массивами
Оператор foreach применяется для перебора элементов в специальным образом организованной группе данных, в том числе и в массиве. Удобство этого вида цикла заключается в том, что нам не требуется определять количество элементов в группе и выполнять перебор по индексу - мы просто указываем на необходимость перебрать все элементы группы. Синтаксис оператора:
foreach (<тип> <имя> in <группа>) <тело цикла>
где имя определяет локальную по отношению к циклу переменную, которая будет по очереди принимать все значения из указанной группы, а тип соответствует базовому типу элементов группы.
Ограничением оператора foreach является то, что с его помощью можно только просматривать значения элементов в группе данных, но нельзя их изменять.
Рассмотрим несколько примеров использования оператора foreach:
для работы с одномерными массивами:
2. static void PrintArray(string a, int [] mas)3. {4. Console.WriteLine(a);5. foreach (int x in mas)Console.Write("{0} ", x);6. Console.WriteLine();7. }
для работы с двумерными массивами:
9. static int Sum (int [,] mas)10. {11. int s=0;12. foreach (int x in mas) s += x;13. return s;14. }
для работы со ступенчатыми массивами:
16. static void PrintArray3(string a, int[][] mas)17. {18. Console.WriteLine(a);19. for (int i = 0; i < mas.Length; i++)20. {21. foreach (int x in mas[i]) Console.Write("{0} ", x);22. Console.WriteLine();23. }24. }