Массивы. Виды массивов. Работа с массивами.




Лабораторная работа №5. 1

 

 

Массивы в C# являются объектами, производными от базового класса System.Array. Поэтому в отличие от других языков C и языка Pascal в C# происходит создание экземпляра класса, унаследованного от System.Array. Отсюда следует, что массив представляет собой ссылочный объект, память ему отводится динамически в "куче".

Массив задает способ организации данных. Массивом называют упорядоченную совокупность элементов одного типа. Каждый элемент массива имеет индексы, определяющие порядок элементов. Число индексов характеризует размерность массива. Каждый индекс изменяется в некотором диапазоне [a,b]. В языке C#, как и во многих других языках, индексы задаются целочисленным типом. Диапазон [a,b] называется граничной парой, a – нижней границей, b – верхней границей индекса.

Объявление одномерного массива выглядит следующим образом:

 

<тип>[] <объявители>;

 

Как и в случае объявления простых переменных, каждый объявитель может быть именем или именем с инициализацией. В первом случае речь идет об отложенной инициализации. Нужно понимать, что при объявлении с отложенной инициализацией сам массив не формируется, а создается только ссылка на массив, имеющая неопределенное значение. Поэтому пока массив не будет реально создан и его элементы инициализированы, использовать его в вычислениях нельзя.

Варианты описания массива:

 

тип[] имя;

тип[] имя = 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()

{

Console.WriteLine("Введите число элементов массива A1");

int size = int.Parse(Console.ReadLine());

int[] A1 = new int[size]; //объявление динамического массива A1

for (int i = 0; i < size; i++)

{

A1[i] = i + 1;

Console.Write(A1[i]);

}

}

 

Здесь размерность массива определяется пользователем.

 

Многомерные массивы.

Очевидно, что одномерные массивы – это частный случай многомерных. Одномерные массивы позволяют задавать такие математические структуры, как векторы, двумерные – матрицы, трехмерные – кубы данных, массивы большей размерности – многомерные кубы данных.

Размерность массива это характеристика типа. Синтаксически размерность массива задается за счет использования запятых. Вот как выглядит объявление многомерного массива в общем случае: <тип>[, …,] <объявители>;

Число запятых, увеличенное на единицу, и задает размерность массива. Что касается объявителей, то все, что сказано для одномерных массивов, справедливо и для многомерных. Можно лишь отметить, что хотя явная инициализация с использованием многомерных константных массивов возможна, но применяется редко из-за громоздкости такой структуры. Проще инициализацию реализовать программно, но иногда она все же применяется:

 

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}};

 


К элементу двумерного массива обращаются, указывая номера строки и столбца, на пересечении которых он расположен, например:

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);

 

Этот оператор выполняется так: на каждом проходе цикла очередной элемент массива присваивается переменной х и с ней производятся действия, записанные в теле цикла.

Случайные числа.

Для генерирования последовательного ряда случайных чисел служит класс Random.

Такие последовательности чисел оказываются полезными в самых разных ситуациях, включая имитационное моделирование. Начало последовательности случайных чисел определяется некоторым начальным числом, которое может задаваться автоматически или указываться явным образом.

В классе Random определяются два конструктора.

public Random()

public Random(int seed)

Первый конструктор создает объект типа Random, использующий системное время для определения начального числа. А во втором конструкторе используется начальное значение seed, задаваемое явным образом.

Пример генерации случайного вещественного числа в диапазоне от 0 до 1:

Random r=new Random(); //создаем переменную класса случайных чисел

double x=r.NextDouble();//генерируем случайное число

Console.WriteLine(x);//выводим на консоль

 

Методы класса Random:

 

public virtual int Next() Возвращает следующее случайное целое число, которое будет находиться в пределах от 0 до Int32 MaxValue-1 включительно;
public virtual int Next(int maxValue) Возвращает следующее случайное целое число, которое будет находиться в пределах от 0 до maxValue-1 включительно;
public virtual int Next(int minValue, int maxValue) Возвращает следующее случайное целое число, которое будет находиться в пределах от minValue до maxValue-1 включительно;
public virtual void NextBytes(byte[] buffer) Заполняет массив buffer последовательностью случайных целых чисел. Каждый байт в массиве будет находиться в пределах от 0 до Byte.MaxValue-1 включительно;
public virtual double NextDouble() Возвращает из последовательности следующее случайное число, которое представлено в форме с плавающей точкой, больше или равно 0,0 и меньше 1,0.

 

Ниже приведена программа, в которой применение класса Random демонстрируется на примере создания компьютерного варианта пары игральных костей.

 

// Компьютерный вариант пары игральных костей:

using System;

 

class RandDice

{

static void Main()

{

Console.Write("Генерирование цифр на игральных костях:\n");

Random ran = new Random(); //создаём переменную ran класса случайных чисел

Console.Write(ran.Next(1, 7) + " "); //генерируем и выводим на экран числа

Console.WriteLine(ran.Next(1, 7));

}

}


Задание:

 

1. Создайте два одномерных массива: первый массив должен быть статическим, состоящий из 10 элементов, а второй динамический. Оба массива должны заполняться через цикл for случайными числами и выводить на экран содержимое с помощью цикла foreach.

2. Создайте матрицу с динамическим размером и заполните её случайными числами, кроме главной диагонали. В главной диагонали (диагональ слева направо) должны содержаться нули. Вывести на экран.

3. Создайте двух уровневый ступенчатый массив, состоящий из пяти элементов, которые представляют из себя массивы, посчитайте сумму всех элементов, всех массивов.

 

Индивидуальные задания:

 

1. Создать одномерный массив из 15 элементов, заполненный случайными числами в диапазоне от -30 до 30. Вывести на экран. Создать два метода:

– для расчета количества чисел, кратных трем;

– расчёта суммы положительных чисел.

Вывести результат обоих методов после распечатанного массива.

2. Создать одномерный массив из 15 элементов, заполненный случайными числами в диапазоне от -30 до 30. Вывести на экран. Создать два метода:

– для нахождения минимального отрицательного числа;

– для расчёта суммы отрицательных чисел.

3. Создать матрицу с динамическим размером, распечатать её, посчитать и вывести на экран сумму её диагоналей.

4. Создать динамический одномерный массив, посчитать сумму чётных и нечётных чисел, результат вывести после распечатки массива.

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2016-04-26 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: