Министерство образования Республики Беларусь БЕЛОРУССКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ИНФОРМАТИКИ И РАДИОЭЛЕКТРОНИКИ Кафедра экономической информатики Отчет По лабораторной работе №2 на тему “ОРГАНИЗАЦИЯ ВВОДА/ВЫВОДА, ДИНАМИЧЕСКОЕ ВЫДЕЛЕНИЕ ПАМЯТИ В ЯЗЫКЕ С++” Выполнила: студентка группы 072304 Микшас Полина Проверила: Григорьева Юлия Юрьевна Минск, 2021 ЦЕЛЬ РАБОТЫ: изучить организацию ввода/вывода данных и работу с динамической памятью при программировании алгоритмов на языке С++. ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ: В языке С++ ввод и вывод данных производится потоками байт. Поток (stream) – общий логический интерфейс с различными устройствами, составляющими компьютер и подключаемые к нему. При операциях ввода байты направляются от устройства в основную память (т. е. поток потребляет информацию). В операциях вывода – наоборот (т.е. поток синтезирует, создает информацию и направляет её к устройствам вывода). Существует два типа потоков: текстовый и бинарный. Текстовый поток используется для ввода-вывода символов. При этом могут происходить некоторые преобразования символов, следовательно, может не быть взаимнооднозначного соответствия между тем, что посылается в поток и тем, что действительно записывается в файл. Двоичный поток можно использовать с данными любого типа, при этом преобразования символов не выполняется, и между тем, что посылается в поток, и тем, что содержится в файле, существует взаимно-однозначное соответствие. В языке С++ имеется четыре встроенных потока (связанных с ними объекта), обеспечивающих ввод и вывод информации и определенных в заголовочном файле iostream (Input/Output Stream, «поток ввода-вывода») как в файле stdio.h в языке С. Эти потоки открываются автоматически, как только программа начинает выполняться. В файле iostream перегружаются два оператора побитового сдвига: << - поместить в выходной поток; >> - считать из входного потока. В файле iostream используются объекты, которые являются частью стандартной библиотеки C++ и частью стандартного пространства имён — std: cout//стандартный поток вывода (экран), cin//стандартный поток ввода (клавиатура), cerr//стандартный поток диагностики (ошибки) без буферизации, clog//стандартный поток диагностики (ошибки) с буферизацией. Для ввода информации с клавиатуры используется объект cin. При вводе необходимо, чтобы данные вводились в соответствии с форматом переменных. Объект cout позволяет выводить информацию на стандартное устройство вывода – экран. Идентификатор endl называется манипулятором. Он очищает поток и добавляет новую строку. Для управления выводом информации в языке С++ используются манипуляторы. Манипуляторы позволяют встраивать 2 инструкции форматирования в выражение ввода-вывода. Для использования манипуляторов необходим заголовочный файл iomanip. Память можно выделять динамически, т.е. размещать в свободной памяти (free store). Свободная память – это предоставляемая системой область памяти для объектов, время жизни которых устанавливается программистом. В С++ для операций выделения и освобождения памяти используются встроенные операторы new и delete. Приложение может распределять (allocate, т.е. резервировать (reserve) области памяти) и возвращать (deallocate, т.е. освобождать (release) области памяти). Оператор new имеет один операнд и две формы записи. Если не освободить зарезервированную память после прекращения ее использования, то она так и останется зарезервированной для приложения даже после его завершения. Это в свою очередь, сократит объем системной памяти, доступной для использования другими приложениями, а возможно, даже замедлит выполнение приложений. Это называется утечкой памяти, и ее следует избегать. Оператор delete не может быть вызван «для никакого адреса», содержащегося в указателе, кроме тех, и только тех, которые были возвращены оператором new и еще не были освобождены оператором delete. Несмотря на то, что указатели могут содержать допустимые адреса, их нельзя освобождать при помощи оператора delete, если они не были возвращены вызовом оператора new. ВАРИАНТ ЗАДАНИЯ: 17. cоздать класс Array для работы с массивами (как целочисленными, так и дробными). Заполнить массив случайными числами. Уменьшить все элементы массива на десять, если их значение больше десяти. Например, в ячейке хранится число 12, тогда в результате преобразования получим 12 – 10 = 2. Память под массив выделять динамически. Размер массива указывает пользователь. Необходимо обязательно освобождать память, выделенную под массив. Написать свой манипулятор, выводящий содержимое массива в табличном виде. ВЫПОЛНЕНИЕ: Array.h: #pragma once #include <iostream> #include <iomanip> #include <time.h> using namespace std; class Array { int n = 0; int m = 0; 3 int** arrInt = NULL; double** arrDouble = NULL; public: Array(int n, int m, bool arrIsInt); ~Array(); void initWithRandomValues(bool arrIsInt); void reduceItemsBy10(bool arrIsInt); void printArrToConsole(bool arrIsInt); }; void Check(int& value, int lim1, int lim2); ostream& printLine(ostream& stream); ostream& printContent(ostream& stream); Array.cpp: #include "Array.h" Array::Array(int n, int m, bool arrIsInt) { this->n = n; this->m = m; if (arrIsInt) { this->arrInt = new int* [n]; for (int i = 0; i < n; i++) { arrInt[i] = new int[m]; } this->initWithRandomValues(arrInt); } else { this->arrDouble = new double* [n]; for (int i = 0; i < n; i++) { arrDouble[i] = new double[m]; } this->initWithRandomValues(arrInt); } } Array::~Array() { for (int i = 0; i < this->n; i++) delete[] arrInt[i]; delete[] arrInt; for (int i = 0; i < this->n; i++) delete[] arrDouble[i]; delete[] arrDouble; } void Array::initWithRandomValues(bool arrIsInt) { srand(time(NULL)); if (arrIsInt) { for (int i = 0; i < this->n; i++) { 4 for (int j = 0; j < this->m; j++) { arrInt[i][j] = rand() % 20 + 1; } } } else { for (int i = 0; i < this->n; i++) { for (int j = 0; j < this->m; j++) { arrDouble[i][j] = (rand() % 200 + 1) * 0.1; } } } } void Array::reduceItemsBy10(bool arrIsInt) { if (arrIsInt) { for (int i = 0; i < this->n; i++) { for (int j = 0; j < this->m; j++) { if (arrInt[i][j] > 10) arrInt[i][j] -= 10; } } } else { for (int i = 0; i < this->n; i++) { for (int j = 0; j < this->m; j++) { if (arrDouble[i][j] > 10) arrDouble[i][j] -= 10; } } } } void Array::printArrToConsole(bool arrIsInt) { if (arrIsInt) { cout << "+"; for (int j = 0; j < this->m; j++) { cout << printLine; } cout << endl; for (int i = 0; i < this->n; i++) { for (int j = 0; j < this->m; j++) { cout << printContent << arrInt[i][j]; } cout << "|" << endl; cout << "+"; for (int j = 0; j < this->m; j++) { cout << printLine; } cout << endl; 5 } } else { cout << "+"; for (int j = 0; j < this->m; j++) { cout << printLine; } cout << endl; for (int i = 0; i < this->n; i++) { for (int j = 0; j < this->m; j++) { cout << printContent << arrDouble[i][j]; } cout << "|" << endl; cout << "+"; for (int j = 0; j < this->m; j++) { cout << printLine; } cout << endl; } } } void Check(int& value, int lim1, int lim2) { while (cin.fail() || (value < lim1) || (value > lim2)) { cin.clear(); cin.ignore(256, '\n'); cout << "Incorrect input! Try again!" << endl; cin >> value; } } ostream& printLine(ostream& stream) { stream << "----+"; return stream; } ostream& printContent(ostream& stream) { stream.setf(ios::right); stream << setprecision(4); stream << "|" << setw(4) << setfill(' '); return stream; } Laba_2.cpp: #include "Array.h" int main() { bool arrIsInt = false; bool toEnd = false; bool arrIsCreated = false; int n = 0, m = 0; Array* arr = NULL; 6 while (!toEnd) { cout << cout << cout << cout << cout << "===== Main Menu =====" << endl; "1. Initialize array" << endl; "2. Reduce items of array by 10" << endl; "3. Show array" << endl; "4. Exit" << endl; int mainMenuInput = 0; cin >> mainMenuInput; Check(mainMenuInput, 1, 4); system("cls"); switch (mainMenuInput) { case 1: { cout << "Select array type" << endl; cout << "1. float" << endl; cout << "2. integer" << endl; int typeOfArr; cin >> typeOfArr; Check(typeOfArr, 1, 2); arrIsInt = --typeOfArr; system("cls"); cout << "Enter number of rows: " << endl; cin >> n; Check(n, 1, 23); cout << "Enter number of columns: " << endl; cin >> m; Check(m, 1, 23); system("cls"); arr = new Array(n, m, arrIsInt); arrIsCreated = true; cout << "Array is successfully created!" << endl << endl; break; } case 2: { if (arrIsCreated) { arr->reduceItemsBy10(arrIsInt); arr->printArrToConsole(arrIsInt); } else cout << "Array isn't created!" << endl << endl; 7 break; } case 3: { if (arrIsCreated) { arr->printArrToConsole(arrIsInt); } else cout << "Array isn't created!" << endl << endl; break; } case 4: { toEnd = true; break; } } } return 0; } 8 9 ВЫВОДЫ: в данной лабораторной работе я изучила организацию ввода/вывода данных и работу с динамической памятью при программировании алгоритмов на языке С++. 10