МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Практическая работа по теме 3. Модульное программирование Создание и инициализация массивов. Изменение размеров массива. Поиск в массиве. Тип коллекции – набор объектов (set). Использование динамического класса ArrayList. Использование хэш таблицы – коллекции Hashtable. Использование коллекции SortedList. Использование очереди. Использование стека. Методы: процедуры и функции. Обработка даты и времени. Практическая работа по теме 3. Модульное программирование .............................................1 Задание 1. Создание и инициализация массивов ...................................................................1 Задание 2. Изменение размеров массива.................................................................................6 Задание 3. Поиск в массиве ......................................................................................................8 Задание 4. Тип коллекции – набор объектов (set) ................................................................11 Задание 5. Использование динамического класса ArrayList ...............................................13 Задание 6. Использование хэш-таблицы – коллекции Hashtable ........................................17 Задание 7. Использование коллекции SortedList ..................................................................20 Задание 8. Использование очереди (набора, работающего по принципу FIFO) ...............23 Задание 9. Использование стека (набора, работающего по принципу LIFO)....................24 Задание 10. Методы: процедуры и функции.........................................................................26 Задание 11. Обработка даты и времени .................................................................................32 Задание 1. Создание и инициализация массивов Задача Создать обычный типизированный массив (класс System.Array), выполнить его инициализацию (заполнение начальными значениями) как при объявлении массива, так и в ходе выполнения программы, просмотреть массив поэлементно. Решение Рассмотреть все возможные способы описания и инициализации обычных типизированных массивов, создаваемых в .NET как экземпляры класса System.Array. Использовать операторы цикла для организации работы с элементами массивов. Обсуждение До этого момента мы рассматривали простые типы данных. Теперь выясним, как можно хранить связанную, структурную информацию. В платформе .NET для структурированных данных применяется понятие «коллекция». Термин «коллекция» (collection) относится к особому типу объектов, которые способны хранить внутри себя другие объекты и позволяет работать с ними или по отдельности, или как с группой. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Простейший тип коллекции – набор объектов, сгруппированный без какого-либо определенного порядка, его часто называют набором (set). Коллекция, в которой объекты хранятся в определенной последовательности, называется списком (list). Среди различных типов коллекций, кроме списков и наборов, также различают: хэш-таблицы, стэки, очереди, сортированные списки. У них различная функциональность и каждый тип предназначен для решения определенных задач. В .NET коллекции описаны в пространстве имен System.Collection. Начнем рассмотрение принципов работы с коллекциями с одной из форм коллекции – массивами данных. Массивы представляют собой простейшую форму структурированных данных, они являются коллекцией, хотя описаны в другом пространстве имен – System.Array. Массивы применяются для хранения множества элементов данных, доступ к которым осуществляется по общему имени и индексу, добавляемому автоматически к каждой переменной массива. Разберемся с тем, как эти индексы формируются. В VB .NET индексация массивов начинается с нуля (это можно изменять, но не рекомендуется). Таким образом, при описании одномерного массива в скобках указывается верхняя граница индекса (нижняя, по умолчанию, всегда равна нулю). При описании многомерного массива в скобках через запятую указываются верхние границы индекса по каждому измерению. Рассмотрим примеры описания массивов: Dim B(19) As Integer – одномерный массив B из 20 целых чисел; Dim SA(6) As String – одномерный массив SA на 7 строк; Private SB(4, 1) As Integer – создание двумерного массива SB (5x2) целых чисел; Public RA(1, 1, 1) As Double – трехмерный (2x2x2) массив RA вещественных чисел. Задание начальных значений элементов массива можно выполнять как с помощью обычных операторов присваивания в коде программы, так и непосредственно при описании массива. Например, был объявлен одномерный массив на две строки: Dim SA(1) As String Далее, в ходе программы выполняется инициализация элементов массива SA: SA(0)="Пн" SA(1)="Вт" Не требуется помещать данные в каждый элемент массива, нет даже необходимости сохранять элементы последовательно. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Dim strHouse(4) As String strHouse(1)=”Jones” strHouse(4)=”Goldstein” strHouse(3)=”Soprano” В случае двумерного или любого n-мерного массивов необходимо четко соблюдать систему индексации элементов массива: SB(0,0)=1: SB(0,1)=2 SB(1,0)=3: SB(1,1)=4 RA(0,0,0)=0.1: RA(0,0,1)=0.1 RA(0,1,0)=0.3: RA(0,1,1)=0.4 Инициировать (задавать начальные значения) массив можно непосредственно при его описании. В этом случае есть дополнительные синтаксические особенности для строк и n-мерных массивов. Рассмотрим эти особенности в примерах: Dim SA() As String = {"Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"} – обратите внимание на фигурные скобки и кавычки; Private SB(,) As Integer = {{1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10}} – обратите внимание на пары фигурных скобок; public RA( , , ) as Double={{{0.1,0.2},{0.3,0.4}},{{0.5,0.6},{0.7,0.8}}} При инициализации массива непосредственно в операторе описания начальные значения каждого элемента указываются в фигурных скобках и разделяются запятыми. Обратите внимание, что в случае, когда инициализация массива производится непосредственно в операторе описания, верхние границы индексов не указываются, так как компилятор VB .NET определяет их по реальному количеству элементов, указанных в правой части соответствующего оператора. После описания массива с его элементами можно работать как с обычными переменными соответствующего типа, в частности, они могут быть частью выражений левой и правой части оператора присваивания. Значения индекса указывается в скобках через запятую. Обычные массивы являются типизированными, так как хранят данные, относящиеся к одному типу. Это обстоятельство позволяет не делать дополнительных проверок при обработке отдельных элементов массива. Массивы особенно полезны, если нужно обрабатывать целый набор элементов, как если бы это был один элемент. Например, изменить нормы оплаты трем сотрудникам можно следующим образом: Dim EmployeePay(2) as Integer Dim ExtraPay As Integer=1000 МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE EmployeePay(0)= EmployeePay(0)+ ExtraPay EmployeePay(1)= EmployeePay(1)+ ExtraPay EmployeePay(2)= EmployeePay(2)+ ExtraPay Но, используя структуру массива, можно сделать то же самое гораздо короче: Sub Main() Dim EmployeePay() As Integer = {20000, 15000, 25000} Dim ExtraPay As Integer = 1000 Dim i As Integer For i = 0 To 2 Console.Write(EmployeePay(i).ToString & ControlChars.Tab) EmployeePay(i) = EmployeePay(i) + ExtraPay Console.WriteLine(EmployeePay(i).ToString) Next Console.ReadLine() End Sub Управляющая структура For..Next позволяет сделать запись обработки элементов массива значительно короче. Кроме For..Next для перебора элементов массива могут быть использованы любые другие конструкции циклов, например, For Each..Next. Sub Main() Dim EmployeePay() As Integer = {20000, 15000, 25000} Dim ExtraPay As Integer = 1000 Dim i As Integer For Each i In EmployeePay Console.Write(i.ToString & ControlChars.Tab) i = i + ExtraPay Console.WriteLine(i.ToString) Next Console.ReadLine() End Sub Массивы реализованы в .NET в классе System.Array, то есть, создавая массив для хранения переменных любого типа, мы создаем объект класса System.Array. Класс имеет набор свойств и методов, которые можно вызывать с именем объекта. Например, AA.GetUpperBound(0) возвращает значение верхней границы одномерного массива AA (индекс 0 показывает размерность массива) МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE или AA.Clear очищает весь массив от значений. Использование методов и свойств класса System.Array рассмотрено в примерах ниже. Самостоятельно Создайте приложение, в котором используются n-мерные массивы; организован ввод элементов в описанные структуры и вывод их на экран. Ниже представлены примеры использования операторов цикла для организации перебора всех элементов массива: Sub Main() Dim List() As String = {"Это", "просто", "тест"} Dim str As String For Each str In List Console.WriteLine(str) Next Console.ReadLine() End Sub А эта программа отобразит в консоли число “2”: Sub Main() Dim AA(,) As Integer = {{3, 2, 6}, {9, 4, 6}} Console.WriteLine(AA(0, 1).ToString) Console.ReadLine() End Sub Аналогично, следующая консоль покажет число “7”: Sub Main() Dim AA(,,) As Integer = {{{3, 5}, {2, 7}}, {{0, 1}, {9, 8}}} Console.WriteLine(AA(0, 1, 1).ToString) Console.ReadLine() End Sub Перебор элементов одномерного массива удобно выполнять в счетном цикле: Sub Main() Dim AA() As Integer = {1, 2, 3} Dim k As Integer For k = 0 To AA.GetUpperBound(0) Console.WriteLine(AA(k).ToString) Next МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Console.ReadLine() End Sub В случае двумерного массива (2x3) вывод можно организовать следующим образом: Dim AA(,) As Integer = {{1, 2, 3}, {1, 2, 3}} Dim j, k As Integer For j = 0 To AA.GetUpperBound(1)-1 For k = 0 To AA.GetLength(1) - 1 Console.Write(AA(j, k).ToString & ControlChars.Tab) Next Console.WriteLine() Next Console.ReadLine() End Sub Фактически, VB .NET не ограничивает массивы одной или двумя размерностями; можно объявить массив с максимум 60 размерностями, если потребуется. Однако использовать массив более чем с тремя размерностями не имеет смысла, лучше поискать другое решение (например, базы данных). Задание 2. Изменение размеров массива Задача Изменять значение размера массива сохранением данных или без сохранения. в ходе программы с Решение Использовать команду Visual Basic .NET. ReDim с ключевым словом Preserve при необходимости сохранения данных в массиве или ReDim без ключа Preserve при новой инициализации массива. Обсуждение Массивы, которые могут изменять свои границы во время работы программы, называют динамическими. В VB .NET существует возможность переопределения верхней границы у ранее определенного массива (для многомерного массива можно переопределять только границу по самому последнему измерению). Для этого существует оператор ReDim. Например, если массивы первоначально описаны как Dim B(19) As Integer Dim SA(6) As String Private SB(4, 1) As Integer МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Public RA(1, 1, 1) As Double, то в дальнейшем можно переопределить границы этих массивов следующим образом: Redim B(20) ReDim SA(1) После переопределения массив B будет состоять из 21 элемента типа Integer, массив SA будет состоять из двух элементов типа String (индекс первого элемента равен нулю, второго – единице). При переопределении массива можно использовать ключевое слово Preserve – в этом случае будут сохранены значения элементов, существовавших до переопределения. Таким образом, достаточно будет задать только значения новых элементов, если размер массива увеличился. ReDim Preserve SB(4,3) ReDim Preserve RA(1,1,2) После переопределения двумерный массив SB будет состоять из двадцати элементов (пять умножить на четыре) типа Integer, трехмерный массив RA будет состоять из двенадцати элементов (2*2*3) типа Double. Если размерность одномерного массива заранее неизвестна, можно при первоначальном определении не указывать ее вообще, а указать в дальнейшем в операторе ReDim. Например, это можно сделать так: Dim SA() As String, N As Integer N=1 ReDim SA(N) SA(0)=”Пн” SA(1)=”Вт” Еще одной особенностью коллекций и массивов является то, что их можно использовать как источник данных для элементов управления форм. Например, если в Windows форме поместить элемент управления ComboBox (или Listbox), то можно отобразить массив значений в этом элементе управления: Private Sub Form12_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim AA() As Integer = {1, 2, 3, 4, 5, 6, 7, 8, 9} ComboBox1.DataSource = AA Label1.Text = ComboBox1.SelectedItem End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged Label1.Text = ComboBox1.SelectedItem End Sub Самостоятельно 1. Определите пустой числовой одномерный массив. Выполните отображение массива на элемент управления ListBox (можно ComboBox) в Windows приложении. 2. Организуйте ввод информации в массив в диалоговом режиме. 3. В коде программы изменяйте размер массива с сохранением всех внесенных данных. Объявленный массив будет обрабатываться несколькими процедурами (обработчиками событий), следовательно, массив должен быть описан с областью видимости уровня формы: Dim AA() As Integer Private Sub Form12_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Ваш код загрузки формы End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Ваш код щелчка по командной кнопке End Sub Задание 3. Поиск в массиве Задача Найти элемент массива с нужным содержанием. Решение Использовать методы и свойства класса System.Array. Обсуждение Допустим, требуется выяснить, в каком из элементов массива содержится некоторое значение. Класс System.Array предоставляет МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE совместно используемый метод (shared-метод) IndexOf, который возвращает позицию первого найденного включения в заданном массиве. Например, чтобы узнать, в каком из элементов массива содержится строка «Самолет», можно использовать выражение: Array.IndexOf(A, “Самолет”), где A – имя массива. Метод IndexOf возвращает целое число – индекс найденного элемента в массиве или -1 в случае его отсутствия. Можно расширить это выражение, добавив целочисленный параметр, задающий индекс, от которого начинается поиск, например: Array.IndexOf(MyArray, “Самолет”,3) – поиск начинается с индекса 3. Можно «пройтись» по всем элементам массива и найти весь перечень включений. Sub Main() Dim A() As String = {"Самолет", "вертолет", "Самолет", "пилот"} Dim i, Index As Integer For i = 0 To 3 Index = Array.IndexOf(A, "Самолет", i) Console.WriteLine("Строка 'Самолет' встречается в :" & Index.ToString) Next Console.ReadLine() End Sub Самостоятельно 1. Создайте строковый массив. Отобразите его содержание в элементе управления ListBox (можно и в ComboBox). 2. При наступлении любого события, например, по щелчку командной кнопки, скопируйте из исходного элемента управления (ListBox) в другой элемент управления (можно тоже ListBox) все слова, начинающиеся на букву «т». 3. Удалите эти слова как в первом ListBox, так и в массиве. Пример решения части задачи (поиск слов, перенос слов в другой список, удаление слов из первого списка) приведен ниже. При циклическом просмотре массива вы не можете удалять элементы. Решение, приведенное ниже заключается в том, что происходит поиск МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE элемента и добавление его в другой массив, затем все найденные элементы удаляются из первоначального ListBox методом Remove. Опишем исходный массив: Dim Words() As String = {"Это", "текст", "пробы", "поиска", "буквы", "т"} Создадим пустой динамический массив для переноса в него найденных слов: Dim NewWords() As String Напишем обработчик события загрузки формы: Private Sub Form10_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load ListBox1.Items.AddRange(Words) End Sub В качестве обработчика щелчка по кнопке «Найти и копировать» напишем процедуру поиска слов и записи их в Listbox2: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim str As String Dim i As Integer For Each str In Words If str.Substring(0, 1).ToUpper = "Т" Then ReDim Preserve NewWords(i) NewWords(i) = str i += 1 End If Next ListBox2.Items.AddRange(NewWords) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE По щелчку на кнопке «Удалить» необходимо удалить найденные слова в ListBox1: Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim str As String For Each str In NewWords ListBox1.Items.Remove(str) Next End Sub Алгоритм удаления слов из исходного массива попробуйте придумать самостоятельно. В качестве варианта можно предложить: переносить в новый массив не слова на букву “т”, а наоборот, слова не на букву “т”. Тогда вы получите требуемую строку в новом массиве. При любом алгоритме действий, становится, очевидно, что работать с массивом удобно, отображая его на элементы управления, позволяющие динамически вставлять и удалять элементы и автоматически изменяющие свои размеры. В самом массиве эти действия выполнять сложнее. Задание 4. Тип коллекции – набор объектов (set) Задача Рассмотреть реализацию простейшего типа коллекций – набора объектов в .NET. Решение Используйте коллекцию – класс System.Enum. Обсуждение Простейшим типом коллекций является набор объектов, сгруппированных без какого-либо определенного порядка; его часто называют набором (set). Набор, который состоит из {объект1, объект2, объект3}, эквивалентен по своим функциям набору, состоящему из {объект1, объект2, объект3}; порядок здесь не имеет значение. В .NET наборы или перечисления реализованы в классе System.Enum. В каких случаях удобно использовать перечислений? Часто переменной приходится присваивать одно из нескольких связанных предопределенных значений (констант). В таких случаях можно создать перечисляемый тип данных, позволяющий группировать значения. Перечисления связывают набор МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE целочисленных констант с одним именем, которое можно использоваться в коде. Например, в следующем коде создается тип Enum переменной ВременаГода, которая используется для определения четырех связанных между собой констант: лето, осень, весна, зима со значениями 0, 1, 2, 3 соответственно: Imports System.Enum Module Module1 При описании перечисления необходимо использовать следующий синтаксис: Enum ВременаГода лето осень весна зима End Enum При использовании перечисления необходимо объявить экземпляр перечисления: Sub Main() Dim x As ВременаГода= ВременаГода. весна Console.WriteLine(x) Console.WriteLine(x.ToString) Console.ReadLine() End Sub End Module Использование перечислений упрощают процесс создания кода программы, повышают уровень его читаемости. В .NET предусмотрено множество различных внутренних констант и перечислений, разработанных для удобства программирования, например, уже известное вам перечисление ControlChars, включающее специальные символы, используемые для выравнивания текста, переноса строки и так далее. Самостоятельно Убедитесь в том что, имея набор констант, организованных как перечисление, использовать их в коде программы очень удобно. Создайте приложение, в котором будут использованы стандартные перечисления и перечисления, созданные вами, как в примере ниже. Imports System.Enum Enum inst МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Международный_банковский_институт Политехнический_Университет Технологический_Институт End Enum Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim r As inst Dim Stud() As String = {"Сидоров", "Волнушкин", "Сыроежкин"} MsgBox(Stud(0) & ControlChars.Tab & r.Международный_банковский_институт.ToString) MsgBox(Stud(1) & ControlChars.Tab & r.Политехнический_Университет.ToString) MsgBox(Stud(2) & ControlChars.Tab & r. Технологический_Институт.ToString) End Sub Задание 5. Использование динамического класса ArrayList Задача Вам нужен одномерный массив, позволяющий динамически вставлять и удалять элементы и автоматически изменяющий свои размеры. Решение Используйте коллекции – класс System.Collections.ArrayList. Обсуждение Обычные массивы в .NET основаны на классе Array. Как в этом убедиться? Создайте любой массив и попробуйте вызвать методы и свойства созданного вами объекта. Вы убедитесь в том, что функциональность присутствует. Например, ваш объект поддерживает свойства, содержащие длину массива, его границы, есть методы сортировки, реверса, очистки и многое другое. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Sub Main() Dim AA() As Integer = {3, 23, 56, 1, 34, 76, 2} Console.WriteLine(AA.GetLength(0)) AA.Sort(AA) Dim i As Byte For i = 0 To AA.GetUpperBound(0) Console.WriteLine(AA(i)) Next AA.Reverse(AA) For i = 0 To AA.GetUpperBound(0) Console.WriteLine(AA(i)) Next Console.ReadLine() End Sub Но класс Array нельзя назвать динамическим, так как он не позволяет добавлять и удалять элементы так же, как это, например, реализовано в элементах управления ListBox или ComboBox. Рассмотрим другой класс – ArrayList, являющийся динамическим классом. Класс ArrayList довольно прост. Для добавления элементов в него служит метод Add, а для удаления – Remove, RemoveRange и RemoveAt. Два последних метода удаляют элементы на основе номеров из индексов, тогда как Remove ищет и удаляет указанный элемент. Вместо метода GetLength, реализованного в классе System.Array, класс ArrayList включает эквивалентное свойство Count. Sub Main() Dim List As New ArrayList List.Add("blue") List.Add("green") List.Add("yellow") List.Add("red") Dim Item As String For Each Item In List Console.WriteLine(Item) Next МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Console.ReadLine() End Sub Удаление элемента “blue” по номеру индекса выполняется методом RemoveAt: List.RemoveAt(0) For Each Item In List Console.WriteLine(Item) Next Console.ReadLine() End Sub Удаление элемента “green” с использованием поиска выполняется методом Remove: List.Remove("red") For Each Item In List Console.WriteLine(Item) Next Console.ReadLine() Console.WriteLine("Количество строк в масиве List: " & List.Count.ToString) Система определения емкости класса ArrayList заключается в следующем: при создании объекта ArrayList для него выделяется внутренний буфер на 16 элементов. Если требуется хранить большее число элементов, размер буфера удваивается до 32, 64 и так далее. Если вам заранее известно, сколько элементов будет содержать объект ArrayList, вы можете зарезервировать требуемое пространство сразу, указав его в конструкторе класса ArrayList. Это несколько повысит быстродействие вашей программы. Резервирование места для 50 элементов: Dim List As New ArrayList(50) Класс ArrayList слабо типизирован, то есть, все свои элементы он хранит как базовые типы Object. Поэтому при извлечении элемента его нужно привести к соответствующему типу: Dim str As String = CType(List(0), String) Такое поведение может вызывать проблемы, потому что нет способа гарантировать, что в массив не добавлен объект неверного типа. Для быстрого добавления ряда элементов в объект ArrayList может служить метод AddRange: МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Sub Main() Dim List As New ArrayList Dim Colors() As String = {"green", "blue", "red", "yellow"} List.AddRange(Colors) Dim Item As String For Each Item In List Console.WriteLine(Item) Next Console.ReadLine() End Sub Преобразование ArrayList в обычный типизированный массив можно выполнить методом ToArray. Это преобразование полезно выполнять, так как использовать объект класса ArrayList удобно для быстрой работы с массивом значений, но для контроля типов хранимых значений, затем можно выполнить обратное преобразование в обычный массив. Рассмотрим код функции, которая ищет в предложении определенные слова и добавляет их в ArrayList. По завершении этой операции ArrayList преобразуется в массив строк. Метод ToArray возвращает объект Array, который нужно преобразовать в строго типизированный массив при помощи функции CType. Private Function FindAnimalWords(ByVal sentence As String) As String() ‘Заполнение набора Dim Words As New ArrayList Dim Word As String For Each Word In sentence.Split() Select Case Word Case "собака", "кошка", "мышка", "слон" Words.Add(Word) End Select Next ‘Преобразование ArrayList в массив и приведение общего массива ‘строго типизированному массиву с помощью функции CType() Return CType(Words.ToArray(GetType(String)), String()) End Function Самостоятельно 1. Выполните тестирование разработанной функции. 2. Отсортируйте элементы полученного массива или объекта класса ArrayList, используйте методы Array.Sort и ArrayList.Sort. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE 3. Докажите, что сортировка зависит от региональных стандартов и упорядочивает элементы в алфавитном порядке (при этом буквы нижнего регистра располагаются раньше аналогичных букв верхнего регистра). Классы Array и ArrayList имеют перегруженную версию метода Sort, которая принимает индексы, определяющие сортируемое подмножество, и собственный объект ICompare, способный выполнять специализированную сортировку, например, List.Sort(3,5,Nothing) – сортировка пяти элементов, начиная с индекса 3 (или 4-го элемента). 4. Примените перегруженный метод Sort для выполнения сортировки только указанного подмножества вашего множества данных. Задание 6. Использование хэш-таблицы – коллекции Hashtable Задача Вам нужен словарный (основанный на применении ключей) набор, или вы хотите заменить стандартный массив System.Array на более эффективный альтернативный вариант. Решение Используйте класс System.Collections.Hashtable. Обсуждение Класс Hashtable – это словарный набор, каждый элемент которого индексируется по уникальному значению. Набор Hashtable идеален, когда нужно быстро извлечь отдельные элементы, потому что он позволяет искать элементы по соответствующим значениям ключа, а не путем перебора всех элементов. Однако в отличие от массивов Array или класса ArrayList он не поддерживает доступ к элементам по номерам их индексов. При работе с хэш-таблицей вы должны решить, какие данные использовать для индексации элементов. Эта информация должна быть уникальной. Она может быть основана на параметрах самого объекта, или ее можно генерировать по требованию в форме GUID (Globally Unique Identifier – глобальный уникальный идентификатор, целое число, включающее 128 двоичных разрядов; в .NET входит структура GIUD, имеющая метод GUID.NewGuid) или порядкового номера. Например, мы можем предполагаем использовать в качестве индексов коды стран (US, UK) и хотим получять название соответствующих стран, чтобы выводить их на экран. Ниже приводится пример объекта Hashtable, в котором хранятся коды и полные названия стран. Строка используется и как ключ (код страны) для элемента, и как значение элемента (название страны). МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE UK United Kingdom US United States DE Germany Рассмотрим все особенности применения хэш-таблиц: 1. Элементы ключ/значение. Каждый элемент в Hashtable содержит больше информации, чем элемент в Array или ArrayList, то есть он «интеллектуальнее». Объект Hashtable меньше связан с хранением данных в списке и больше – с поиском и извлечением информации. 2. Вставка элементов. При использовании Hashtable можно добавлять любое необходимое число пар ключ/значение. При использовании простых массивов необходимо заранее указывать их размер, а потом этот размер трудно изменять. В случае использования объекта Hashtable (как и ArrayList) подобных ограничений не существует. 3. Удаление элементов. Удаление элементов из объектов Hashtable происходит с той же легкость, что и их добавление. Подобно ArrayList, Hashtable сам размещает в памяти пары ключ/значение. 4. Быстрый поиск информации. Коллекция Hashtable обеспечивает быстрый поиск информации, но в сравнении с ArrayList процесс поиска выполняется медленнее. Рассмотрим использование объекта Hashtable на конкретном примере. Создадим объект класса Hashtable точно так же, как это делается в случае ArrayList или любого другого класса .NET: Sub Main() Dim myHashTable As New Hashtable Затем добавляем пары ключ/значение. Напомним, что ключ – это то же самое, что индекс позиции,.a значение – хранимые данные. Каждый элемент запоминается с помощью метода Add(). myHashTable.Add("UK", "United Kingdom") myHashTable.Add("US", "United States") myHashTable.Add("DE", "Germany") Dim CountryName As String Этот оператор вернет значение Germany. Ключи чувствительны к регистру, поэтому, написав следующее myHashTable("de") мы получим нулевой результат. CountryName = myHashTable("DE") Console.WriteLine(CountryName) Console.ReadLine() End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Предложенный синтаксис добавления элементов в хэш-таблицу прекрасно работает, но чаще используется более аккуратный и упрощенный способ записи. Sub Main() Dim myHashTable As New Hashtable myHashTable("UK") = "United Kingdom" myHashTable("US") = "United States" myHashTable("DE") = "Germany" Dim CountryName As String CountryName = myHashTable("DE") Console.WriteLine(CountryName) Console.ReadLine() End Sub Рассмотрим, каким образом производится перечисление элементов хэш-таблицы. При перечислении общего набора используется тип содержащихся в нем элементов. Класс Hashtable не поддерживает эту договоренность. Вместо этого вы должны просмотреть набор объектов DictionaryEntry. Каждому элементу набора соответствует один объект DictionaryEntry. Получить ключ элемента позволяет свойство DictionaryEntry.Key, а извлечь элемент набора – DictionaryEntry.Value. Sub Main() Dim myHashTable As New Hashtable myHashTable("UK") = "United Kingdom" myHashTable("US") = "United States" myHashTable("DE") = "Germany" Dim Item As DictionaryEntry For Each Item In myHashTable Console.WriteLine("Key: " & Item.Key.ToString) Console.WriteLine("Object: " & Item.Value.ToString) Console.WriteLine() Next Console.ReadLine() End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Самостоятельно 1. «Побродите» по созданному объекту Hashtable, просматривая каждый из его элементов и используя содержащиеся в них ключ и значение. 2. Как и ArrayList, класс Hashtable хранит элементы как типы Object, поэтому, после извлечения элементов их нужно приводить к нужному типу. Выполните это самостоятельно. 3. К числу других полезных методов и свойствам класса Hashtable относятся: Метод Remove удаляет элемент из набора. Этот метод принимает ключ элемента, который нужно удалить. Методы Contains и ContainsKey возвращают True или False в зависимости от того, имеется ли в хэш-таблице указанный ключ, а метод ConstainsValue – тоже, если есть указанный объект. Свойство Keys возвращает набор всех ключей хэш-таблицы, а свойство Values – набор всех объектов. Используйте все эти свойства и методы самостоятельно. Задание 7. Использование коллекции SortedList Задача Вам нужен набор, автоматически добавлении или удалении. сортируемый при каждом Решение Класс System.Collections.SortedList сортирует элементы на основе их ключей. Обсуждение Класс SortedList – это основанный на применении ключей словарный набор, который постоянно поддерживает упорядоченное состояние своих элементов. Конечно, это замедляет добавление/удаление элементов. И все же эти операции с набором SortedList обычно выполняются быстрее, чем постоянная пересортировка объекта Array или ArrayList. Самое важное в классе SortedList то, что он упорядочивает элементы, опираясь на значение ключей, а не сами объекты. Рассмотрим на конкретном примере использование сортированного словарного набора. Например, можно использовать отсортированный список для хранения статей в словаре (табл. 1). Табл.1. Статьи энциклопедии Ключ Значение МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Aardvark (муравьед) Amaryllis (амариллис) Armadillo (броненосец) Крупное живущее в норах ночное копытное млекопитающее. Осенний цветок. Южноафриканское луковичное растение. Представитель семейства живущих в норах неполнозубых млекопитающих. Создадим Windows-форму, включающую элементы управления Label, ComboBox и Button. Напишем процедуру загрузки формы: Dim List As New SortedList Private Sub Form10_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim item As DictionaryEntry List("Armadillo") = "Представитель семейства живущих в норах неполнозубых млекопитающих." List("Amaryllis") = "Осенний цветок. Южно-африканское луковичное растение." List("Aardvark") = "Крупное живущее в норах ночное копытное млекопитающее" List("Artichoke") = "Высокое сложноцветное растение." For Each item In List ComboBox1.Items.Add(item.Key) Next End Sub Напишем обработчик события для командной кнопки: Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Label1.Text = List(ComboBox1.SelectedItem) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Самостоятельно 1. Разберите программный код, приведенный ниже, и используйте его для построения консольного или Windows приложения. 2. Примените другой синтаксис для добавления полученных объектов в отсортированный список. 3. Проверьте ситуацию в случае изменения имени файла в каталоге С:\. Imports System.IO Module Module1 Sub Main() Dim Dir As New DirectoryInfo("C:\") Dim Files() As FileInfo Files = Dir.GetFiles Dim List As New SortedList Dim File As FileInfo For Each File In Files List.Add(File.Name, File) Next Dim Item As DictionaryEntry For Each Item In List Console.WriteLine(CType(Item.Value, FileInfo).Name) Next Console.ReadLine() End Sub End Module В приведенном примере необходимо объяснить некоторые строки кода. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Так как процедура связана с поиском и отображение файловой структуры, для запуска этого кода необходимо импортировать пространство имен System.IO. С использованием классов DirectoryInfo и FileInfo мы познакомимся подробнее в теме «Файлы и каталоги». Задание 8. Использование очереди (набора, работающего по принципу FIFO) Задача Вам нужен набор, элементы которого будут извлекаться в порядке добавления. Решение Используйте класс System.Collections.Queue – набор, работающий по принципу «первый вошел, первым вышел» (first-in, first-out, FIFO). Обсуждение Очереди применяются для выполнения разных последовательных задач. Например, в очереди можно хранить список заданий, которые должен выполнить серверный компонент. Так как очередь является набором FIFO, ее самые старые элементы всегда обрабатываются первыми. С концептуальной точки зрения, объект Queue – это массив с динамически изменяемыми размерами, хранящий объекты во многом аналогично объекту ArrayList. При создании очередь имеет емкость, равную 32 элементам (если в конструкторе вы не указали другое значение), удваивая ее при необходимости. Для получения числа элементов очереди служит свойство Count, для добавления элемента – метод Enqueue, а для извлечения – метод Dequeue, который при этом удаляет элемент из очереди. Кроме того, метод Peek позволяет извлечь следующий элемент очереди без его удаления. Однако вы не можете извлекать объекты из очереди в произвольном порядке или по номеру индекса. Рассмотрим создание и использование очереди на конкретном примере. Создадим простую очередь элементов и выполним чтение каждого из них: Module Module1 Sub Main() Создание очереди Dim Q As New Queue Заполнение очереди элементами Q.Enqueue("Первый вошел") Q.Enqueue("Второй вошел") МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Q.Enqueue("Третий вошел") Q.Enqueue("Четвертый вошел") Q.Enqueue("Пятый вошел") Для извлечения элементов очереди создадим объект String Dim Item As String Свойство Count позволяет организовать конечный цикл просмотра очереди Do While Q.Count > 0 Извлечение из очереди происходит с одновременным удалением Item = CType(Q.Dequeue, String) Console.WriteLine("Вышел: " & Item) Console.WriteLine(Q.Count.ToString & " осталось в очереди") Loop Очередь пуста Console.ReadLine() End Sub End Module Самостоятельно Организуйте ввод числовых значений, включающих нули. Используйте очередь, как структуру, выполняющую прием входящей информации. Создайте на основе данных из очереди массив, не имеющий нулевых значений. Задание 9. Использование стека (набора, работающего по принципу LIFO) Задача Вам нужен набор, элементы которого будут извлекаться в обратном порядке (иначе говоря, последний добавленный элемент должен всегда обрабатываться первым). Решение Используйте тип System.Collections.Stack, который представляет собой набор, работающий по принципу «последний вошел, первым вышел» (last-in, first-out, LIFO). Обсуждение Стеки применяются в случае, если требуется, чтобы последние добавленные элементы всегда обрабатывались первыми. Как и МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE объекты ArrayList и Queue, Stack является массивом с динамически изменяемыми размерами. При создании стек имеет емкость, равную 32 элементам (если вы не указали другое значение в конструкторе), удваивая ее при необходимости. Для получения числа элементов служит свойство Count, для добавления элемента на вершину стека – метод Push, а для извлечения – метод Pop, который при этом удаляет элемент из стека. Кроме того, метод Peek позволяет извлечь следующий элемент стека, не удаляя его. Однако вы не можете извлекать объекты из стека в произвольном порядке или по номеру индекса. В следующем примере создается простой стек и выполняется чтение всех его элементов: Module Module1 Sub Main() Создадим структуру стек Dim S As New Stack Разместим в стеке данные S.Push("Первый вошедший элемент") S.Push("Второй вошедший элемент") S.Push("Третий вошедший элемент") S.Push("Четвертый вошедший элемент") S.Push("Пятый вошедший элемент") Извлечем элементы из стека. После извлечения элементов стек пуст. Dim Item As String Do While S.Count > 0 Item = CType(S.Pop, String) Console.WriteLine("Вышел " & Item) Console.WriteLine(S.Count.ToString & " элементов осталось в стеке") Loop Console.ReadLine() End Sub End Module МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Самостоятельно Используйте структуру стека для хранения числовой информации, на основе которой создайте типизированный массив только четных чисел. Задание 10. Методы: процедуры и функции Задача Научиться компоновать фрагменты кода программы в виде небольших законченных подпрограмм, оформленных специальным образом. Решение Описать, в соответствии с определенным в VB.NET синтаксисом, повторяющиеся фрагменты кода в виде процедур или функций и обеспечить доступ к этим структурам. Обсуждение Методы – это небольшие законченные программы, состоящие из операторов языка программирования, оформленные специальным образом. Методы позволяют описать одинаковые повторяющиеся участки кода. Методы имеют имя, которое служит для вызова этих подпрограмм в коде основной программы, в кодах других подпрограмм или в собственном коде (рекурсия). По своей функциональности методы условно можно разделить на процедуры (sub) и функции (function). Главным отличием функции от процедуры является то, что функция возвращает под своим именем результирующее, вычисленное при исполнении кода функции, значение, процедура такого значения не возвращает. Сигнатура (описание заголовка) функции выглядит следующим образом: Private|Public Function Имя_Функции(ByVal | ByRef параметры As Тип_Параметров) As Тип_Результата Соответственно, сигнатура (описание заголовка) процедуры выглядит так: Private|Public Sub Имя_Процедуры(ByVal | ByRef параметры As Тип) Ключевые слова Public, Private устанавливают уровень доступа к методам: или метод доступен только в текущем модуле, форме – Private, или он доступен глобально, в любой имеющейся структуре – Public. Ключевые слова ByRef, ByVal описывают способ передачи входных параметров: или по ссылке (By Reference) или по значению (By Value). МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE В случае передачи параметра по ссылке (ByRef) компилятор связывает метод непосредственно с самим значением переменной, хранящимся в памяти. В случае передачи параметра по значению (By Value) компилятор выделяет место в памяти для хранения копии значения переменной, сама переменная остается неизменной. По умолчанию (то есть при отсутствии указания на способ передачи параметра) используется передача параметров по значению (ByVal). При вызове метода в сигнатуре происходит замена формальных параметров (их описаний) на конкретные фактические значения или параметры. Досрочное завершение методов выполняется специальными операторами Exit Sub или Exit Function, соответственно. Остается сказать, что для выдачи вычисленного значения из функции (говорят: функция возвращает значение) используется ключевое слово Return: Return результат вычисления. Приступим к изучению технологии использования методов в коде программы. 1. Рассмотрим пример, иллюстрирующий передачу параметров по ссылке и по значению. Module Module1 Sub Main() Dim X As Integer=45 proba1(X) Console.WriteLine("Переменная вне процедуры = " & X) proba2(X) Console.WriteLine("Переменная вне процедуры = " & X) Console.ReadLine() End Sub 2. Напишем код процедуры proba1(), входной параметр, для которой будет передаваться по значению (ByVal), то есть копия параметра. В ходе выполнении процедуры proba1() к значению объекта X будет добавляться число 5, другими словами, X изменяется в процедуре. Имена формальных и фактических переменных могут быть как одинаковыми, так и разными. Это ни на что не влияет. МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Sub proba1(ByVal X As Integer) X += 5 Console.WriteLine("Переменная, переданная по значению, в процедуре = " & X) End Sub 3. Напишем процедуру proba2(), в которую входной параметр будет передавать по ссылке (ByRef), то есть, обеспечен доступ непосредственно к самой переменной X. Пусть процедура proba2() так же изменяет значение X, увеличивая его на 5. Sub proba2(ByRef X As Integer) X += 5 Console.WriteLine("Переменная, переданная по ссылке, в процедуре = " & X) End Sub End Module 4. Соберите консольное приложение и запустите его на исполнение. Убедитесь в том, что передача параметров по ссылке и по значению имеет различные последствия для самих переменных. 5. Тот же эффект наблюдается для любых типов данных, например, для строк. Рассмотрим этот случай: Module Module1 Sub Main() Dim S As String S="Основная строка" proba1(S) Console.WriteLine("Переменная вне процедуры = " & S) proba2(S) Console.WriteLine("Переменная вне процедуры = " & S) Console.ReadLine() End Sub Sub proba1(ByVal S As String) S = "Измененная строка" Console.WriteLine("При передаче строки по значению: " & S) End Sub Sub proba2(ByRef S As String) S = "Измененная строка" Console.WriteLine("При передаче строки по ссылке: " & S) End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE End Module 6. Теперь рассмотрим синтаксис описания функции и ее вызов в коде основной программы на классическом примере нахождения корней квадратного уравнения. Функция для вычисления количества корней квадратного уравнения и значений этих корней может выглядеть, например, так: Public Function Roots(ByVal A As Double, ByVal B As Double, ByVal C As Double, ByRef X1 As Double, ByRef X2 As Double) As Integer Dim D As Double If A = 0 Then Return 0 Else D=B*B-4*A*C If D > 0 Then ' решений два Return 2 X1 = (-B + System.Math.Sqrt(D)) / (2 * A) X2 = (-B - System.Math.Sqrt(D)) / (2 * A) ElseIf D = 0 Then ' решений одно Return 1 X1 = -B / (2 * A) Else ' решений нет Return 0 End If End If End Function Обратите внимание на различные способы передачи входных параметров в функцию Roots: значения коэффициентов не должны изменяться, поэтому они передаются по значению (ByVal), а корни уравнения вычисляются, переменные для их значений передаются в функцию по ссылке (ByRef). 7. Пример обращения к функции напишем следующий: МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Sub Main() Dim A, B, C, X1, X2 As Double, nSol As Integer Console.WriteLine("Введите значение A") A = Console.ReadLine Console.WriteLine("Введите значение B") B = Console.ReadLine Console.WriteLine("Введите значение C") C = Console.ReadLine nSol = Roots(A, B, C, X1, X2) If nSol = 0 Then Console.WriteLine("Решений нет") ElseIf nSol = 1 Then Console.WriteLine("X1= " & X1) Else Console.WriteLine("X1= " & X1 & "X2= " & X2) End If Console.ReadLine() End Sub Воспользуемся текущим примером, чтобы ввести понятие «импортирование пространств имен». Вы должны были обратить внимание на вызов стандартной математической функции для вычисления корня квадратного SQRT(). Функция находится в пространстве имен System.Math, которое можно было заранее импортировать в проект, то есть сделать доступным следующим оператором, написанным до кода всех процедур: Impotrs System Math Теперь к функции SQRT() можно обращаться просто по имени, например, X1 = (-B + Sqrt(D)) / (2 * A). Самостоятельно внесите соответствующие изменения в код функции и снова протестируйте приложение. Пространства имен можно перечислять через запятую, используя одно ключевое слово Imports. Самостоятельно Пусть требуется создать столбец текстовых строк фиксированной ширины. Например, для оформления вывода текста в элементах МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE управления ListBox, ComboBox или просто для вывода в окне консоли или для печати. Другими словами, напишите и протестируйте в различных практических случаях метод, который дополняет строки текстового массива пробелами в соответствии с самой длинной строкой в массиве. Метод может быть реализован как функция, или как процедура, по-вашему, усмотрению. Необходимо предусмотреть возможность указания, с какой из сторон (слева или справа) строки будут дополняться пробелами. Для этого вам необходимо иметь в проектируемом методе соответствующий входной параметр, скорее всего, переменную логического типа (Boolean). Для решения задачи можно использовать методы класса System.String PadLeft или PadRight, дополняющие строку пробелами слева или справа, соответственно, до указанного размера, который является входным параметром метода. Поскольку, пока, у вас нет еще достаточного опыта написания процедур и функций, этот пример начнем рассматривать вместе, но тестирование метода вы выполните самостоятельно. В листинге ниже представлена процедура, позволяющая выполнять перечисленные действия. Используйте ее для построения интерфейса консоли или Windows приложения. Private Sub PadString(ByVal strings() As String, ByVal padLeft As Boolean) 'Определение максимальной длины строки в массиве Dim MaxLength As Integer = 0 Dim str As String For Each str In strings If str.Length > MaxLength Then MaxLength = str.Length Next 'Дополнение всех строк массива до максимальной длины. 'Цикл For..Next здесь не годится, потому что допускает только чтение, 'а нам нужно изменять строки Dim i As Integer For i = 0 To strings.GetUpperBound(0) - 1 If padLeft Then strings(i) = strings(i).PadLeft(MaxLength) Else strings(i) = strings(i).PadRight(MaxLength) End If Next End Sub МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Пример тестирования метода приведен ниже. Если вы воспользуетесь указанной процедурой тестирования, попробуйте изменить соответствие элементов массива, применив любой алгоритм. Sub Main() Dim Fruits() As String = {"яблоки", "манго", "бананы", "апельсины"} Dim Colors() As String = {"красный", "желтый", "оранжевый", "зеленый"} PadStrings(Fruits, True) PadStrings(Colors, False) Dim i As Integer For i = 0 To Fruits.GetUpperBound(0) - 1 Console.WriteLine(Fruits(i) & " " & Colors(i)) Next Console.ReadLine() End Sub Задание 11. Обработка даты и времени Задача Получить текущую дату и время. Выполнить математические действия над датами и интервалами времени. Решение Использовать объекты классов или структур System.Data, System.DateTime, System.TimeSpan, их свойства и методы. Обсуждение Для работы с информацией о дате и времени .NET предоставляет структуры System.DateTime (хранит дату и время, например, 20.01.2006 12:00:00) и System.TimeSpan (хранит интервал времени, например 3 часа), а также класс System.Date. При объявлении переменных формата дата/время вы можете использовать оба типа данных (DateTime и Date), как например, в листинге ниже. Объекты типа TimeSpan удобно использовать при вычислениях с датами. Для определения текущих значений даты и времени можно использовать методы Now и ToDay, которые возвращают значение типа Date, содержащее текущие дату и системное время. Этими методами располагает, как DateTime, так и Date. Рассмотрим на примере определение текущей даты и времени: МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE Sub Main() Dim d As Date Console.WriteLine(d.Today) Console.WriteLine(d.Now) d = d.Today.AddDays(30) Console.WriteLine(d) Dim d1 As DateTime Console.WriteLine(d1.Today) Console.WriteLine(d1.Now) Console.WriteLine(d1.Today.AddYears(1)) Console.ReadLine() End Sub С помощью символа (#) происходит непосредственное присваивание значения даты. Вычисления с датами удобно выполнять методами Add или Subtract (оба типа имеют аналогичные методы). Результат метода Subtract удобно присвоить не просто числовому объекту, а объекту типа TimeSpan, который в свою очередь, имеет ряд свойств и методов. Sub Main() Dim d As Date = #10/10/2005# Console.WriteLine(d) Dim dd As TimeSpan dd = DateTime.Now.Subtract(d) Console.WriteLine(dd.Days) Console.ReadLine() End Sub При работе с датами нельзя использовать операторы сравнения (< и >). Однако вы можете получить число, представляющее интервал TimeSpan, используя свойства, TotalHourse, TotalMinutes, TotalMilliseconds или Ticks, которое может участвовать в операции сравнения как операнд. Самостоятельно Создайте приложение, позволяющее определять, на какой день недели выпадает конкретная дата, является ли указанный год високосным и сколько дней содержится в конкретном месяце. Используйте пространство имен System.Globalization, в котором определены классы, поддерживающие календарные даты, связанные с региональными стандартами. В число этих классов входят классы GregorianCalendar (западный стандарт), HebrewCalendar, JulianCalendar, JapaneseСalendar и так далее. В этих классах инкапсулирован ряд методов, которые позволят вам решить поставленную задачу: МЕЖДУНАРОДНЫЙ БАНКОВСКИЙ ИНСТИТУТ INTERNATIONAL BANKING INSTITUTE GetDaysInMonth – возвращает число дней в конкретном месяце; GetDaysInYear – возвращает число дней в конкретном году; IsLeapYear – возвращает True, если конкретный год является високосным и так далее. Пример объявления объекта класса GregorianCalendar и обращения к его функциям представлен ниже: Module Module1 Sub Main() Dim calendar As New System.Globalization.GregorianCalendar Console.WriteLine ("Количество дней в феврале 2006 года " & calendar.GetDaysInMonth(2006, 2, 0)) Console.ReadLine() End Sub End Module