1629295407-c61bfe4caba98380ea3e7cdae6295416 (846200), страница 32
Текст из файла (страница 32)
Массивы и строки165Обратите внимание на то, как в классе LengthDemo цикл for использует свойствоnums.Length для управления количеством итераций. Поскольку каждый массивсопровождается информацией о собственной длине, можно использовать эту информацию,а не вручную отслеживать размер массива. При этом следует иметь в виду, что свойствоLength никак не связано с реально используемым количеством элементов массива.
Оносодержит количество элементов, которое массив способен хранить.При получении длины многомерного массива возвращается общее количествоэлементов, обусловленное “врожденной” способностью массива хранить данные.Например:// Использование свойства Length для 3-х-мерного массива.using System;class LengthDemo3D {public static void Main() {int[,,] nums = new int[10, 5, 6];Console.WriteLine("Длина массива равна " +nums.Length);}}Вот результаты выполнения этой программы:Длина массива равна 300Как подтверждает результат запуска предыдущей программы, свойство Lengthсодержит количество элементов, которое может хранить массив nums и которое в данномслучае равно 300 (10 x 5 x 6).
При этом у нас нет возможности получить длину массива поконкретному измерению (координате).Использование свойства Length упрощает многие алгоритмы за счет выполненияболее простых операций над массивами. Например, следующая программа используетсвойство Length для реверсирования содержимого массива посредством его копированияв другой массив в направлении от конца к началу.// Реверсирование массива.using System;class RevCopy {public static void Main() {int i,j;int[] nums1 = new int[10];int[] nums2 = new int[10];for(i=0; i < nums1.Length; i++)nums1[i] = i;Console.Write("Исходное содержимое массива: ");for(i=0; i < nums2.Length; i++)Console.Write(nums1[i] + " ");Console.WriteLine();// Копируем массив nums1 в массив nums2 с// изменением порядка следования элементов.if(nums2.Length >= nums1.Length) // Необходимо// убедиться, что массив nums2// достаточно велик.166Часть I.
Язык C#for(i=0, j=nums1.Length-1; i < nums1.Length; i++, j--)nums2[j] = nums1[i];Console.Write("Содержимое массива в обратном порядке: ");for(i=0; i < nums2.Length; i++)Console.Write(nums2[i] + " ");}}Console.WriteLine();Вот как выглядят результаты выполнения этой программы:Исходное содержимое массива: 0 1 2 3 4 5 6 7 8 9Содержимое массива в обратном порядке: 9 8 7 6 5 4 3 2 1 0Здесь свойство Length выполняет две важных функции. Во-первых, оноподтверждает, что массив-приемник имеет размер, достаточный для хранения содержимогоисходного массива. Во-вторых, оно обеспечивает условие завершения цикла for, которыйвыполняет реверсное копирование.
Безусловно, это очень простой пример, и размермассива легко узнать и без свойства Length, но аналогичный подход можно применить кширокому диапазону более сложных ситуаций.Использование свойства Length при работе с рваными массивамиПри работе с рваными массивами использование свойства Length приобретаетособое значение, поскольку позволяет получить длину каждого отдельного (“строчного”)массива. Рассмотрим, например, следующую программу, которая имитирует работуцентрального процессора (ЦП) в сети с четырьмя узлами.// Демонстрация использования свойства Length при// работе с рваными массивами.using System;class Jagged {public static void Main() {int[][] network_nodes = new int[4][];network_nodes[0] = new int[3];network_nodes[1] = new int[7];network_nodes[2] = new int[2];network_nodes[3] = new int[5];int i, j;// Создаем фиктивные данные по// использованию ЦП.for(i=0; i < network_nodes.Length; i++)for(j=0; j < network_nodes[i].Length; j++)network_nodes[i][j] = i * j + 70;Console.WriteLine("Общее количество сетевых узлов: " +network_nodes.Length + "\n");for(i=0; i < network_nodes.Length; i++) {for(j=0; j < network_nodes[i].Length; j++) {Глава 7.
Массивы и строки167Console.Write("Использование ЦП на узле " + i +" для ЦП " + j + ": ");Console.Write(network_nodes[i][j] + "% ");Console.WriteLine();}}}}Console.WriteLine();Результаты выполнения этой программы выглядят так:Общее количество сетевых узлов: 4Использование ЦП на узле 0 для ЦП 0: 70%Использование ЦП на узле 0 для ЦП 1: 70%Использование ЦП на узле 0 для ЦП 2: 70%ИспользованиеИспользованиеИспользованиеИспользованиеИспользованиеИспользованиеИспользованиеЦПЦПЦПЦПЦПЦПЦПнананананананаузлеузлеузлеузлеузлеузлеузле1111111длядлядлядлядлядлядляЦПЦПЦПЦПЦПЦПЦП0:1:2:3:4:5:6:70%71%72%73%74%75%76%Использование ЦП на узле 2 для ЦП 0: 70%Использование ЦП на узле 2 для ЦП 1: 72%Использование ЦП на узле 3 для ЦП 0: 70%Использование ЦП на узле 3 для ЦП 1: 73%Использование ЦП на узле 3 для ЦП 2: 76%Использование ЦП на узле 3 для ЦП 3: 79%Использование ЦП на узле 3 для ЦП 4: 82%Обратите внимание на то, как свойство Length используется для рваного массиваnetwork_nodes.
Вспомните, что двумерный рваный массив — это массив массивов.Поэтому выражениеnetwork_nodes.Lengthвозвращает количество массивов, хранимых в массиве network_nodes (в данном случаеэто значение равно 4). Чтобы получить длину отдельного массива во “внешнем” рваноммассиве, используйте, например, такое выражение:network_nodes[0].LengthЭто выражение возвращает длину первого массива.Цикл foreachВ главе 5 упоминалось о том, что в языке C# определен цикл foreach, но подробноеего рассмотрение было отложено на “потом”. По заголовку этого раздела нетруднодогадаться, что время для этого наступило.Цикл foreach используется для опроса элементов коллекции.
Коллекция — этогруппа объектов. C# определяет несколько типов коллекций, и одним из них являетсямассив. Формат записи цикла foreach имеет такой вид:foreach(тип имя_переменной in коллекция) инструкция;168Часть I. Язык C#Здесь элементы тип и имя_переменной задают тип и имя итерационнойпеременной, которая при функционировании цикла fоreach будет получать значенияэлементов из коллекции. Элемент коллекция служит для указания опрашиваемойколлекции (в данном случае в качестве коллекции мы рассматриваем массив). Такимобразом, элемент тип должен совпадать (или быть совместимым) с базовым типом массива.Здесь важно запомнить, что итерационную переменную применительно к массиву можноиспользовать только для чтения.
Следовательно, невозможно изменить содержимоемассива, присвоив итерационной переменной новое значение.Рассмотрим простой пример использования цикла foreach. Приведенная нижепрограмма создает массив для хранения целых чисел и присваивает его элементамначальные значения. Затем она отображает элементы массива, попутно вычисляя их сумму.// использование цикла foreach.using System;class ForeachDemo {public static void Main() {int sum = 0;int[] nums = new int[10];// Присваиваем элементам массива nums значения.for(int i = 0; i < 10; i++)nums[i] = i;// Используем цикл foreach для отображения значений// элементов массива и их суммирования.foreach(int x in nums) {Console.WriteLine("Значение элемента равно: " + x);sum += x;}Console.WriteLine("Сумма равна: " + sum);}}При выполнении этой программы получим следующие результаты:Значение элемента равно: 0Значение элемента равно: 1Значение элемента равно: 2Значение элемента равно: 3Значение элемента равно: 4Значение элемента равно: 5Значение элемента равно: бЗначение элемента равно: 7Значение элемента равно: 8Значение элемента равно: 9Сумма равна: 45Как видно из приведенных выше результатов, цикл foreach последовательноопрашивает элементы массива в направлении от наименьшего индекса к наибольшему.Несмотря на то что цикл foreach работает до тех пор, пока не будут опрошены всеэлементы массива, существует возможность досрочного его останова с помощьюинструкции break.
Например, следующая программа суммирует только пять первыхэлементов массива nums.// Использование инструкции break в цикле foreach.using System;Глава 7. Массивы и строки169class ForeachDemo {public static void Main() {int sum = 0;int[] nums = new int[10];// Присваиваем элементам массива nums значения.for(int i = 0; i < 10; i++)nums[i] = i;// Используем цикл foreach для отображения значений// элементов массива и их суммирования.foreach(int x in nums) {Console.WriteLine("Значение элемента равно: " + x);sum += x;if(x == 4) break; // Останов цикла, когда x равен 4.}}}Console.WriteLine("Сумма первых 5 элементов: " + sum);Вот как выглядят результаты выполнения этой программы:Значение элемента равно: 0Значение элемента равно: 1Значение элемента равно: 2Значение элемента равно: 3Значение элемента равно: 4Сумма первых 5 элементов: 10Очевидно, что цикл foreach останавливается после получения пятого элементамассива.Цикл foreach работает и с многомерными массивами.
В этом случае он возвращаетэлементы в порядке следования строк: от первой до последней.// Использование цикла foreach с двумерным массивом.using System;class ForeachDemo2 {public static void Main() {int sum =0;int[,] nums = new int[3,5];// Присваиваем элементам массива nums значения.for(int i = 0; i < 3; i++)for(int j=0; j < 5; j++)nums[i,j] = (i+1)*(j+1);}}170// Используем цикл foreach для отображения значений// элементов массива и их суммирования.foreach(int x in nums) {Console.WriteLine("Значение элемента равно: " + x);sum += x;}Console.WriteLine("Сумма равна: " + sum);Часть I.