Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Названия цветов 2 страница




Особенности вычисления значений целых чисел

 

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

int X = 2; // Первая целая переменная
int Y = 3; // Вторая целая переменная

и при этом:

int Z = X + Y; // Операция сложения

то не возникает никаких проблем с вычислением значения переменной Z: 2 + 3 = 5

Аналогично, если выполняется операция умножения:

int Z = X * Y; // Операция умножения

то результат также легко предсказуем: 2 * 3 = 6

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

int Z = X / Y; // Операция деления

Нетрудно написать 2 / 3. Но это - не целое число. Каким же будет значение выражения X/Y и переменной Z?

Правило вычисления значений целых чисел состоит в том, что дробная часть отбрасывается.

В этом примере справа от знака равенства находится выражение, содержащее только целые числа, т.е. в данном случае приведение типов не происходит. Это значит, что типом выражения X/Y является тип int. Поэтому результатом вычисления целого значения выражения X/Y (= 2/3) будет 0 (ноль). В результате это значение (ноль) будет присвоено переменной Z.

Соответственно, при других значениях переменных X и Y результат будет другим. Например, если:

int X = 7; // Значение переменной целого типа
int Y = 3; // Значение переменной целого типа
int Z = X / Y; // Операция деления

то значение 7 / 3 выражения X / Y и переменной Z будет равно 2 (двум).

Порядок вычисления выражений

 

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

Вычисление значения выражения производится в соответствии с приоритетом арифметических операций и слева направо, причём каждый промежуточный результат вычисляется по правилам приведения типов.

Рассмотрим порядок вычисления выражения в следующем примере:

Y = 2.0*(3*X/Z - N) + D; // Пример выражения

Выражение в правой части от знака равенства состоит из двух слагаемых: 2.0*(3*X/Z - N) и D. Слагаемое 2.0*(3*X/Z - N) состоит из двух множителей, а именно, 2 и (3*X/Z - N). Выражение в скобках 3*X/Z - N, в свою очередь, состоит из двух слагаемых, причём слагаемое 3*X/Z состоит из трёх множителей, а именно, 3, X и Z.

Для вычисления значения выражения в правой части от знака равенства сначала будет вычислено значение выражения 3*X/Z. Это выражение содержит две операции (умножение и деление), имеющих одинаковый приоритет, поэтому вычисление выражения будет выполняться слева направо. Сначала будет вычислено значение выражения 3*X, причём тип этого значения будет таким, какой тип имеет переменная X. Затем будет вычислено значение выражения 3*X/Z, его тип также будет вычислен на основании правил приведения типов. После этого программа вычислит значение и тип выражения 3*X/Z - N, потом выражения 2.0*(3*X/Z - N) и в последнюю очередь - значение и тип всего выражения 2.0*(3*X/Z - N) + D.

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

Задача 6. Вычислить значения выражений А/В*С и А*С/В для целых чисел А, В и С.

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

int A = 3; // Значение целого типа
int B = 5; // Значение целого типа
int C = 6; // Значение целого типа
int Res_1 = A/B*C; // Результат 0 (ноль)
int Res_2 = A*C/B; // Результат 3 (три)

Проследим процесс вычисления выражения A/B*C:

1. Сначала (слева направо) будет вычислено значение выражения A/B. В соответствии с указанными выше правилами значением выражения (3/5) будет целое значение 0 (ноль).

2. Вычисление выражения 0*С (ноль умножить на С). Результат - целое значение 0 (ноль).

3. Общий результат (значение переменной Res_1) - целое значение 0 (ноль).

Теперь посмотрим, как будут развиваться события при вычислении выражения A*C/B.

1. Вычисление A*C. Значением этого выражения будет целое число 18 (3*6=18).

2. Вычисление выражения 18/B. Ответ очевиден: (18/5) после отбрасывания дробной части получится целое число 3(три).

3. Общий результат (значение переменной Res_2) - целое значение 3 (три).

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

В разделе Операторы рассматривается понятие и общие свойства операторов, в главе Операторы раскрываются собственные свойства каждого оператора.

