Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Преобразования разнотипных значений




Лабораторная работа № 2

Программы линейной структуры

 

Цель работы

Изучить структуру программы на языке Visual Studio.NET, операторы присваивания, ввода и вывода данных, используемые при проектировании программ линейной структуры.

Порядок выполнения работы

Получить задание для выполнения лабораторной работы (раздел 5) согласно своему варианту (номер студента по журналу). Разработать и отладить программу. Составить и защитить отчет о лабораторной работе у преподавателя.

 

Содержание отчета

· Наименование и цель работы.

· Задание на лабораторную работу согласно варианту.

· Схема алгоритма, текст программы на алгоритмическом языке.

· Результаты работы программы.

 

Краткая теория

 

Переменные и присваивание

Имена переменных в VB .NET имеют длину до 255 символов и обычно начинаются с буквы в кодировке Unicode (за дополнительной информацией о Unicode обращайтесь на сайт www.unicode.org), хотя также допускается символ подчеркивания. Далее следует произвольная комбинация букв, цифр и символов подчеркивания. Все символы имени являются значимыми, но регистр символов игнорируется; считается, что firstBase и firstbase — одна и та же переменная. Присваивание выполняется при помощи знака =

 

theYear = 2001

 

 В .NET Framework используются новые правила присваивания имен переменным. В соответствии рекомендациями, приведенными в MSDN, применять венгерскую запись нежелательно, а значимые имена переменных (то есть не состоящие из одной буквы, как i или t) должны оформляться в альтернативной схеме выбора регистра.

Имена переменных не могут совпадать с последовательностями, зарезервированными VB .NET (список для текущей версии приведен в табл. 4.1), однако это ограничение можно обойти, заключив имя переменной в квадратные скобки. Например, переменная не может называться Loop, а имя [Loop] подойдет — хотя делать это не рекомендуется. Зарезервированные слова внутри имен переменных допустимы (скажем, loopit — вполне нормальное имя). При попытке использования ключевого слова в качестве имени переменной VB .NET подчеркивает его и информирует об ошибке (при помощи экранной подсказки).

 

Таблица 4.1. Ключевые слова

 

AddressOf Alias And Ansi As
Assembly Auto Binary BitAnd Byte
BitNot BitOr BitXor Boolean ByRef ByVal
Call Case Catch CBool CByte
CChar CDate CDec Class CLng
CDbl Char CInt CObj Compare
Const CShort CSng CStr Ctype
Date Decimal Declare Default Delegate
Dim Do Double Each Else
Elself End Enum Erase Error
Event Exit Explicit ExternalSource False
Finally For Friend Function Get
GetType GoTo Handles If Implements
Imports In Inherits Integer Interface
Is Lib Like Long Loop
Me Mod Module Mustlnherit MustOverride
MyBase MyClass Namespace Next New
Not Nothing Notlnheritable NotOverridable Object
Off On Option Optional Or
Overloads Overridable Overides ParamArray Preserve
Private Property Protected Public RaiseEvent
Readonly ReDim REM RemoveHandler Resume
Return Select     Set Shadows Shared Short
Single Static Step Stop Strict
String Structure Sub SyncLock Text
Then Throw To True Try
TypeOf Unicode Until When While
With With Events WriteOnly Xor

 

 Литералы и их соответствие типам данных

Литералом называется последовательность символов, которая может интерпретироваться как значение одного из примитивных типов.

Хотя возможность непосредственной интерпретации данных предусмотрена в любом языке программирования, решить, как именно следует интерпретировать те или иные данные, иногда бывает непросто. Наверное, все согласятся с тем, что 3 — это число 3 и его следует интерпретировать именно так. Но что такое число 3 с точки зрения компилятора? Сколько байт памяти следует под него выделить? Теоретически для хранения числа 3 хватит 2 бит, но в современных языках программирования обычно происходит не так.

Итак, компилятор должен проанализировать литерал и принять необходимые решения, поэтому вы должны по возможности точнее описать, что вы имеете в виду, не полагаясь на разумность компилятора. Вернемся к примеру с простым числом 3. В VB .NET оно может представлять собой (среди прочего):

