Язык программирования Си

Разложение функции в ряд Тейлора, алгоритм работы программного интерфейса сокетов, исходный текст программ с комментариями. Возможности языка программирования Си и среда разработки приложений в ОС Linux. Виртуальная среда VMWare Player и VirtualBox.

Рубрика Программирование, компьютеры и кибернетика
Вид лабораторная работа
Язык русский
Дата добавления 02.09.2014
Размер файла 1,8 M

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

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

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

МИНОБРНАУКИ РОССИИ

Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования

«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ ЭКОНОМИЧЕСКИЙ УНИВЕРСИТЕТ»

КАФЕДРА ВЫЧИСЛИТЕЛЬНЫХ СИСТЕМ И ПРОГРАММИРОВАНИЯ

ОТЧЕТ ПО ЛАБОРАТОРНОЙ РАБОТЕ №1

по дисциплине: «Информационные технологии»

Выполнил:

Воробьев В.С.

2014 г.

1. Постановка задачи

Цель лабораторной работы: знакомство с возможностями языка программирования Си и средой разработки приложений в ОС Linux.

Работа выполняется под ОС Linux (Kali): http://www.kali.org/downloads/

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

Для знакомства с семейством ОС UNIX полезно прочесть руководство пользователя.

1. Написать на языке Си программу, подсчитывающую ряд Тейлора для функции exp(x). Через аргументы командной строки задать x и точность, сравнить полученный результат со встроенной функцией. Условие: программа должна содержать локальную функцию-обертку для strcmp().

2. Разработать клиент-серверное приложение, суть которого заключается в следующем. Клиент отправляет на сервер зашифрованное по алгоритму XOR число. Сервер возвращает ответ - значение функции exp(x), полученное методом разложения в ряд Тейлора. На стороне сервера полученное число расшифровывается, вычисляется exp(x) по методу разложения в ряд Тейлора, снова зашифровывается и отправляется обратно клиенту. Клиент расшифровывает полученное значение и выводит на экран (или записывает в файл). Клиент и сервер заранее знают общий ключ шифрования.

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

алгоритм программа linux тейлор

1. Когда ряд Тейлора функции по степеням сходится в некоторой окрестности точки и притом к самой функции . Если это имеет место, то

,

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

Выражение формулы Тейлора для многочлена в окрестности точки а, где а - это х0:

,

Для функции exp(x), где экспонента - показательная функция с основанием, равным иррациональному числу e, т. е. f(x)=ex, P(a)=ea.

Производная первого порядка:

Производная второго порядка:

Производная третьего порядка:

Тогда разложение функции exp(x) в ряд Тейлора в окрестности точки а следующее:

,

Исходными данными в программе задания 1 будут значение x (по заданию), принадлежащее интервалу ; сигма обозначим t; n - количество слагаемых ряда Тейлора. Найдем х0 как х=х±t/2.

С помощью функции strcmp сравниваем полученный результат разложения в ряд Тейлора с результатом, полученным встроенной функцией.

Функция strcmp():

#include

int strcmp(const char *strl, const char *str2);

Описание функции. Заголовочный файл: string.h

Описание

Эта функция сравнивает символы двух строк, string1 и string2. Начиная с первых символов функция strcmp сравнивает поочередно каждую пару символов, и продолжается это до тех пор, пока не будут найдены различные символы или не будет достигнут конец строки.

Параметры:

string1 Первая сравниваемая Си-строка.

string2 Вторая сравниваемая Си-строка.

Возвращаемое значение

Функция возвращает несколько значений, которые указывают на отношение строк: Нулевое значение говорит о том, что обе строки равны. Значение больше нуля указывает на то, что строка string1 больше строки string2, значение меньше нуля свидетельствует об обратном.

Функция strcmp начинает сравнивать по одному символу и как только будут найдены первые неодинаковые символы, функция проанализирует числовые коды этих символов. Чей код окажется больше, та строка и будет считаться большей.

2. XOR - это функция булевой алгебры, носящей название «исключающее или», данная функция используется для работы с данными представленными в двоичной системе исчисления. Основным достоинством, позволяющим использовать эту функцию в шифровальных алгоритмах является ее обратимость, при отсутствии потери информации.

XOR-шифрование является самым простым и одним из самых эффективных (при правильном использовании) алгоритмов.

Как известно из булевой алгебры, операция логического сложения «» по основанию 2 (или логического исключаещего ИЛИ -- XOR, eXclusive OR) имеет следующую семантику [3, стр.186]:

То есть, операция z = x y по сути поразрядная (побитовая -- результат не зависит от соседних битов). Если только один из соответствующих битов равен 1, то результат 1. А если оба 0 или оба 1, то результат 0.

Задача сводится к обеспечению генерации ключа в соответствии с требованиями выбранного алгоритма. Отечественный ГОСТ 28147/89 - им официально разрешено шифрование на территории РФ.

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

Ключ нужно вводить вручную.

Алгоритм ГОСТ 28147-89 имеет четыре режима работы.

- Режим простой замены принимает на вход данные, размер которых кратен 64-м битам. Результатом шифрования является входной текст, преобразованный блоками по 64 бита в случае зашифрования циклом «32-З», а в случае расшифрования -- циклом «32-Р».

- Режим гаммирования принимает на вход данные любого размера, а также дополнительный 64-разрядный параметр -- синхропосылку. В ходе работы синхропосылка преобразуется в цикле «32-З», результат делится на две части. Первая часть складывается по модулю 232 с постоянным значением 101010116. Если вторая часть равна 232-1, то её значение не меняется, иначе она складывается по модулю 232-1 с постоянным значением 101010416. Полученное объединением обеих преобразованных частей значение, называемое гаммой шифра, поступает в цикл «32-З», его результат порязрядно складывается по модулю 2 с 64-разрядным блоком входных данных. Если последний меньше 64-х разрядов, то лишние разряды полученного значения отбрасываются. Полученное значение подаётся на выход. Если ещё имеются входящие данные, то действие повторяется: составленный из 32-разрядных частей блок преобразуется по частям и так далее.

- Режим гаммирования с обратной связью также принимает на вход данные любого размера и синхропосылку. Блок входных данных поразрядно складывается по модулю 2 с результатом преобразования в цикле «32-З» синхропосылки. Полученное значение подаётся на выход. Значение синхропосылки заменяется в случае зашифрования выходным блоком, а в случае расшифрования -- входным, то есть зашифрованным. Если последний блок входящих данных меньше 64 разрядов, то лишние разряды гаммы (выхода цикла «32-З») отбрасываются. Если ещё имеются входящие данные, то действие повторяется: из результата зашифрования заменённого значения образуется гамма шифра и т.д.

- Режим выработки имитовставки принимает на вход данные, размер которых составляет не меньше двух полных 64-разрядных блоков, а возвращает 64-разрядный блок данных, называемый имитовставкой. Временное 64-разрядное значение устанавливается в 0, далее, пока имеются входные данные, оно поразрядно складывается по модулю 2 с результатом выполнения цикла «16-З», на вход которого подаётся блок входных данных. После окончания входных данных временное значение возвращается как результат.

3. Выполненная работа (Исходный текст программ с комментариями)

Задание 1

Программа на Си.

С комментариями

#include <stdio.h>// Стандартная библиотека ввода-вывода

#include <math.h> //Стандартная библиотека математических функций

#include <stdlib.h> //Стандартная биб-ка для функции rnd()

#include <string.h> //Стандартная биб-ка для функции strcmp()

float stepen (float x, int y); //возведение основания х в степень у

long int fact(int n);// вычисление факториала

int main(){

int x0, i, n; //начальное значение значение х0, вспомогательная переменная //для цикла, количество слагаемых ряда Тейлора, Целочисленные переменные float t, s, x, s1; //сигма для интервала от x0-t lj x0+t, сумма ряда, из //интервала х, число е в степени х0, переменные двойной точности

float maxVal, minVal; //диапазон для определения значения х

char *str1, *str2; // для сравнения

double r,p; //дробная и целая часть числа

int decpnt, sign, ndig; //для преобразования числа в строку

const char * filename = "d:\\number.txt";//файл, в который запишем //полученный результат суммы ряда

const char * mode = "w";//режим записи в файл

FILE * file;//файловая переменная

printf("Введите начальное значение x0, сигма t, количество слагаемых в ряду n:"); // пояснение для следующей строки

scanf("%d%e%d",&x0,&t,&n); //ввели

// найдем х принадлежащее интервалу от х0-t до х0+t

maxVal=x0+t;

minVal=x0-t;

x=rand()%((int)maxVal-(int)minVal+1)+(int)minVal;//вычисление х генератором случайных чисел

printf("maxVal= %f minVal = %f x= %f\n", maxVal, minVal,x); //

printf("x0= %d t = %f n= %d\n", x0, t,n); // Форматный вывод %d или %i - //вывод значения как целого со знаком в формате DEC;

s=0; // обнулили сумму ряда

s1=stepen(exp(1),x0); // чтобы не вывызать функцию для //каждого слагаемого

for (i=0; i<=n; i++) // открываем цикл для вычисления суммы ряда

s+=s1/fact(i)*stepen(x-x0,i); // вычисление очередного слагаемого //ряда Тейлора по формуле (3) отчета

printf("число е в степени 1 =%g\n",exp(1));// проверяем //полученные результаты

printf("число е в степени х0 соответственно =%g\n", s1);

printf("сумма ряда s=%g\n",s);

printf("Введите точность вычисления");

scanf("%d",&ndig);//ввели

// преобразуем число в строку функцией ecvt

str1=ecvt(s1, ndig, &decpnt, &sign);// s1 в строку из ndig цифр; в //параметре decpt хранится отрицательное значение;указывает адресный //указатель sign

str2=ecvt(s, ndig, &decpnt, &sign);

printf("s1= %s\n, s= %s\n",str1, str2);

if (strcmp(str1,str2)==0)// сравниваем числа функцией strcmp

printf("Строки идентичны\n");

else printf ("Строки отличаются\n"); // возвращает отрицательное число, //нуль или положительное число для s < t, s == t или s > t, соответственно

// запись результат в файл

file=fopen (filename, mode);

fprintf(file, "%.10f", s1);

fclose(file);

return 0; // успешное завершение

}

float stepen (float x, int y) //возведение числа х в степень у

{ int i;

float p;

p=1;

for (i=1; i<=y; i++)

p=p*x;

return p;

}

long int fact(int n)

{if (n<0)// если n меньше 0

return 0;// возвращаем 0

if (n==0)// если n равен 0

return 1;// возращаем 1

else return n*fact(n-1); // делаем рекурсию

}

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

Задание 2

#include <stdio.h>// Стандартная библиотека ввода-вывода

#define N 10

int stack[N];// для хранения двоичного представления целой части числа

int in_stack = 0; // сколько элементов в стеке

int dr_arr[N];// массив для хранения двоичного //представления части вещественного числа после запятой до шифрования

int arr[N];// массив для хранения двоичного представления //мантиссы вещественного числа до шифрования

int i_arr;// количество цифр целой части числа в двоичном //представлении

int key[N]={1,0,1,0,1,0,1,0,1,0};//ключ шифрования

int Result[N];//результат шифрования двоичного //представления мантиссы вещественного числа

int Result1[N];//результат шифрования двоичного представления //части вещественного числа после запятой

int DecToBin(int n);//перевод из десятичной в двоичную сс //мантиссы (целой части числа)

float Dr_DecToBin(float n);//перевод из десятичной в двоичную сс части //числа после мантиссы

float stepen (float x, int y); //возведение основания х в степень у

int BinToDec(int arr_arr[], int l);//перевод из двоичной в //десятичную сс мантиссы (целой части числа)

float Dr_BinToDec();//перевод из двоичной в десятичную сс части //числа после мантиссы

int Code_(int arr_arr[], int l);//объявление функции шифрования

int main(){

int x, x1,i; // Целочисленные переменные

float y, y1; // вещественное число и его часть после мантиссы

int in_arr = 0;// Индекс массива arr[10]

int t;//работа НА СЕРВЕРЕ или на клиенте

const char * filename = "d:\\number.txt";//Спецификация файла (т.е. имя //файла и путь к нему)

const char * mode = "r";//Способ использования файла r - открыть //существующий файл для чтения;

FILE * file;//Логическое имя - указатель на требуемый файл

const char * filename1 = "d:\\code1.txt";//файл, в который запишем //полученный результат закодированной целой части суммы ряда

const char * filename2 = "d:\\code2.txt";//файл, в который запишем //полученный результат закодированной дробной части суммы ряда

const char * filename3 = "d:\\code3.txt";//файл, в который запишем //количество цифр целой части числа в двоичном представлении

const char * mode1 = "w";//режим записи в файл

printf("Обработка на клиенте - ввести 1, ввести 2 -на сервере: ");

scanf("%d",&t);//ввели

switch (t)

{

case 1:{

file=fopen (filename, mode); //открываю файл для считывания числа, //полученного по формуле ряда Тейлора

while (fscanf(file, "%10f", &y)!=EOF) // пока не конец файла считываю //число в переменную y

fclose(file);//закрыли файл

x= (int)y;//выделили целую часть числа, мантиссу

printf("Число %f получено при разложении в ряд Тейлора exp(x) имеет //целую часть =%d\n", y,x); // Форматный вывод

DecToBin(x);//вызов функции перевода целой части числа в //двоичную СС

printf("Двоичное представление целой части числа :");

i_arr=in_stack;// количество цифр целой части числа в //двоичном представлении

while(in_stack > 0){

printf("%d", pop());// чтение из стека двоичного представления //целой части числа

}

printf("\n");

y1=y-x;//выделение вещественной части числа

printf("часть после мантиссы =%f\n",y1);

Dr_DecToBin(y1);

printf("Двоичное представление дробной части числа после мантиссы :");

while(in_arr <N){

printf("%d", dr_arr[in_arr]);//вывод Двоичного представления //вещественной части числа

in_arr++;

}

printf("\n");

//шифрование мантиссы

//printf("Зашифрованая целая часть числа:\n");

Code_(arr,1);//Зашифрованая целая часть числа

// запись результата шифрования в файл

file=fopen (filename1, mode1);//открытие файла

for (i=0;i<i_arr; i++)//цикл для записи целой части числа в файл

{

fprintf(file, "%d\n", Result[i]);//запись целой части числа в файл

}

//fprintf(file, "\n");//перевод строки

fclose(file);//закрытие файла

//шифрование части следующей за мантиссой, т.е. дробной части числа

file=fopen (filename2, mode1);//открытие файла на запись

Code_(dr_arr, 2);//Зашифрованая дробная часть числа

// запись результата шифрования в файл

for (i=0;i<10; i++)//цикл для записи дробной части числа в файл

{

fprintf(file, "%d\n", Result1[i]);//запись дробной части числа в файл

}

fclose(file);//закрытие файла

file=fopen (filename3, mode1); //открываю файл для записи количество цифр //целой части числа в двоичном представлении

fprintf(file, "%d\n", i_arr);//запись количество цифр целой части числа в //двоичном представлении

fclose(file);//закрытие файла

printf("запись результата шифрования в файл\n");

break;

//завершение работы на клиенте

}

case 2:{

//считывание информации на сервере

printf("считывание из файла закодированного числа\n");

//считывание из файла целой части закодированного числа

i=0;

file=fopen (filename1, mode);

while (fscanf(file, "%d", &x)!=EOF)

{

Result[i]=x;

i++;

}

fclose(file);

//считывание из файла дробной части закодированного числа

i=0;

file=fopen (filename2, mode);

while (fscanf(file, "%d", &x)!=EOF)

{

Result1[i]=x;

i++;

}

fclose(file);

//считывание из файла количества цифр целой части числа в двоичном //представлении

i=0;

file=fopen (filename3, mode); //открываю файл для считывания количества //цифр целой части числа в двоичном представлении

while (fscanf(file, "%d", &i_arr)!=EOF)

{

i++;

}

fclose(file);

printf("проверка считывания закодированной целой части числа \n");

for (i=0;i<i_arr; i++)//вывод на экран раскодированной целой части числа

{

printf("%d",Result[i]);

}

printf("\n");

printf("проверка считывания закодированной дробной части числа\n");

for (i=0;i<10; i++)//вывод на экран раскодированной целой части числа

{

printf("%d",Result1[i]);

}

printf("\n");

//раскодирование дробной части числа

printf("раскодирование дробной части числа:\n");

Code_(Result1,2);

for (i=0;i<10; i++)//вывод на экран раскодированной дробной части числа

{

printf("%d",Result1[i]);

}

printf("\n");

//раскодирование целой части

printf("раскодирование целой части числа:\n");

Code_(Result,1);

for (i=0;i<i_arr; i++)//вывод на экран раскодированной целой части числа

{

printf("%d",Result[i]);

}

printf("\n");

//Перевод из двоичной СС в 10-ую СС

printf("Перевод целой части из 2-ого в 10-ое представление %d\n",BinToDec(Result,i_arr));

printf("Перевод части следующей за мантиссой из 2-ого в 10-ое представление %f\n",Dr_BinToDec(Result1));

return 0; // успешное завершение

}

int DecToBin(int n)//перевод из десятичной в двоичную сс мантиссы (целой части числа)

{

if (n >0)

{

stack[in_stack] = n%2;

in_stack++;

DecToBin(n/2);

}

return 0;

}

int BinToDec(int arr_arr[], int l)//перевод из двоичной в десятичную сс //мантиссы (целой части числа)

{

int summ=0,i;

for (i=l;i>=0;i--)

{

summ+=arr_arr[i] * stepen(2,i);

}

return summ;

}

/* Снять значение со стека */

int pop(){

if(in_stack == 0){

printf("Стек пуст, ошибка.\n");

return (-1);

}

in_stack--;

arr[in_stack]=stack[in_stack];

//printf("%d",arr[in_stack]);

return stack[in_stack];

}

float Dr_DecToBin(float n)//перевод вещественной части числа в //двоичную систему счисления

{

int i = 0;

while ((i<10)||(n==0))

{

n*=2;

if (n <1)

{

dr_arr[i] = 0;

}

else

{

dr_arr[i] = 1;

n-=1;

}

i++;

}

return 0;

}

float Dr_BinToDec(int arr_arr[])//перевод вещественной части числа в 10-//ую систему счисления

{

int i;

float summ1=0;

for(i=0;i<10;i++)

{

summ1+=arr_arr[i]/stepen (2,i);

}

return summ1;

}

float stepen (float x, int y) //возведение числа х в степень у

{ int i;

float p;

p=1;

for (i=1; i<=y; i++)

p*=x;

return p;

}

int Code_(int arr_arr[], int l)

{

int i;

{

for (i=0;i<10; i++)

{

switch (l)

{

case 1: //целой части числа

{Result[i]=key[i]^arr_arr[i];

};

case 2: //дробной части числа

{Result1[i]=key[i]^arr_arr[i];

};

//http://dfe.petrsu.ru/koi/posob/c/c.htm#g1.2

//http://www.helloworld.ru/texts/comp/lang/c/c6/index2.htm

//http://citforum.ru/programming/c/dir.shtml

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

Выводы

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

Таким образом, при преобразовании числа с большей точностью к числу с меньшей (c большей разрядностью к меньшей, длинного числа к короткому), возможна потеря точности.

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

2) К достоинствам XOR-шифрования относятся его простота и «естественность» реализации на ЭВМ, однако этот метод обладает слабой стойкостью (в случае, если ключи не являются абсолютно случайными).

Интересно, что в свое время данный алгоритм использовался Microsoft для шифрования содержимого документов в Office 95.

3) Вычисления, производимые над вещественными числами, не точны, т.к. компилятор использует всю память, отведенную для числа, а не только те цифры, которые получены. Демонстрационный пример ниже.

В строке 5 число, которое надо перевести в двоичную СС. В строке 8 выводим его значение на экран. Оно отличается от предыдущего. Поэтому значение, полученное при переводе вещественной части числа из 2-ой СС в 10-ую отличается. Попытка перевести вещественную часть числа в строку также этот же результат.

Основная литература

1. Дэвид Гриффитс, Дон Гриффитс - Head First C / Изучаем программирование на C.

2. Учебное пособие Высшая математика для экономистов Практикум Под редакцией Наума Шевелевича Кремера

3. Васильева И.Н. Информационные технологии и защита информации : учеб. пособие / И.Н. Васильева. Е.В. Стельмаиюнок - СПб -СПбГИЭУ. 2011.-271 с.

4. Шапошникова С. В. Особенности языка С./ Учебное пособие - Лаборатория юного линуксоида, май 2012

5. http://dfe.petrsu.ru/koi/posob/c/c.htm#g1.2

6. http://www.helloworld.ru/texts/comp/lang/c/c6/index2.htm

7. http://citforum.ru/programming/c/dir.shtml

Размещено на Allbest.ru


Подобные документы

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

    учебное пособие [1,7 M], добавлен 26.10.2013

  • Delphi - среда быстрой разработки, в которой в качестве языка программирования используется типизированный объектно-ориентированный язык Delphi. Варианты программного пакета. Особенности работы, вид экрана после запуска. Описание структуры программы.

    курсовая работа [1,3 M], добавлен 25.11.2014

  • Знакомство с этапами разработки трёх приложений для системы семейства Linux с использованием языка программирования С++. Анализ особенностей операционной системы Ubuntu 12.10. Характеристика способов тестирования команд с помощью стандартных средств.

    контрольная работа [732,1 K], добавлен 06.08.2013

  • Интегрированная среда разработки Delphi и элементы, входящие в ее состав. Математическая модель, алгоритм решения и его свойства. Описание операторов, процедур, функций и методов. Создание приложений по аналитической геометрии и теоретической механике.

    курсовая работа [1,8 M], добавлен 26.05.2010

  • Основные приемы работы в среде программирования Delphi. Особенности технологии создания простейших приложений. Работа с компонентами среды разработки приложений. Ввод, редактирование, выбор и вывод информации. Аспекты использования структуры ветвления.

    методичка [619,9 K], добавлен 17.11.2011

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

    презентация [396,3 K], добавлен 12.11.2012

  • Разработка игры "Угадай персонажа", ее суть и содержание. Запоминание новых персонажей и вопросов, коррекция базы данных. Использование языка программирования С++ и среды разработки Microsoft Visual Studio 2010. Алгоритмы и методы, структура программы.

    курсовая работа [571,9 K], добавлен 14.07.2012

  • Разработка программного продукта с помощью языка программирования Visual Basic. Описание интерфейса пользователя и возможностей программы. Исходный код основных модулей. Программа, демонстрирующая основные возможности диаграмм и среды Visual Basic.

    контрольная работа [989,9 K], добавлен 29.03.2011

  • Анализ принципа создания приложений для Linux. Состав стандартного проекта CLX, его иерархия классов, свойства, методы, отличия от VCL. Особенности кроссплатформенного программирования, а также дополнительные возможности кроссплатформенных приложений.

    курсовая работа [107,2 K], добавлен 25.12.2009

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

    курсовая работа [33,7 K], добавлен 12.01.2015

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.