Массивы
О нумерации элементов массива
По каждому измерению элементы нумеруются последовательно: i, i+1, i+2 и так далее. Но каково начальное значение индекса? В языке C# принято, что нумерация начинается с нуля. Так что в одномерном массиве размера n индексы изменяются в пределах от нуля (для первого элемента) до n-1 (индекс последнего элемента). В двумерном массиве элемент с индексами 3 и 5, что на языке C# пишется как mas[3, 5], обозначает элемент четвертой строки шестого столбца массива mas.
Сумма, произведение, максимальный и минимальный элементы массива
Покажем, как работать с массивами на примере классических задач вычисления суммы элементов массива и других его характеристик. В лекции, представленной на видео, построен простой проект, демонстрирующий возможное решение этих задач на примере конкретного массива. Проект доступен в этом уроке. Приведу интерфейс проекта:
Интерфейс предельно прост. Четыре кнопки для подсчета характеристик массива, Четыре окошка, где эти характеристики будут показаны. Вот как выглядит в этом проекте обработчик события Click для кнопки "Сумма":
private void buttonSum_Click(object sender, EventArgs e) { int sum = 0; for (int i = 0; i < arr.Length; i++) { sum += arr[i]; } richTextBoxSum.Text = sum.ToString(); }
Массив arr доступен обработчику события. Он определен следующим образом:
int[] arr = { 1, 2, 3, 4 };
Не буду приводить обработчики событий для других кнопок. Вместо этого приведу тексты функций, вычисляющих характеристики массива. Вот код функции Sum, вычисляющей сумму элементов массива:
/// <summary> /// Сумма элементов массива /// </summary> /// <param name="arr">массив</param> /// <returns>сумма его элементов</returns> int Sum(int[] arr) { int n = arr.Length; int sum = 0; for (int i = 0; i < n; i++) sum += arr[i]; return sum; }
Наша функция имеет один параметр – сам массив. В теле функции можно выяснить, каков размер массива, используя свойство Length, которым обладают объекты типа массив. Далее вычисление суммы следует правилам "Объявить, задать, сложить".
Давайте сравним код этой функции с кодом ранее написанной функции, вычисляющей сумму трех элементов:
/// <summary> /// Сумма трех аргументов /// </summary> /// <param name="x1">аргумент1</param> /// <param name="x2">аргумент2</param> /// <param name="x3">аргумент3</param> /// <returns>сумма x1 + x2 + x3</returns> int Sum(int x1, int x2, int x3) { // return x1 + x2 + x3; int sum = 0;//вводим переменную для суммы с начальным значением 0 sum = sum + x1; //прибавляем первое слагаемое sum = sum + x2; //прибавляем второе слагаемое sum = sum + x3; //прибавляем третье слагаемое return sum; //возвращаем результат }
Посмотрите, насколько общее решение, позволяющее вычислить сумму элементов массива независимо от того, сколько в нем элементов элегантнее частного решения вычисления суммы трех элементов. Эта элегантность и красота решения достигается за счет использования такой структуры данных как массив.
А можно ли столь же просто вычислить сумму массива большей размерности? Оказывается, да. Вот соответствующий код для двумерного массива:
/// Сумма элементов двумерного массива /// </summary> /// <param name="arr">массив</param> /// <returns>сумма его элементов</returns> int Sum_Best(int[,] arr) { int n = arr.Length; int sum = 0; foreach (int item in arr) sum += item; return sum; }
Здесь использован ранее не встречающийся оператор цикла foreach, который удобно применять при работе с массивами, поскольку он позволяет последовательно читать все элементы массива вне зависимости от размерности массива.
Следует заметить, что в отличие от цикла for в цикле foreach элементы массива можно только читать, но их нельзя изменять.
Приведу уже без дополнительных комментариев функции, вычисляющие произведение, максимальный и минимальный элементы массивов:
/// <summary> /// Произведение элементов массива /// </summary> /// <param name="arr">массив</param> /// <returns>произведение его элементов</returns> int Product(int[] arr) { int n = arr.Length; int prod = 1; for (int i = 0; i < n; i++) prod *= arr[i]; return prod; } /// <summary> /// Минимальный элемент массива /// </summary> /// <param name="arr">массив</param> /// <returns> его минимальный элемент</returns> int Min(int[] arr) { int n = arr.Length; int min = int.MaxValue; for (int i = 0; i < n; i++) if( arr[i] < min) min = arr[i]; return min; } /// <summary> /// Максимальный элемент массива /// </summary> /// <param name="arr">массив</param> /// <returns> его максимальный элемент</returns> int Max(int[] arr) { int n = arr.Length; int max = int.MinValue; for (int i = 0; i < n; i++) if (arr[i] > max) max = arr[i]; return max; }
В проекте, сопровождающем лекцию, можно увидеть пример работы с двумерным массивом.
Замечание об инициализации переменных
Переменные sum, prod, min, max, которые используются при вычислении соответствующих характеристик массива следует правильно инициализировать. В наших примерах кода используется рекомендованный способ инициализации, - сумму следует инициализировать нулем, произведение – единицей, минимум и максимум максимально возможным и минимально возможным значениями соответственно. Рекомендуемый способ не является единственно возможным.
Иногда для инициализации используется первый элемент массива. Это возможный прием, - во многих случаях такая инициализация корректно работает. Однако в ряде ситуаций она приводит к ошибкам, например, если исходный массив пуст или ищется максимальный элемент, удовлетворяющий некоторым дополнительным условиям.
При нахождении максимального элемента часто переменную max инициализируют отрицательным значением. Это корректно работает, если все элементы массива положительны, но в случаях, когда это предположение ошибочно, результат может быть не верным. Рекомендуемая нами схема инициализации корректно работает во всех ситуациях.