Байт: фактически вы сообщаете компилятору, что для хранения числа следует выделить минимальный объем памяти.

Короткое целое: старый тип Integer .

Целое .NET:тип Long (компилятор выделяет для хранения числа 4 байта).

К счастью, символ 3 никогда не будет автоматически интерпретироваться как строковая константа (если не переопределять стандартную логику VB). В VB .NET строки и числа по умолчанию не смешиваются — более подробно эта тема рассматривается в разделе «Преобразования разнотипных значений».

С точки зрения компилятора простой констатации «это число 3» недостаточно. Разумеется, VB .NET, как и любой язык программирования, позволяет уточнить смысл литерала. Например, 31 — литерал типа Integer со значением 3, а литерал "3" относится к строковому типу String (тип String рассматривается ниже в этой главе).

 Примитивные типы можно рассматривать как атомарные элементы языка, хотя в VB .NET они представляют собой псевдонимы для классов из библиотеки System.

В переменной, объявленной с примитивным типом, хранятся значения указанного типа. Ниже перечислены примитивные числовые типы VB .NET.

Byte: 1-байтовое целое без знака в интервале от 0 до 255.

Short: 2-байтовое целое со знаком в интервале от -32 768 до 32 767, аналог типа Integer в прежних версиях VB. Признаком типа Short в литералах является суффикс S — например, 237S.

Integer: 4-байтовое целое со знаком в интервале от -2 147 483 648 до 2 147 483 647, аналог типа Long в прежних версиях VB. Признаком типа Integer в литералах является суффикс I — например, 2371.

Если суффикс не указан, а число входит в интервал допустимых значений типа Integer, по умолчанию оно сохраняется в формате Integer. Это связано с тем, что на 32-разрядных процессорах тип Integer обрабатывается эффективнее остальных типов.

Long: 8-байтовое целое со знаком в интервале от -9 223 372 036 854 775 808 до 9 223 372 036 854 775 807. Не имеет аналогов в прежних версиях VB. Признаком типа Long в литералах является суффикс L — например, 2371.

При выполнении операций с вещественными числами используются следующие типы:

Single: 4-байтовое вещественное число. Признаком типа Single в литералах является суффикс F — например, 1.23F или 3F.

Double: 8-байтовое вещественное число. Если в числе с десятичной точкой не указан суффикс, по умолчанию оно сохраняется в формате Double. Это связано с тем, что Double работает эффективнее Single; на 32-разрядных процессорах Double является основным типом для выполнения вещественных операций.

Decimal: 12-байтовое вещественное число, гарантирующее отсутствие ошибок округления в громадном интервале допустимых значений с 28 значащими цифрами. Формальное определение гласит, что тип Decimal предназначен для хранения чисел с мантиссой в интервале ±79 228 162 514 264 337 593 543 950 335, масштабируемых до произвольного порядка при условии, что количество значащих цифр не превышает 28. Таким образом, наименьшее число, представляемое типом Decimal, равно ±0.0000000000000000000000000001. Признаком типа Decimal в литералах является суффикс D.

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

 

Console.WriteLine(12345678 * 4567)

 

компилятор выдает ошибку:

 

This constant expression produces a value that is not representable in type System.Integer.

 

Проблема решается при помощи суффикса типа Long:

 

Console.WriteLine(123456781 * 4567)

 

Общие методы MaxValue и MinValue, ассоциированные с типом, возвращают соответственно верхнюю и нижнюю границы интервала допустимых значений. Пример:

 

Console.WriteLine(Integer.MaxValue)

 

В таблице 4.2 собраны данные о соответствии числовых типов VB .NET, типов .NET Framework и их аналогов из VB6 (если они есть).

 

Таблица 3.2. Соответствие между числовыми типами 

Тип VB. NET Тип .NET Framework

Byte               System. Byte      

Boolean     System. Boolean

Decimal     System. Decimal

Double      System. Double  

Short               System. Intl6

Integer       System.Int32