Операторы

Понятие оператора

 

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

Оператор - это составная часть программы, фраза алгоритмического языка, предписывающая определённый порядок преобразования информации.

Любая программа содержит операторы. Наиболее близкой аналогией оператору является предложение. Операторы образуют программу так же, как обычные предложения образуют текст рассказа или повести.

Свойства операторов

 

Различаются два вида свойств операторов - общeе и собственные.

Общее свойство операторов

 

Все операторы имеют одно общее свойство - они исполняются.

Можно сказать, что оператор - это инструкция, содержащая руководство к действию (описание приказа). Для компьютера выполнять запущенную на нём программу означает (последовательно переходя от одного оператора к другому) выполнять предписания (инструкции, приказы), содержащиеся в операторах.

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

Собственные свойства операторов

 

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

Типы операторов

 

Различают два типа операторов - простые и составные.

Простые операторы

 

Простые операторы в языке MQL4 заканчиваются знаком ";" (точка с запятой). С помощью этого разделителя компьютер может определить, где заканчивается один и начинается другой оператор. Знак ";" (точка с запятой) так же необходим в программе, как "." (обычная точка) необходима в обычном тексте для разделения предложений. Один оператор может располагаться в нескольких строках, несколько операторов можно располагать в одной строке.

Каждый простой оператор заканчивается знаком ";" (точка с запятой).

Примеры простых операторов:

Day_Next= TimeDayOfWeek(Mas_Big[n][0]+60); // Простой оператор

 

Go_My_Function_ind(); // Простой оператор

 

a=3; b=a*x+n; i++; // Несколько операторов в строке

 

Print(" Day= ",TimeDay(Mas_Big[s][0]), // Один оператор..

" Hour=",TimeHour(Mas_Big[s][0]), // расположен..

" Minute=",TimeMinute(Mas_Big[s][0]),// в нескольких..

" Mas_Big[s][0]= ",Mas_Big[s][0], // строках

" Mas_Big[s][1]= ",Mas_Big[s][1]);

Составные операторы

 

Составной оператор состоит из нескольких простых, разделенных знаком ";", и оформляется фигурными скобками. Чтобы можно было использовать несколько операторов там, где ожидается присутствие только одного, предусматривается составной оператор (который также называют "блоком"). Список операторов в составном операторе выделяется фигурными скобками, а свидетельством окончания составного оператора является наличие закрывающей фигурной скобки.

Пример использования составного оператора в условном операторе. Сначала идет условный оператор if(выражение), за ним следует составной оператор. Составной оператор содержит список исполняемых операторов.

 


Рис. 17. Составной оператор.

 

Тело составного оператора заключено в фигурные скобки. Каждый составной оператор заканчивается закрывающей фигурной скобкой.

Примеры составных операторов:

// Пример оператора switch

switch(ii) // Оператор switch(выражение)

{ // Открывающая фигурная скобка

case 1: Buf_1[Pok-f+i]= Prognoz; break; // Вложенные операторы (тело операт.)

case 2: Buf_2[Pok-f+i]= Prognoz; break; // Вложенные операторы (тело операт.)

case 3: Buf_3[Pok-f+i]= Prognoz; break; // Вложенные операторы (тело операт.)

} // Закрывающая фигурная скобка,..

//.. означает окончание оператора

//----------------------------------------------------------------------------------

// Пример использования цикла

for (tt=1; tt<=Kol_Point[7]; tt++) // Оператор for(выражения)

{ // Открывающая фигурная скобка

Numb = Numb + Y_raz[tt]*X_raz[ii][tt]; // Вложенный оператор (тело операт.)

} // Закрывающая фигурная скобка..

//.. означает окончание оператора

//----------------------------------------------------------------------------------

// Пример условного оператора if

if (TimeDay(Mas_Big[f][0])!= 6) // if (выражение)

