
Лаба 6 / Лабораторная_работа_№6_Токарев_0421
.docxМИНОБРНАУКИ РОССИИ
Санкт-Петербургский государственный
электротехнический университет
«ЛЭТИ» им. В.И. Ульянова (Ленина)
Кафедра Электротехнологической и преобразовательной техники
отчет
по лабораторной работе № 6
по дисциплине «Информационные технологии»
Тема: Функции
Студент гр. 0421 |
|
Токарев А.А. |
Преподаватель |
|
Чмиленко Ф.В. |
Санкт-Петербург
2021
Цель работы: получение навыков разработки пользовательских функций и освоение модульного принципа программирования
Задания:
Объявление, определение и использование функций
Модульный принцип программирования
Глобальные переменные
Доступ к глобальным переменным в разных модулях
Передача параметров по ссылке
Передача и возврат сложных объектов
Передача указателя в функцию
Дополнительные задания:
Применение лямбда-функций
Ход работы:
Задание 1.
Создадим программу, состоящую из одного модуля, в которой определим функцию Volume, которая получает на вход радиус основания конуса и его высоту, а возвращает объем конуса:
#include <stdio.h>
#include <iostream>
using namespace std;
double Volume (double R, double H);
int main()
{
system("chcp 1251");
system("cls");
double r,h;
cout << "Введите радиус основания конуса: " << endl;
cin >> r;
cout << "Введите высоту конуса: " << endl;
cin >> h;
double v = Volume(r,h);
cout << "Объем конуса с радиусом " << r << " и высотой " << h << " равен " << v << endl;
system("pause");
return 0;
}
double Volume (double R, double H)
{
double v = (3.14 * R * R * H) / 3;
return v;
}
Рисунок 1 – Результат работы программы по нахождению объема конуса
Закомментируем объявление функции и скомпилируем программу заново. Компилятор выдаст ошибку о том, что функция не объявлена:
Рисунок 2 – Ошибка, возникающая при закомментировании объявления функции
Перенесем определение функции Volume выше функции main. Программа будет работать также, как и при определении функции Volume до функции main. Из этого можно сделать вывод о том, что объявлять функции можно как до, так и после функции main.
Задание 2.
Создадим программу, аналогичную предыдущей, но состоящую из двух модулей: Lab6_2.cpp и Volume.cpp. Содержание Lab6_2.cpp:
#include <stdio.h>
#include <iostream>
#include "Volume.h"
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
double r,h;
cout << "Введите радиус основания конуса: " << endl;
cin >> r;
cout << "Введите высоту конуса: " << endl;
cin >> h;
double v = Volume(r,h);
cout << "Объем конуса с радиусом " << r << " и высотой " << h << " равен " << v << endl;
system("pause");
return 0;
}
Содержание Volume.cpp:
double Volume (double R, double H)
{
double v = (3.14 * R * R * H) / 3;
return v;
}
Для модуля Volume.cpp также понадобится заголовочный файл Volume.h:
#pragma once
double Volume (double R, double H);
Рисунок 3 – Результат работы программы по определению объема конуса, состоящей из нескольких модулей
Задание 3.
Доработаем программу, разработанную в задании 1. В программе, сразу после директив препроцессора, объявим глобальную переменную, double PI = 3.14 и сразу инициализируем ее. Далее, заменим функции Volume значение константы в явном виде на глобальную переменную:
#include <stdio.h>
#include <iostream>
using namespace std;
double Volume (double R, double H);
double PI = 3.14;
double Volume (double R, double H)
{
double v = (PI * R * R * H) / 3;
return v;
}
int main()
{
system("chcp 1251");
system("cls");
double r,h;
cout << "Введите радиус основания конуса: " << endl;
cin >> r;
cout << "Введите высоту конуса: " << endl;
cin >> h;
double v = Volume(r,h);
cout << "Объем конуса с радиусом " << r << " и высотой " << h << " равен " << v << endl;
system("pause");
return 0;
}
Рисунок 4 – Результат работы программы после замены значения константы 3.14 в функции Volume на глобальную переменную PI
Проведем исследование, присвоив внутри функции main значение глобальной переменной PI = 6.28:
#include <stdio.h>
#include <iostream>
using namespace std;
double Volume (double R, double H);
double PI = 3.14;
int main()
{
system("chcp 1251");
system("cls");
double r,h;
PI = 6.28;
cout << "Введите радиус основания конуса: " << endl;
cin >> r;
cout << "Введите высоту конуса: " << endl;
cin >> h;
double v = Volume(r,h);
cout << "Объем конуса с радиусом " << r << " и высотой " << h << " равен " << v << endl;
system("pause");
return 0;
}
double Volume (double R, double H)
{
double v = (PI * R * R * H) / 3;
return v;
}
Рисунок 5 – Результат работы программы после присваивания глобальной переменной PI внутри функции main значения 6.28
Как можно видеть, переменная изменила свое значение, т.к. это повлияло на итоговое значение объема конуса. Добавим еще две глобальные переменные int a и float b без инициализации и выведем их значение в функции main:
#include <stdio.h>
#include <iostream>
using namespace std;
double Volume (double R, double H);
double PI = 3.14;
int a;
float b;
int main()
{
system("chcp 1251");
system("cls");
double r,h;
cout << "Введите радиус основания конуса: " << endl;
cin >> r;
cout << "Введите высоту конуса: " << endl;
cin >> h;
double v = Volume(r,h);
cout << "Объем конуса с радиусом " << r << " и высотой " << h << " равен " << v << endl;
cout << "Значение глобальной переменной а равно " << a << endl;
cout << "Значение глобальной переменной b равно " << b << endl;
system("pause");
return 0;
}
double Volume (double R, double H)
{
double v = (PI * R * R * H) / 3;
return v;
}
Рисунок 6 – Результат работы программы по определнию объема конуса, с добавленным выводом значений двух неинициализированных глобальных переменных
Как можно видеть, неинициализированные глобальные переменные по умолчанию имеют значение 0. Глобальные переменные будут отличаться от локальных тем, что доступ к ним имеет любая функция в программе, т.е. они имеют глобальную область видимости.
Задание 4.
Доработаем программу, созданную в задании 2, объявив глобальную переменную PI во всех модулях, а определив только в одном. Таким образом Lab6_4.cpp будет иметь следующее содержание:
#include <stdio.h>
#include <iostream>
#include "Volume.h"
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
double r,h;
cout << "Введите радиус основания конуса: " << endl;
cin >> r;
cout << "Введите высоту конуса: " << endl;
cin >> h;
double v = Volume(r,h);
cout << "Объем конуса с радиусом " << r << " и высотой " << h << " равен " << v << endl;
system("pause");
return 0;
}
Содержание Volume.cpp:
#define VOLUME
#include "Volume.h"
double Volume (double R, double H)
{
double v = (PI * R * R * H) / 3;
return v;
}
Содержание Volume.h:
#pragma once
#ifdef VOLUME
double PI = 3.14;
#else
extern double PI;
#endif
double Volume (double R, double H);
Рисунок 7 – Результат работы программы, в которой глобальная переменная PI используется в нескольких модулях
Задание 5.
Разработаем функцию типа void, которая получает по ссылке две переменные типа double и меняет их местами, если первая переменная больше второй. Содержание модуля Lab6_5.cpp:
#include <stdio.h>
#include <iostream>
#include "Swap.h"
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
double a,b;
cout << "Введите первое число: " << endl;
cin >> a;
cout << "Введите второе число: " << endl;
cin >> b;
Swap(a, b);
cout << "Первое число равно " << a << endl;
cout << "Второе число равно " << b << endl;
system("pause");
return 0;
}
Содержание модуля Swap.cpp:
#include "Swap.h"
void Swap (double &a, double &b)
{
double c = b;
if (a > b)
{
b = a;
a = c;
}
}
Содержание модуля Swap.h:
#pragma once
void Swap (double &a, double &b);
Рисунок 8 – Результат работы программы по перемене значений двух чисел местами, в случае, если первое число больше второго
Задание 6.
Разработаем программу, в которой будем использовать функцию, которая получает по ссылке две переменные пользовательского типа – комплексное число MyComplex – и складывает их.
Программа получает с клавиатуры значение мнимой и вещественной частей двух комплексных чисел и с помощью функции Complex складывает их и затем выводит с учетом знака. Содержание модуля Lab6_6.cpp:
#include <stdio.h>
#include <iostream>
#include "MyComplex.h"
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
MyComplex Complex_1;
MyComplex Complex_2;
MyComplex Complex_3;
cout << "Введите вещественную часть первого комплексного числа: " << endl;
cin >> Complex_1.real;
cout << "Введите мнимую часть первого комплексного числа: " << endl;
cin >> Complex_1.imag;
cout << "Введите вещественную часть второго комплексного числа: " << endl;
cin >> Complex_2.real;
cout << "Введите мнимую часть второго комплексного числа: " << endl;
cin >> Complex_2.imag;
Complex_3 = Complex(Complex_1, Complex_2);
cout << "Результат сложения двух комплексных чисел равен " << Complex_3.real << showpos << Complex_3.imag << "i" << endl;//вывод вещественной и мнимой части комплексного числа с учетом знака
system("pause");
return 0;
}
Содержание модуля MyComplex.h:
#pragma once
struct MyComplex Complex(MyComplex &Complex_1, MyComplex &Complex_2);
struct MyComplex
{
double real,imag;
};
Содержание модуля MyComplex.cpp:
#include "MyComplex.h"
struct MyComplex Complex(MyComplex &Complex_1, MyComplex &Complex_2)
{
struct MyComplex Answer;
Answer.real = Complex_1.real + Complex_2.real;
Answer.imag = Complex_1.imag + Complex_2.imag;
return Answer;
}
Рисунок 9 – Результат работы программы по сложению двух комплексных чисел
Задание 7.
Разработаем программу, в которой будем использовать две функции для работы со строками в стиле С. Функция Count будет получать первым параметром указатель на строку символов, а вторым – символ и подсчитывать количество этих символов в строке. Функция Place будет получать первым параметром указатель на строку символов, а вторым – символ и возвращать, когда он встречается в заданной строке в первый раз. Содержание модуля Lab6_7.cpp:
#include <stdio.h>
#include <iostream>
#include "Count.h"
#include "Place.h"
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
char *str = new char[20];// выделение памяти под строку из 20 символов
char ch;
int ans_1, ans_2;
cout << "Введите строку для исследования: " << endl;
cin >> str;
cout << "Введите символ для поиска: " << endl;
cin >> ch;
ans_1 = Count(str, ch);
ans_2 = Place(str, ch);
cout << "Количество символов " << ch << " в введенной строке равно: " << ans_1 << endl;
cout << "Символ " << ch << " первый раз встречается в введенной строке под порядковым номером " << ans_2 << endl;
system("pause");
delete []str; // освобождение памяти, выделенной под строку
return 0;
}
Содержание модуля Count.cpp:
#include "Count.h"
int Count(char *str, char ch)
{
int i = 0;
int cnt = 0;
while (str[i] != '\0')
{
if(str[i] == ch)
{
cnt++;
}
i++;
}
return cnt;
}
Содержание модуля Count.h:
#pragma once
int Count(char *str, char ch);
Содержание модуля Place.cpp:
#include "Place.h"
int Place(char *str, char ch)
{
int i = 0;
int cnt = 0;
while (str[i] != '\0')
{
if(str[i] == ch)
{
cnt = i + 1;
break;
}
else
{
cnt = 0;
}
i++;
}
return cnt;
}
Содержание модуля Place.h:
#pragma once
int Place(char *str, char ch);
Рисунок 10 – Результат работы программы, демонстрирующей работу с указателями на строку, передающимися в функции
Создадим новую программу, в которой разработаем функцию Sred, которая будет получать указатель на одномерный массив и размер массива (по значению) и вычислять его среднее значение. Содержание модуля Lab6_7_1.cpp:
#include <stdio.h>
#include <iostream>
#include "Sred.h"
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
int size;
cout << "Введите размер массива: " << endl;
cin >> size;
double *mas = new double[size];// выделение памяти под массив
double ans;
cout << "Введите массив для исследования: " << endl;
for (int i = 0; i < size; i++)
{
cin >> mas[i];
}
ans = Sred(mas, size);
cout << "Среднее значение массива равно: " << ans << endl;
system("pause");
delete []mas; // освобождение памяти, выделенной под массив
return 0;
}
Содержание модуля Sred.cpp:
#include "Sred.h"
double Sred(double *mas, int size)
{
double sum = 0;
for (int i = 0; i < size; i++)
{
sum += mas[i];
}
return sum / size;
}
Содержание модуля Sred.h:
#pragma once
double Sred(double *mas, int size);
Рисунок 11 – Результат работы программы,демонстрирующей работу с указателями на массив, передающимися в функции
Дополнительное задание:
Переделаем программу, созданную в предыдущем задании так, чтобы в ней использовались лямбда-функции:
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
system("chcp 1251");
system("cls");
int size;
auto lambda_sred = [](double *mas, int size) //применение лямбда-функции
{
double sum = 0;
for (int i = 0; i < size; i++)
{
sum += mas[i];
}
return sum / size;
};
cout << "Введите размер массива: " << endl;
cin >> size;
double *mas = new double[size];// выделение памяти под массив
double ans;
cout << "Введите массив для исследования: " << endl;
for (int i = 0; i < size; i++)
{
cin >> mas[i];
}
cout << "Среднее значение исследуемого массива равно: " << lambda_sred(mas, size) << endl;
system("pause");
delete []mas; // освобождение памяти, выделенной под массив
return 0;
}
Выводы:
В данной лабораторной работе была изучена работа с функциями в языке С++. Были приведены примеры как объявления и определения функции в одном файле с функцией main, так и в составе include-файлов, их подключение к основному модулю.
Также были изучены глобальные переменные, которые задаются как в основном модуле, так и в подключаемых. Их основным отличием от локальных является доступ к ним из любой части программы.
Чтобы получить доступ к глобальным переменным в нескольких модулях, их нужно определить в заголовочном файле и включить его в этих модулях.
Помимо этого, в лабораторной работе были изучены передача параметра по ссылке в функцию. Удобно использовать передачу по ссылке в случае, если нам нужно изменить значение передаваемого аргумента, либо, если объект, который мы передаем в функцию (например, структура), является большим и занимает много места в памяти. С помощью передачи параметра по ссылке мы можем сэкономить память.
Также была изучена передача указателя в функцию. С помощью передачи указателя в функцию, функция может работать с массивами.
Дополнительно было продемонстрировано применение лямбда-функций, которые упрощают синтаксис программы и улучшают читаемость кода.
В большей части заданий был применен модульный принцип программирования, который имеет массу преимуществ. Он улучшает читаемость кода, упрощает поиск ошибок в коде, позволяет представить программу в более структурированном виде.