Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Podbelsky_V_V_C_Bazovy_kurs.pdf
Скачиваний:
69
Добавлен:
02.06.2015
Размер:
1.73 Mб
Скачать

104

Г л а в а 7

 

 

{

static void Main()

{

int number;

do Console.Write("Введите целое положительное число: ");

while (!int.TryParse(Console.ReadLine(), out number)||number<=0);

int len = (int)Math.Log10(number) + 1; char[] ciphers = new char[len];

int figure, i = len - 1; do

{

figure = number % 10; number = number / 10;

ciphers[i--] = (char)(figure + ‘0’);

}

while (number != 0); Console.Write("Цифры числа:");

foreach (char ch in ciphers) Console.Write(" " + ch);

Console.WriteLine();

}

}

Результат выполнения программы:

Введите целое положительное число :rws<ENTER> Введите целое положительное число: 975310<ENTER> Цифры числа: 9 7 5 3 1 0

В программе int number – число, вводимое пользователем. Для чтения и последующего преобразования введённой последовательности цифр в числовое значение используются уже известные нам статические методы Console.ReadLine() и int. TryParse(). Переменная int len в объявлении получает значение количества цифр во введенном числе. Она определяет длину символьного массива, адресуемого ссылкой ciphers. Переменная int figure последовательно принимает значения цифр числа. Переменная int i служит индексом при записи в массив изображений цифр. Обратите внимание на выражение (char)(figure+'0'). В скобках выполняется сложение значения цифры (переменная

Массивы

105

 

 

figure) с кодом символа '0'. Тем самым формируется числовой код символа, соответствующего значению цифры. Так как элементы массива имеют тип char, то необходимо явное приведение типа (char). После записи изображения каждой цифры в массив, индекс i уменьшается на 1.

Цикл foreach осуществляет прямой перебор массива ciphers[], и цифры на экран выводятся в правильном порядке. Результаты выполнения программы иллюстрируют сказанное.

Итак, мы убедились, что размер массива можно выбрать до его определения. Однако как только массив (объект класса массивов) определен, его размер изменить невозможно. Если размер нужно увеличить или уменьшить, приходится сначала создать новый массив нужных размеров, потом копировать в него значения элементов имеющегося массива и уничтожить этот старый массив.

7.2. Массивы как наследники класса Array

Одномерные массивы наследуют из класса Array несколько свойств и много методов, упрощающих работу с массивами.

Среди свойств следует в первую очередь назвать свойство int Length – целочисленное (32 бита) значение, определяющее общее количество элементов экземпляра массива (изменять его нельзя). Это свойство незаменимо в методах, параметрами которых служат ссылки на массивы. Второе из полезных свойств

– int Rank – размерность (число измерений) массива.

Методы класса Array позволяют решать многие типовые задачи обработки массивов. Вот некоторые из статических методов, применяемые к одномерным массивам:

static int BinarySearch() – бинарный поиск в упорядоченном массиве; результат выполнения – индекс соответствующего условию поиска элемента или отрицательное число, если элемента с искомым значением в массиве нет;

static void Сlear() – позволяет очистить (обнулить, присвоить значение пробелов или значение null) все элементы массива или указанный параметрами интервал его элементов;

static void Copy () – копирование части массива или всего массива в другой массив;

106

Г л а в а 7

 

 

static int IndexOf() – возвращает результат – наименьший индекс (минимальный номер) элемента, значение которого совпадает с образцом;

static int LastIndexOf() – возвращает последний индекс (максимальный номер) элемента, значение которого совпадает с образцом;

static void Reverse() – меняет на обратный порядок элементов в массиве;

static void Sort() – выполняет сортировку элементов массива. Необязательные параметры этого метода позволяют определить правило упорядочения. По умолчанию арифметические массивы сортируются в порядке возрастания значений

элементов. Строки упорядочиваются лексикографически. Нестатические методы (методы объектов) класса Array: object Clone() – получение точной копии того массива-объ-

екта, к которому применён метод. Возвращает ссылку на новый массив (на копию), всегда имеющую тип оbject;

void CopyTo(Array, ind) – в массив Array копируются элементы вызывающего массива, начиная с индекса ind;

int GetLength() – возвращает размер массива (число элементов) по указанному аргументом измерению (номера измерений от нуля);

int GetUpperBound() – возвращает верхнюю границу индекса массива по указанному аргументом измерению;

object GetValue() – возвращает значение указанного парамет-​ ром элемента массива;

void SetValue() – присваивает значение указанному параметром элементу.

Следующая программа иллюстрирует применение методов Clone(), Sort(), Reverse().

// 07_04.cs массивы методы класса Array using System;

class Program