{ // Открывающая фигурная скобка

Sred =(Nabor_Koef[ii][vv][2]+ NBh)*Point;// Вложенные операторы (тело операт.)

Ind = Nabor_Koef[ii][vv][0] + f; // Вложенные операторы (тело операт.)

Print(" Ind= ",Ind); // Вложенные операторы (тело операт.)

} // Закрывающая фигурная скобка..

//.. означает окончание оператора

 

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

Примеры использования простых операторов:

//----------------------------------------------------------------------------------

// Пример оператора for

for (n=1; n<=Numb; n++) // for(выражения)

Mas[n]= Const_1+ n*Pi; // Вложенный оператор (тело операт.)

//----------------------------------------------------------------------------------

// Пример условного оператора if

if (Table > Chair) // if (выражение)

Norma = true; // первый оператор (подоператор 1)

else // Альтернативное условие

Norma = false; // второй оператор (подоператор 2)

//----------------------------------------------------------------------------------

 

Несколько простых операторов могут быть объединены в составной оператор без строгой необходимости.

Это - редко встречающаяся, но вполне допустимая конструкция. В этом случае операторы, заключённые в фигурные скобки, называют блоком операторов. Такое использование допустимо. Обрамление фигурными скобками делается по воле программиста для удобства представления кода. Пример блока операторов:

{ // Открывающая фигурная скобка
Day_Next= TimeDayOfWeek(Mas_Big[n][0]+60); // Простой оператор
b=a*x+n; // Простой оператор
} // Закрывающая фигурная скобка..

Требования к операторам

 

Операторы должны быть записаны в текст программы в соответствии с правилами форматирования (представления в программе). Ни один оператор не может быть составлен вне этих правил. Если же программа содержит оператор, составленный вопреки правилам форматирования, то при компиляции программы редактор MetaEditor выдаст сообщение об ошибке. Это значит, что в таком виде программа (содержащая ошибочный оператор) не может использоваться.

Выражение "Формат оператора" следует понимать как набор правил форматирования, присущих виду оператора. Каждый вид оператора имеет свой формат. Форматы операторов подробно рассматриваются в соответствующих разделах главы Операторы.

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

 

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

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

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

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

Пример написания и исполнения операторов

 

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

В качестве примера рассмотрим, как работает оператор присваивания. Для этого возьмём решение простой системы линейных уравнений и сравним, как некоторые математические вычисления отражаются в обычном тексте и как - в тексте программы, в операторах.

 

Задача 7. Дана система уравнений: Y = 5 Y - X = 2 Требуется найти численное значение переменной Х.

Вариант 1. Текст составлен обычным способом на листе бумаги.

1. 5 - Х = 2

2. Х = 5 - 2

3. Х = 3

Вариант 2. Текст программы.

Y = 5; // Строка 1
X = Y - 2; // Строка 2

И в первом, и во втором варианте записи (строки) содержат законченный смысл. Тем не менее, строки из первого варианта не могут в таком виде использоваться в программе, потому что их вид не соответствует формату оператора присваивания.

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

Оба оператора в Варианте 2 являются операторами присваивания. Любой оператор присваивания отдаёт компьютеру буквально следующий приказ:

Вычислить значение выражения справа от знака равенства и присвоить полученное значение переменной слева от знака равенства.

По этой причине в операторе присваивания слева от знака равенства не может находиться ничего, кроме переменной. Например, запись 5 - Х = 2, используемая в первом варианте, содержит ошибку, потому что набор символов 5 - Х не является переменной. Поэтому не существует и ячейки памяти, в которую должно быть помещено численное значение выражения, вычисленного справа от знака равенства.

Проследим, что будет делать компьютер, выполняя операторы второго варианта.

1. Переход к оператору (строка 1).

Y = 5; // Строка 1

2. Обращение к правой части оператора (правая часть находится между знаком равенства и точкой с запятой).

3. Компьютер обнаружил, что правая часть оператора содержит численное значение.

4. Запись численного значения (5) в ячейку памяти переменной Y.

5. Переход к следующему оператору (строка 2).

X = Y - 2; // Строка 2

6. Обращение к правой части оператора.

7. Компьютер обнаружил, что правая часть оператора содержит выражение.