Long               System.Int64

Single        System. Single  

 

 Прочие литералы

Кроме числовых литералов также существуют литералы типов Boolean,Date и Char. Тип данных Bool ean принимает значения True и False. В VB .NET он представляется 4 байтами.

В VB .NET бета-версии 1 значение True было равно +1 (как и в других языках .NET). Начиная с бета-версии 2 оно снова стало равно -1. Говоря точнее, в поразрядных операциях и при преобразовании к числовым типам значение True равно -1, а не 1. Но если логическая величина VB .NET передается за пределы VB, при приведении к числовому типу нового языка она считается равной 1. Пожалуй, это решение было ошибочным, поскольку одной из целей, поставленных при разработке .NET, было обеспечение максимальной межъязыковой совместимости. Пока вы ограничиваетесь встроенными константами True и False, все будет нормально, но стоит перейти к конкретным числовым значениям — и у вас могут возникнуть проблемы.

Тип данных Date представляет дату и/или время. Такие литералы заключаются между символами #...# — например, #Jan 1. 2001#. Если время не указано), предполагается, что литерал соответствует полуночи указанной даты.

Тип Date в VB .NET не преобразуется к типу Double. В частности, из этого следует, что с датами нельзя производить математические вычисления — например, вычислить завтрашнюю дату командой Today+1.

Тип данных Char представляет один символ Unicode. Объем кодировки Unicode (65 536 символов) вполне достаточен для представления всех существующих алфавитов. Обычно символ заключается в кавычки, за которыми следует префикс С (например, "Н"С), но вы также можете воспользоваться встроенной функцией Chr и указать числовой код символа Unicode. Например, запись Chr(&H2153) представляет символ 1/3 кодировке Unicode, хотя в некоторых операционных системах этот символ не будет отображаться во время работы программы. Если заключить один символ в кавычки без суффикса «С», вы получите тип String вместо Char, а автоматическое преобразование между этими типами не поддерживается (команда Option Strict описана ниже в этой главе).

Объявление переменных

В VB .NET переменные объявляются в процедурах и функциях при помощи ключевых слов Dim и As, а присваивание выполняется знаком =:

 

Dim foo As String

foo = "bar"

 

Если вы не изменяли стандартную настройку VB .NET, переменные должны объявляться перед использованием. В VB .NET поддерживается инициализация переменных при объявлении. Пример:

 

Dim salesTax As Decimal = 0.0825D

 

Команда объявляет переменную с именем salesTax и присваивает ей начальное значение 0.0825 типа Decimal. При инициализации могут использоваться любые синтаксически правильные выражения VB .NET. Следующая команда присваивает переменной startAngle встроенное значение математической константы п, используя для этого константу класса System. Math: Dim startAngle As Decimal - Math.PI

Если переменная не была инициализирована при объявлении, ей присваивается стандартное значение, соответствующее ее типу, — например, числовым переменным присваивается 0. При таком удобном синтаксисе, как в VB .NET, всегда лучше инициализировать переменную при объявлении, чем полагаться на значение по умолчанию. В следующем фрагменте используется оператор &, применявшийся в VB для конкатенации строк:

 

Sub Main()

Dim salesTax As Double = 0.0825

Dim state As String = "California"

Console.WriteLine("The sales tax in " & state & " is " & salesTax)

 

Console. ReadLine()

End Sub

 

Программа выводит следующий результат:

 

The sales tax in California is 0.0825

 

В отличие от предыдущих версий VB, объявление нескольких переменных в одной строке программы работает именно так, как подсказывает здравый смысл. Иначе говоря, следующая команда объявляет три переменные: i, j и k, относящиеся к типу Integer:

 

Dim i, j, k As Integer

 

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

 

Dim i, j, k As Integer = 1

 

Как и в прежних версиях VB, вместо указания типа с ключевым словом As может использоваться суффикс типа. Например:

 

Dim i%, myname$

 

Приведенная команда объявляет переменную i типа Integer и переменную myName типа String. Программистам VB .NET поступать подобным образом не рекомендуется.