{

static void Main()

{

char[] hi = { '1', 'A', '2', 'B', '3', 'C', '4', 'D', '5', 'E', };

char[] hiNew = (char[])hi.Clone();

// Копирование

Array.Sort(hiNew);

// Сортировка

Массивы

107

 

 

Console.Write("Сортировка: "); foreach (char ch in hiNew)

Console.Write(ch);

Console.WriteLine(); Array.Reverse(hiNew); // реверсирование Console.Write("Реверсирование: "); foreach (char ch in hiNew)

Console.Write(ch);

Console.WriteLine(); Console.Write("Исходный массив: "); foreach (char ch in hi)

Console.Write("" + ch); Console.WriteLine();

}

}

Результат выполнения программы:

Сортировка: 12345ABCDE

Реверсирование: EDCBA54321 Исходный массив: 1A2B3C4D5E

В программе определен и инициализирован символьный массив и адресующая его ссылка hi. Затем определена ссылка hiNew и создана копия массива с помощью метода Clone(), который применён к объекту, адресованному ссылкой hi. Так как метод Clone() возвращает ссылку на базовый класс object, то выполнено явное приведение типов (char []). Только так можно присвоить результат ссылке hiNew. Методом Array. Sort() выполнена сортировка массива, связанного со ссылкой hiNew. Элементы упорядочены по возрастанию целочисленных значений кодов символов. Далее выводится отсортированный массив и выполнена его обработка методом Reverse(). Обратите внимание, что исходный массив остаётся без изменений.

7.3. Виды массивов и массивы многомерные

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

108

Г л а в а 7

 

 

Рассмотренные нами одномерные массивы являются частным случаем всего разнообразия массивов, которые можно использовать в C#. Для этих массивов размерность равна 1, а размер одномерного массива определяется числом возможных значений индекса.

В общем случае тип массива объявляется с помощью конструкции:

тип_не_массива спецификаторы_размерностей

Здесь тип_не_массива это один из следующих типов:

тип_значения тип_класса тип_интерфейса тип_делегата

спецификатор размерности - это [] или [разделители_ размеров];

разделитель_размеров – это запятая. Количество запятых на 1 меньше соответствующей размерности массива.

Спецификаторы размерностей размещаются подряд в нужном количестве после типа_не_массива. Рассмотрим случай, когда спецификатор размерности один. Например:

type[R] – тип одномерного массива с R элементами типа type. Важными частными случаями типов массивов с одним спе -цификатором размерности кроме типов одномерных массивов, являются «прямоугольные» типы массивов, т. е. двумерные (матрицы), трехмерные («параллелепипеды») и т.д. Именно такие массивы традиционно принято называть многомерными

массивами. Примеры:

int [,] dots;

//Ссылка на двумерный массив

byte [,,] bits;

//Ссылка на трехмерный массив

Для определения объекта – конкретного экземпляра типа многомерных массивов используется выражение с операцией new

new тип_не_массива [d1,d2, d3 …] инициализатор

Здесь di – размер – количество элементов по соответствующему измерению. Инициализатор представляет собой вложение конструкций

Массивы

109

 

 

Элементами такого списка в свою очередь служат заключенные в фигурные скобки списки инициализаторов. Глубина вложения соответствует размерности массива. Размерность массива (его ранг) можно получить с помощью нестатического свойства Rank.

Пример определения с использованием инициализации матрицы (двумерного массива) с размерами 4 на 2:

int [,] matr = new int[4,2] {{1,2},{3,4},{5,6},{7,8}};

Как и для одномерных массивов, при наличии инициализатора конструкцию new int[4,2] можно опустить.

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

// 07_05.cs двумерный массив единичная матрица using System;

class Program

{

static void Main()

{

int size;

do Console.Write("size = ");

while (!int.TryParse(Console.ReadLine(), out size) || size < 1);

int[,] one = new int[size, size];

for (int i = 0; i < size; i++, Console.WriteLine()) for (int j = 0; j < size; j++)

{

if (i == j) one[i, j] = 1; Console.Write(one[i, j] + "\t");

}

foreach (int mem in one) Console.Write(mem+" ");

Console.WriteLine(); Console.WriteLine("one.Length = " + one.Length); Console.WriteLine("one.Rank = " + one.Rank);

}

{список_инициализаторов}.

}

110 Г л а в а 7

Результат выполнения программы:

size = 4<ENTER>

 

1

0

0

0

0

1

0

0

0

0

1

0

0

0

0

1

1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 one.Length = 16

one.Rank = 2

Впрограмме формируется двумерный массив (экземпляр массивов типа int[,]), размеры которого определены переменной size. Значение size вводит пользователь. По умолчанию все элементы массива получают нулевое значение. Во вложенных циклах диагональным элементам присвоены единичные значения, и выводятся значения всех элементов. Обратите внимание, как в заголовке внешнего цикла for используется обращение к методу Console.WriteLine() для перехода на новую строку при выводе. Далее иллюстрируется применение цикла foreach к многомерному массиву. Перебор значений массива, представляющего матрицу, выполняется по строкам. (Быстрее изменяется правый индекс.)

Вконце программы выведено значение свойства one.Length

это общее количество элементов в массиве и значение ранга массива (ранг равен двум).

7.4.Массивы массивов

инепрямоугольные массивы