8. Вычисление численного значения правой части оператора (5 - 2).

9. Запись численного значения (3) в ячейку памяти этой переменной Х.

Выполнение компьютером действий 1 - 4 есть исполнение первого оператора (строка 1). Выполнение компьютером действий 5 - 9 есть исполнение второго оператора (строка 2).

 

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

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

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

X = X + 1; // Пример счётчика

с точки зрения математической логики и здравого смысла кажется ошибочной. Но она вполне приемлема, если воспринимать её как оператор (кстати, именно этот оператор имеет широкое применение).

В этом операторе вычисляется новое значение переменной Х: выполняя оператор присваивания (то есть вычисляя значение правой части оператора), компьютер обратится к ячейке памяти, несущей численное значение переменной Х (например, в момент обращения оно окажется равным 3), вычислит выражение в правой части оператора присваивания (3 + 1) и полученное значение (4) запишет в ячейку памяти переменной Х. В результате исполнения этого оператора присваивания переменная Х получит новое значение - (4). Компьютер будет удерживать это значение переменной Х до тех пор, пока переменная Х не встретится в левой части от знака равенства в каком-нибудь другом операторе присваивания. В этом случае будет вычислено новое значение этой переменной, которое она будет удерживать до следующего возможного изменения.

Функции

 

Понятие функции

 

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

Функция - это именованная, обособленная часть программы, описывающая порядок преобразования информации.

Говоря о функциях, мы будем иметь в виду два аспекта: описание функции и вызов функции.

Описание функции - именованная, обособленная часть программы, предназначенная для исполнения.

Вызов функции (обращение к функции) - это запись, исполнение которой приводит к исполнению функции.

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

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

во-первых, составленный таким образом текст программы гораздо легче читается;

во-вторых, легко видеть и при необходимости изменять текст функции, не меняя при этом основной код;

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

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

Состав функции

 

Итак, функция может быть описана и вызвана. Рассмотрим пример. Пусть у нас имеется небольшая программа (рис. 18), вычисляющая гипотенузу по двум заданным катетам с помощью теоремы Пифагора.

В этой программе все вычисления собраны в одном месте, операторы исполняются подряд в том порядке, в котором они встречаются в программе (в направлении сверху вниз).


Рис. 18. Код цельной программы pifagor.mq4.

 

Задача 8. Оформить часть представленного кода программы в виде функции.

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

В этой программе часть вычислений оформлена в виде функции. В основном коде имеется обращение к пользовательской функции. Описание пользовательской функции расположено за пределами (после) основного кода.


Рис. 19. Код программы, содержащий описание и обращение к пользовательской функции gipo.mq4.

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

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

Описание функции

 

Описание функции состоит из двух основных частей - заголовка функции и тела функции.

Заголовок функции состоит из указания типа возвращаемого значения, названия функции и списка формальных параметров. Список формальных параметров заключается в круглые скобки и располагается после названия. Тип возвращаемого значения может быть одним из известных нам типов: int, double, bool, color, datetime и string. Если функция не возвращает никакого значения, то её тип можно обозначить void ("без типа") или любым другим типом.

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


Рис. 20. Описание функции.

Описание функции должно находиться в программе обособленно, за пределами любых других функций (т.е. не внутри какой-либо другой функции, а снаружи).

Вызов функции

 

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


Рис. 21. Вызов функции (обращение к функции).

Вызов любой функции всегда указывается в коде другой функции (т.е. не за пределами всех функций, а внутри одной из них).

Типы функций

 

Различают три типа функций - специальные, стандартные (встроенные, предопределённые) и пользовательские.

Специальные функции

 

В языке MQL4 имеется всего 3 специальные функции. Они имеют предопределённые имена: init(), start() и deinit(), которые запрещено использовать для названия других функций. Специальные функции подробно рассматриваются в разделе Специальные функции. Здесь укажем лишь, что основной код программы размещается внутри этих функций (рис. 18, 19).

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




Поделиться с друзьями:


Дата добавления: 2014-12-29; Просмотров: 287; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.12 сек.