1. Цель работы: Приобретение навыков работы с динамическими массивами памяти.
Домашнее задание
2.1 Изучите материал по темам: массивы и указатели, многомерные массивы, массивы указателей, динамические массивы.
2.2 Приведите примеры описания, определения и инициализации статического одномерного и многомерного массивов, массива указателей, динамического массива.
Лабораторное задание.
3.1 Набрать программу № 1
// Программа №1
#include "stdafx.h"
#include <iostream>
using namespace std;
void main(){
int n;
cout<<"\n Input n =";
cin>>n;
double **matr;
matr = new double* [n];
if(matr == NULL) {
cout<<"\n He создан динамический массив";
return;
}
for(int i = 0; i < n; i++){
matr[i] = new double [n];
if(matr[i]== NULL) {
cout<<"\n He создан динамический массив";
return;
}
for(int j = 0; j < n;j++)
if(i!= j) matr [i][j] = 0;
else matr[i][j] = 1;
}
for(int i = 0; i < n; i++){
cout<<"\n string "<<":"<<i;
for(int j = 0;j< n; j++)
cout<<"\t"<<matr[i][j];
}
for(int i=0; i < n; i++) delete matr[i];
delete[]matr;
getchar();getchar();
}
3.2 Отладить программу №1 (Эта программа является примером создания двухмерного динамического массива.)
3.3 Написать функцию, реализующие перемножение, сложение, вычитание двух матриц. Эти функции должны принимать указатели (или ссылки) на матрицы и возвращать указатель на результирующую матрицу.
3.4 Написать функцию транспонирования матрицы.
3.5 Написать алгоритм и функцию решения системы линейных алгебраических уравнений методом Гаусса.(*)
3.6 Ответить на контрольные вопросы.
3.6 Написать отчет.
Содержание отчета
4.1 Титульный лист. Домашнее задание.
4.2 Тексты программ, написанных при выполнении 3.3 и 3.4 пунктов лабораторного задания.
Контрольные вопросы
5.1 Операторы и функции динамического выделения памяти new, delete, malloc(), free(). Привести примеры использования этих операторов и функций.
5.2 В чем разница между динамическим массивом и статическим массивом памяти.
5.3 Напишите функцию, принимающую в качестве параметров указатели (или ссылки) на две строки и возвращающую указатель на новую строку, являющуюся результатом слияния этих строк.
5.4 Приведите примеры передачи в функцию как параметра динамического и статического массива памяти.
5.5 Напишите функцию, принимающую указатель (или ссылку) на матрицу в качестве параметра и возвращающую указатель на копию этой матрицы, повернутую по часовой стрелки.
5.6 Напишите функцию, принимающую указатель (или ссылку) на матрицу в качестве параметра и возвращающую указатель на копию этой матрицы, повернутую против часовой стрелки.
5.7 Напишите функцию, принимающую указатель (или ссылку) на матрицу в качестве параметра и возвращающую указатель на копию этой матрицы, транспонированную относительно не главной диагонали.
5.8 Напишите функцию, принимающую указатель (или ссылку) на матрицу в качестве параметра и возвращающую указатель на копию этой матрицы, повернутую зеркально вниз.
5.9 Напишите функцию, принимающую указатель (или ссылку) на матрицу в качестве параметра и возвращающую указатель на копию этой матрицы, повернутую зеркально вправо.
5.10 Перечислите способы передачи параметров в функцию. Приведите примеры.
Лабораторная работа №7
Линейные списки и структурированные данные.
1. Цель работы: Получение навыка работы со структурами и линейными списками.
Домашнее задание
1. Разработать алгоритм и пояснить на рисунках последовательность действий, которую необходимо выполнить для того, чтобы вставить объект в начало, в конец, в середину или удалить из двухсвязного списка.
Рис 1 Двухсвязный список
Р(prior) - указатель на предыдущий элемент списка; N(next) - указатель на следующий элемент списка; begin - указатель на начало списка; О - объект или указатель на объект, вставленный в список.
2. Изучить текст программы №1.
Лабораторное задание
1. Набрать программу №1
//Программа №1
#include "stdafx.h"
#include<string.h>
#include<iostream>
using namespace std;
struct card { //Определение структурного типа для книги
char *author; // Ф.И.О. автора
char *title; // Заголовок книги
char *city; // Место издания
char *firm; // Издательство
int year; // Год издания
int pages; // Количество страниц
};
//Функция печати сведений о книге:
void printbook(card& car)
{ static int count = 0;
cout<<"\n"<< ++count <<". "<<car.author;
cout<<" "<<car.title<<".- "<<car.city;
cout<<": "<<car.firm<<", ";
cout<<"\n"<<car.year<<".- "<<car.pages<<" c.";
}
struct record { //Структурный тип для элемента списка (1)
card book;
record *prior;
record *next;
};
//Исходные данные о книгах:
card books[] = { //Инициализация массива структур: (2)
{ "Wiener R.S.", "Turbo C",
"M", "ST",1991, 384},
{ "Stroustrup B.","Langvige C",
"kiev","DiaSoft",1993, 560},
{ "Turbo C++.", "For programm",
"M","INTKV",1991,394},
{ "Limppman S.B.","C++ for new",
"M","GELION",1993,496}
};
void main()
{ record *begin = NULL, //Указатель начала списка (3)
*last = NULL, //Указатель на очередную запись
*list; //Указатель на элементы списка
// n-количество записей в списке:
int n = sizeof(books)/sizeof(books[0]);
// Цикл обработки исходных записей о книгах:
for (int i=0;i<n; i++)
{//Создать новую запись(элемент списка): (4)
last = new(record);
//Занести сведения о книге в новую запись:
(*last).book.author = books[i].author;
(*last).book.title = books[i].title;
last->book.city = books[i].city;
last->book.firm = books[i].firm;
last->book.year = books[i].year;
last->book.pages = books[i].pages;
//Включить запись в список(установить связи):
if (begin == NULL) //Списка ещё нет (5)
{last->prior = NULL;
begin = last;
last->next = NULL;
}
else
{ //Список уже существует
list = begin;
//Цикл просмотра цикла - поиск места для
//новой записи:
while (list) //(6)
{if (strcmp(last->book.author,
list->book.author) < 0)
{//Вставить новую запись перед list:
if (begin == list)
{//Начало списка: (7)
last->prior = NULL;
begin = last;
}
else
{//Вставить между записями: (8)
list->prior->next = last;
last->prior = list->prior;
}
list->prior = last;
last->next = list;
//Выйти из цикла просмотра списка:
break;
}
if (list->next == NULL)
{//Включить запись в конец цикла: (9)
last->next = NULL;
last->prior = list;
list->next = last;
//Выйти из цикла просмотра списка:
break;
}
//Перейти к следующему элементу списка:
list = list->next;
}//Конец цикла просмотра списка
//(Поиск места для новой записи)
} //Включение записи выполнено
} //Конец цикла обработки исходных данных
//Печать в алфавитном порядке библиографического списка:
list = begin; // (10)
cout<<"\n";
while (list) {
printbook(list->book);
list = list->next;
}
getchar();
}
2. Отладить программу №1 (Программа является примером использования двухсвязного линейного списка.)
3. Написать функции вставки в начало, в середину и в конец списка объекта типа card, а также функции удаления и доступа (по индексу) к объекту типа card в списке.
4. Модифицировать программу №1 так, чтобы можно было с клавиатуры вводить и удалять записи в списке.
5. Модифицировать функции списка так, чтобы ими можно было пользоваться для организации списка произвольного типа объектов *.
6. Написать отчет.
Содержание отчета.
1. Титульный лист. Домашнее задание
2. Тексты функций написанных при выполнении пунктов 3,4 и 5 лабораторного задания.
Контрольные вопросы
1. Что такое стек, очередь, дек?
2. Чем отличается указатель типа void* от указателей другого типа type*?
3. Расскажите, что такое структура и объединение? Приведите примеры определения, инициализации и описания структуры и объединения.
4. Как получить доступ к полю структуры и объединения? Какое множество операций определено над структурой/объединением и полями структуры/объединения?
5. Приведите примеры использования оператора typedef со стандартными типами данных, со структурами и объединениями.
6. Битовые поля структур и объединений, назначение, способ определения, множество операций, определенных над битовыми полями.
7. Написать функции реализующие стек целых чисел.
8. Написать функции реализующие дек вещественных чисел.
9. Написать функции реализующие очередь символьных переменных.
10. В чем состоят преимущества и недостатки связанных списков перед массивами? Приведите примеры.
11. Запишите синтаксис доступа к полям данных структурированных типов данных через имя объекта этого типа и указатель на объект этого типа.
12. Напишите функцию сортировки объектов типа card, вставленных в список, по названию книги или году издания. (Для этого необходимо создать динамический массив указателей М на объекты типа card в списке и с помощью функции qsort() отсортировать массив М по соответствующему критерию, при этом последовательность объектов в списке остается неизменной).
Лабораторная работа №8
Типы данных, определённые программистом
Цель работы: Получение навыков в создании новых типов данных и определении множества операций над ними.
Домашнее задание.
Изучить материал по темам: конструкторы, деструкторы и доступность компонентов класса; компонентные данные и компонентные функции; друзья классов; расширение действия стандартных операций; шаблоны классов.
Лабораторное задание
1. Набрать и отладить программу №1
//Программа №1
#include "stdafx.h"
#include <string.h>
#include <iostream>
#include <MATH.H>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
// class Matr
//-------------------------------------------------------------------
template <class T>
class Matr
{
long line;
long col;
T ** matr;
public:
virtual ~Matr(); //Деструктор
Matr(long l, long c); // Конструктор
Matr():line(0), col(0),matr(NULL){} //Конструктор по умолчанию
Matr(Matr<T>& A); //Конструктор копии
T * operator[](long i){return matr[i];}
template <class T>
friend Matr<T> operator*(Matr<T>& A, Matr<T>& B);
const Matr<T>& operator=(const Matr<T>& A);
template <class T>
friend Matr<T> operator*(double K, const Matr<T>& A);
Matr<T> operator+(const Matr<T>& A);
Matr<T> operator-(const Matr<T>& A);
void display();
};
// Matr<T>::Matr()
//-------------------------------------------------------------------
template <class T>
Matr<T>::Matr(long l1, long col1)
{
line = l1;
col = col1;
matr = new T*[line];
if(matr == NULL) cout<< "Out of memory";
for (int i = 0; i < line; i++){
matr[i] = new T[col];
if(matr[i] == NULL) cout<<"Out of memory";
}
}
// Matr<T>::Matr(Matr<T>& A)
//-------------------------------------------------------------------
template <class T>
Matr<T>::Matr(Matr<T>& A):line(A.line), col(A.col)
{
matr = new T*[line];
if(matr == NULL) cout<< "Out of memory";
for (int i = 0; i < line; i++){
matr[i] = new T[col];
if(matr[i] == NULL) cout<<"Out of memory";
}
for(long j = 0; j<line; j++){
for(int i = 0; i<col; i++){
matr[j][i] = A.matr[j][i];
}
}
}
// Matr<T>::~Matr()
//-------------------------------------------------------------------
template <class T>
Matr<T>::~Matr()
{
for (int i = 0; i < line; i++) delete[] matr[i];
delete matr;
}
// void display(const Matr<T>& A)
//-------------------------------------------------------------------
template <class T>
void Matr<T>::display(){
cout<<"\n";
for(int i = 0; i<line;i++){
cout<<"\n";
for(int j = 0; j < col; j++)
cout<<matr[i][j]<<"\t";
}
}
// Matr<T>::operator*()
//-------------------------------------------------------------------
template <class T>
Matr<T> operator*(Matr<T>& A,
Matr<T>& B)
{
if(!(A.col == B.line)) cout<<"\n A*B A.col!= B.line";
Matr<T> arMatr(A.line, B.col);
long l1 = A.line;
long col1 = A.col;
long col2 = B.col;
for(long i = 0; i < l1; i++){
for(long j = 0; j < col2; j++){
arMatr[i][j] = 0;
for(long k = 0; k < col1; k++) {
arMatr[i][j]+=A[i][k]*B[k][j];
}
}
}
return arMatr;
}
// Matr::operator=()
//-------------------------------------------------------------------
template <class T>
const Matr<T>& Matr<T>::operator=(const Matr<T>& A)
{
if(this == &A) return *this;
line = A.line;
col = A.col;
for(long i = 0; i<A.line; i++){
for(long j = 0; j<A.col; j++){
matr[i][j] = A.matr[i][j];
}
}
return *this;
}
// Matr<T>::operator*()
//-------------------------------------------------------------------
template <class T>
Matr<T> operator*(double K, const Matr<T>& A)
{
Matr<T> M(A.line, A.col);
for(long i = 0; i<A.line; i++){
for(long j = 0; j<A.col; j++){
M.matr[i][j] = K * A.matr[i][j];
}
}
return M;
}
// Matr<T>::operator+()
//-------------------------------------------------------------------
template <class T>
Matr<T> Matr<T>::operator+(const Matr<T>& A)
{
if(line!= A.line || col!= A.col) {
cout<<"\n A!= B";
Matr<T> M(0,0);
return M;
}
Matr<T> M(A.line, A.col);
for(long i = 0; i<A.line; i++){
for(long j = 0; j<A.col; j++){
M.matr[i][j] = matr[i][j] + A.matr[i][j];
}
}
return M;
}
// Matr<T>::operator-()
//-------------------------------------------------------------------
template <class T>
Matr<T> Matr<T>::operator-(const Matr<T>& A)
{
if(line!= A.line) {
cout<<"\n - no A.line = B.line";
Matr<T> M(0,0);
return M;
}
if(col!= A.col) {
cout<<"\n - no A.line = B.line";
Matr<T> M(0,0);
return M;
}
Matr<T> M(A.line, A.col);
for(long i = 0; i<A.line; i++){
for(long j = 0; j<A.col; j++){
M.matr[i][j] = matr[i][j] - A.matr[i][j];
}
}
return M;
}
// TMatr()
//-------------------------------------------------------------------
template <class T>
Matr<T> TMatr(Matr<T>& M){
Matr<T> TM(M.col, M.line);
for(int i = 0; i < M.line; i++)
for(int j = 0; j < M.col; j++)
TM[j][i] = M[i][j];
return TM;
}
void main(){
Matr<double> A(2,2), B(2,2);
A[0][0]=A[0][1]=A[1][0]=A[1][1] = 1;
B[0][0]=B[0][1]=B[1][0]=B[1][1] = 2;
A.display();
B.display();
A=(2.5*A-A+B)*B;
A.display();
getchar();
}
2. В каждую компонентную функцию вставить строку программы, печатающую, что именно эта компонентная функция вызвана. (В конструктор, например, вставить строку cout<<"\n Это конструктор.";) и объяснить последовательность вызовов компонентных функций при выполнении main().
3. До определить множество операций над матрицами, т.е. написать компонентные функции, реализующие операции ==,!=, >, <, A * const, cout<<A. Считать, что матрица А > матрицы В, если max |aij |> max |bij|; i = 1,…,N; j = 1, …, M.
4. Определить новый тип данных, комплексное число, и множество операций над ним.
5. Написать отчет.
Содержание отчета
5. Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.
6. Выполненное домашнее задание.
7. Тексты программ, написанных при выполнении 3 и 4 пунктов лабораторного задания.
Контрольные вопросы.
1. Для чего используется конструктор копии? В каких случаях наличие конструктора копии в классе обязательно, для правильной работы программы, а в каких нет?
2. Как работает компонентная функция operator=? В каких случаях наличие компонентной функции operator= в классе обязательно, для правильной работы программы, а в каких нет?
3. Конструктор преобразования типа. Приведите примеры явного и неявного вызова конструктора преобразования типа для класса комплексное число.
4. Перегрузка операций. Запишите множество перегружаемых и не перегружаемых операций языка С++. Расскажите о свойствах перегруженных операций.
5. Напишите класс vector (вектор) и определите над ним множество операций { +, -, ==, =,!=, скалярное произведение}.
6. Напишите класс str (строка) и определите над ним множество операций { +, -, ==, =,!=, <, >}.
7. Напишите класс круг и определите над ним множество операций {==,!=, <,> } (по площади).
8. Напишите класс квадрат и определите над ним множество операций {==,!=, <,> } (по площади).
9. Напишите класс список, обеспечивающий: вставку, удаление, доступ к элементу в списке.
10. Деструктор, его назначение и сигнатура.
11. Добавьте в класс Matr статическую компонентную функцию и статическое поле данных, в котором хранится количество объектов типа Matr.
12. Напишите компонентные функции, обеспечивающие сохранение и восстановление объекта типа Matr из файла.
13. В чем состоит идея инкапсуляции данных? В чем её основное достоинство? С помощью каких средств языка С++ она реализуется в программе? Приведите примеры класса, написанного с инкапсулированными данными и нет.
Лабораторная работа N 9