Все программисты хорошо помнят, какие жаркие дискуссии проходили по поводу соглашений об именах переменных. Существует сложная система префиксов (так называемая венгерская запись), позволяющая с первого взгляда определить тип переменных. Согласно общим рекомендациям программирования для .NET Framework применение венгерской записи нежелательно. Мы будем следовать этим рекомендациям, и в книге префиксы встречаются очень редко.

Команды семейства DefType (например, Deflnt) в VB .NET не поддерживаются.

Преобразования разнотипных значений

По мнению многих программистов, прежние версии VB слишком либерально относились к преобразованию типов. В результате возникало явление «злостного искажения типов» — скажем, VB6 позволял умножить строковое представление числа на Integer.

В VB .NET предусмотрен режим жесткой проверки типов Option Strict. Чтобы активизировать его, включите следующую команду в начало программы (также можно воспользоваться флажком Strict Type Checking на вкладке Build диалогового окна Project Properties):

 

Option Strict On

 

При активизации этого режима (а это следует делать всегда!) VB .NET требует, чтобы любые преобразования типов, которые могут привести к потере данных, выполнялись явно. Например, при преобразовании Single к типу Integer может произойти потеря точности, поскольку тип Integer не позволяет представить весь интервал допустимых значений типа Single. С другой стороны, если потеря данных исключена (скажем, при преобразовании Integer в тип Long или Decimal), VB .NET выполняет преобразование автоматически. В документации VB .NET преобразования без потери данных называются расширяющими преобразованиями (widening conversions). В таблице 4.3 переделены допустимые расширяющие преобразования для базовых типов данных.

 

Таблица 4.3. Допустимые расширяющие преобразования для базовых типов VB .NET 

Тип Допустимое расширение
Byte Byte, Short, Integer, Long, Decimal Single, Double
Short Short, Integer, Long, Decimal, Single, Double
Integer Integer, Long, DecimaL Single, Double
Long Long, DecimaL Single, Double
Single Single, Double
Date Date, String

 

Более того, при активном режиме жесткой проверки типов вы не сможете использовать конструкции вида:

 

Dim foo As Boolean

foo = 3

 

В этом фрагменте логической переменной foo значение True присваивается в виде ненулевого. Подобные преобразования должны выполняться явно:

Dim foo As Boolean

foo =СВооl(З)

 

VB .NET автоматически выполняет преобразование между символьным типом и строкой, состоящей из одного символа.

При желании вы можете вернуться к доисторическим временам и отказаться от жесткой проверки типов. Для этого достаточно начать модуль со следующей команды:

 

Option Strict Off

 

Впрочем, поступать подобным образом не рекомендуется.

 

Если содержимое переменной одного типа может быть преобразовано к другому типу, можно воспользоваться функцией явного преобразования, как в только что приведенном примере с СВооl. Функции явного преобразования типов перечислены в таблице 4.4.

 

Таблица 4.4. Функции явного преобразования типов 

Функция  Описание

CBool    Преобразует выражение к типу Boolean

CByte    Преобразует выражение к типу Byte

CInt     Преобразует выражение к типу Integer с округлением

CIng     Преобразует выражение к типу Long с округлением

CSng         Преобразует выражение к типу Single

CDate    Преобразует выражение к типу Date

СDbl     Преобразует выражение к типу Double

CDec     Преобразует выражение к типу Decimal

CStr     Преобразует выражение к типу String

CChar   Преобразует первый символ строки к типу Char

 

 

VB .NET выполняет числовые преобразования только в том случае, если преобразуемое число входит в интервал допустимых значений нового типа; в противном случае выдается сообщение об ошибке.

На первый взгляд кажется, что тип Char можно интерпретировать как короткое целое без знака (то есть целое в интервале от 0 до 65 535), но делать этого не следует. Начиная с бета-версии 2 было запрещено преобразование Char в число функциями семейства CInt; вместо этого используется встроенная функция Asc.

Ниже приведен хрестоматийный пример — преобразование температуры по Цельсию в температуру по шкале Фаренгейта. Мы руководствуемся следующими предположениями:

Пользователь завершает ввод текста нажатием клавиши Enter.

Все введенные символы воспринимаются методом ReadLine().

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

 

' Преобразование температуры по Цельсию в температуру по Фаренгейту

 

Option Strict On Module

Module Modulel

Sub Main()

Dim cdeg As Decimal

Console.WriteLine(“ Enter the degrees in centigrade...")

cdeg = CDec(Console.ReadLine())

Dim fdeg As Decimal

fdeg = (((9.0 / 5.0) * cdeg) + 32)

Console.WriteLine(cdeg & " is " & fdeg & " degrees Fahrenheit.")

Console. ReadLine()

End Sub

End Module

 

Обратите внимание на суффикс @ — он гарантирует, что при вычислениях будет использоваться тип Decimal. Если убрать этот суффикс, то при включенной жесткой проверке типов будет выдано сообщение об ошибке!

При использовании простого оператора / для деления в VB .NET необходимо учитывать некоторые нюансы. За дополнительной информацией обращайтесь к разделу «Математические операторы».

Константы

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

В VB .NET при активизации жесткой проверки типов необходимо явно указывать тип констант:

 

Const PIE = 3.14159 ' Не будет компилироваться с Option Strict

 

Const PIE As Double = 3.14159 ' Правильно, но Math.PI лучше :-)

 

Значение констант может определяться числовыми выражениями, в том числе и содержащими ранее определенные константы:

 

Const PIE_OVER_2 As Double = PIE / 2

 

Аналогичным образом определяются строковые константы:

 

Const USER_NAME As String = "Bill Gates"

 

Строки

Строковая переменная содержит текст в кодировке Unicode длиной до 231 (более 2 миллиардов!) символов. Как было показано выше, значения строкового типа заключаются в кавычки:

 

Dim message As String

message = "Help"

 

Конкатенация (объединение) строк обычно выполняется оператором &. Старый вариант с оператором + тоже работает, но при отключении жесткой проверки типов он может вызвать серьезные проблемы, поэтому использовать знак + при конкатенации не рекомендуется. Старый способ идентификации строковых переменных с суффиксом $ (например, aStringVariableS) иногда используется для временных переменных.

В VB .NET строковые переменные не относятся к базовому типу, а являются экземплярами класса String. Некоторые нюансы, связанные с их применением, будут рассмотрены позже, а пока мы упомянем лишь одну особенность, о которой необходимо знать для эффективной работы со строками в VB .NET: при любой модификации строки в VB .NET создается новый экземпляр строки. Частая модификация строки требует больших затрат ресурсов, поэтому в VB .NET имеется класс StringBuilder для выполнения подобных операций (например, выборки данных из буфера и объединения их в строковой переменной).

В отличие от предыдущих версий VB, в VB .NET не поддерживаются строки фиксированной длины.

Строковые функции

В вашем распоряжении остались все классические строковые функции Left, Right, Mid и т. д., но версии этих функций с суффиксом $ теперь не поддерживаются. В таблице 4.5 перечислены важнейшие функции класса String. Не забывайте, что при многократной модификации строк (например, при вызове Mid в цикле) следует использовать класс StringBuilder. Некоторые из приведенных методов используют массивы, которые будут рассмотрены ниже в этой главе.

При программировании для .NET рекомендуется по возможности использовать методы и свойства класса String, входящего в .NET Framework. Самые распространенные строковые методы перечислены в табл. 3.6.

 

Таблица 4.5. Основные строковые функции 

Функция Описание

Asc     Возвращает код первого символа в строке

Chr     Преобразует число в символ Unicode

Filter     Получает строковый массив и искомую строку; возвращает одномерный массив всех элементов, в которых был найден заданный текст

GetChar Возвращает символ строки с заданным индексом в формате Char. Индексация символов начинается с 1. Например, команда GetChar("Hello",2) возвращает символ «е» в виде типа Char

InStr     Возвращает позицию первого вхождения одной строки в другой строке

InStrRev Возвращает позицию последнего вхождения одной строки в другой строке

Join     Строит большую строку из меньших строк

LCase    Преобразует строку к нижнему регистру

Left     Находит или удаляет заданное количество символов от начала строки

Len     Возвращает длину строки

LTrim    Удаляет пробелы в начале строки

Mid     Находит или удаляет символы в строке

Replace Заменяет одно или более вхождений одной строки в другой строке

Right     Находит или удаляет заданное количество символов в конце строки

RTrim   Удаляет пробелы в конце строки

Space        Генерирует строку заданной длины, состоящую из пробелов

Split     Позволяет разбивать строку по заданным разделителям (например, пробелам)

Str     Возвращает строковое представление числа

StrComp Альтернативный способ сравнения строк

StrConv Преобразует строку из одной формы в другую (например, с изменением регистра)

String        Создает строку, состоящую из многократно повторяющегося символа

Trim     Удаляет пробелы в начале и конце строки

UCase   Преобразует строку к верхнему регистру

 

Таблица 3.6. Основные строковые методы и свойства .NET Framework 

Метод/свойство  Описание

Chars        Возвращает символ, находящийся в заданной позиции строки

Compare Сравнивает две строки

Copy     Копирует существующую строку

Copy To Копирует заданное количество символов, начиная в заданную позицию массива символов

Empty   Константа, представляющая пустую строку

EndsWith Проверяет, завершается ли заданная строка определенной последовательностью символов

IndexOf Возвращает индекс первого вхождения подстроки в заданной строке

Insert     Возвращает новую строку, полученную вставкой подстроки в заданную позицию

Join     Объединяет массив строк с заданным разделителем

LastlndexOf    Возвращает индекс последнего вхождения заданного символа или подстроки в строке

Length   Возвращает количество символов в строке

PadLeft  Выравнивает символы строки по правому краю. Строка дополняется слева пробелами или другими символами до заданной длины

PadRight Выравнивает символы строки по левому краю. Строка дополняется справа пробелами или другими символами до заданной длины

Remove Удаляет из строки заданное количество символов, начиная с заданной позиции

Replace Заменяет все вхождения подстроки другой подстрокой

Split     Разбивает строку, превращая ее в массив подстрок

Starts With Проверяет, начинается ли заданная строка определенной последовательностью символов

Substring Возвращает подстроку, начинающуюся с заданной позиции

ToCharArray  Копирует символы строки в символьный массив

ToLower Возвращает копию строки, преобразованную к нижнему регистру

ToUpper Возвращает копию строки, преобразованную к верхнему регистру

Trim     Удаляет пробелы или все символы из набора, заданного в виде массива символов Unicode, в начале и конце строки

TrimEnd Удаляет пробелы или все символы из набора, заданного в виде массива символов Unicode, в конце строки

TrimStart Удаляет пробелы или все символы из набора, заданного в виде массива символов Unicode, в начале строки

 

Индексация символов в строке начинается в методах .NET Framework с нуля, индекс первого символа равен 0.

Поскольку в .NET Framework строки являются объектам, синтаксис вызова этих методов достаточно логичен и удобен. Выполните следующую программу:

 

Sub Main()

Dim river As String =" Mississippi Missippi"

'один пробел слева

Console. WriteLine( river. Tollpper ())

Console.WriteLine(river.ToLower())

Console.WriteLine(river.Trim())

Console. WriteLine(river. EndsWith("I"))

Console.WriteLine(river.EndsWith("i"))

Console.WriteLine(river.IndexOf("s"))

'Индексация начинается с 0!

Console.WriteLine(river.Insert(9. " river"))

'Индексация

' начинается с 0!

Console.ReadLine()

End Sub

 

Результат выглядит так:

 

MISSISSIPPI MISSIPPI

mississippi missippi

Mississippi Missippi

False

True

3

Mississi riverppi Missippi

 

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 172.

stydopedya.ru не претендует на авторское право материалов, которые вылажены, но предоставляет бесплатный доступ к ним. В случае нарушения авторского права или персональных данных напишите сюда...