Как следует из синтаксического определения, при объявлении типа массива можно задавать несколько спецификаторов размерностей. В стандарте приведен пример такого типа массивов (с тремя спецификаторами размерностей):

int [] [ , , ][ , ] – одномерный массив, элементы которого - трехмерные массивы, каждый с элементами типа "двумерный массив с элементами типа int". Такой массив можно рассматривать как массив массивов.

Так как размеры массивов, входящих как элементы в другой массив, могут быть разными, то массив массивов в общем

Массивы

111

 

 

случае не является “прямоугольным”. Такие непрямоугольные массивы в стандарте C# названы jagged array (зубчатые массивы). Пример из стандарта:

int[][] j2 = new int[3][]; j2[0] = new int[] { 1, 2, 3 };

j2[1] = new int[] { 1, 2, 3, 4, 5, 6 };

j2[2] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Обратите внимание, что с помощью одной операции new невозможно создать массив массивов. В примере j2 – ссылка на объект типа массив массивов с элементами типа int. Выражение new int[3][] создает объект-массив с тремя элементами типа "ссылка на одномерный массив с элементами типа int". Каждая из этих ссылок доступна с помощью соответствующего выражения j2[0], j2[1], j2[2]. Однако вначале значения этих ссылок не определены. Только присвоив каждой из них результат выражения new int[] инициализатор, мы связываем ссылки с конкретными одномерными массивами, память для которых за счёт выполнения операции new будет выделена в куче.

Приведенные четыре объявления можно заменить одним, используя правила инициализации (количество операций new при этом не изменится):

int[][] j3 = new int[3][] { new int[] { 1, 2, 3 },

new int[] { 1, 2, 3, 4, 5, 6 },

new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9} };

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

Применяя инициализатор, разрешено опускать для массива массивов выражение с операцией new, например, таким образом:

int[][] j4 = { new int[3], new int[6], new int[9] };

112

Г л а в а 7

 

 

Вэтом объявлении размер массива верхнего уровня задан списком инициализаторов. Размеры массивов нижнего уровня

сэлементами типа int здесь заданы явно, и значения элементов определяются по умолчанию как нулевые.

Вкачестве примера с непрямоугольным (зубчатым) массивом рассмотрим следующую программу, формирующую нижнюю нулевую треугольную матрицу. Элементам ее диагонали присвоим номера строк (нумерацию будем выполнять, начиная от 1). Как в примере с единичной матрицей, размер матрицы (число ее строк) будет вводить пользователь, как значение переменной int size. Текст программы:

// 07_06.cs нижняя треугольная матрица using System;

class Program

{

static void Main()

{

int size;

do Console.Write("size = ");

while (!int.TryParse(Console.ReadLine(), out size) || size < 1);

int[][] tre = new int[size][]; for (int j = 0; j < size; j++)

{

tre[j] = new int[j + 1]; tre[j][j] = j + 1;

}

for (int i = 0; i < tre.Length; i++, Console.WriteLine()) for (int j = 0; j < tre[i].Length; j++)

Console.Write(tre[i][j] + "\t"); Console.WriteLine("tre.Length = " + tre.Length); Console.WriteLine("tre.Rank = " + tre.Rank);

}

}

Результат выполнения программы:

size = 4<ENTER>

1

02

Массивы

113

 

 

0

0

3

 

0

0

0

4

tre.Length = 4

 

tre.Rank = 1

 

Впрограмме объявлена ссылка tre на массив массивов. Операцией new определен массив из size элементов – ссылок на массивы. Каждый элемент tre[j] – ссылка на еще не существующий одномерный массив с элементами типа int. Эти массивы – реальные строки треугольной матрицы – формируются в цикле. Длина j–го массива равна j+1.

Вцикле печати массива для определения числа элементов используется свойство Length. Выражение tre.Length возвращает число строк матрицы. Обратите внимание, что в отличие от многомерного массива свойство Length равно числу элементов только "верхнего" уровня массива массивов. tri[j]. Length позволяет определить длину j-й строки. Свойство Rank, относящееся к объекту типа int[][], равно 1, так как это одномерный массив ссылок на массивы. Остальное очевидно из результатов выполнения программы.

Вводя ссылку на массив и объявляя конкретный объект

экземпляр массива, программист каждый раз определяет некоторый тип именно таких массивов, которые ему нужны. Синтаксис объявления этих типов мы уже разобрали и объяснили с помощью примеров. Следует обратить внимание, что имена этих типов массивов и синтаксис определения типов массивов не похожи на те конструкции, которые применяются для определения пользовательских классов как таковых (вводимых с помощью служебного слова class). Однако, каждый декларируемый в программе тип массивов является настоящим классом и создается как производный (как наследник) системного класса Array. Будучи наследником, каждый тип массивов получает или по-своему реализует методы и свойства класса Array. Следующая программа иллюстрирует возможности некоторых методов, о которых мы ещё не говорили.

// 07_07.cs массивы – методы и свойства класса Array using System;

class Program

{

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]