
2 / 1
.docxМИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ
федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ
АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
Кафедра вычислительных систем и сетей
ПРЕПОДАВАТЕЛЬ
Доцент, канд. техн. наук |
|
|
|
Л.Н. Бариков |
должность, уч. степень, звание |
|
подпись, дата |
|
инициалы, фамилия |
Лабораторная работа №1
Динамические массивы
по курсу: Основы программирования
СТУДЕНТКА ГР. № |
Z0411 |
|
|
|
М.В.Карелина |
|
|
номер группы |
|
подпись, дата |
|
инициалы, фамилия |
Номер студенческого билета: 2020/3477
Санкт-Петербург
2022
Цель лабораторной работы:
Изучение структурной организации динамических массивов и способов доступа к их элементам с использованием указателей; совершенствование навыков процедурного программирования на языке C/C++ при решении задач обработки динамических массивов.
Порядок выполнения работы:
1. Получить у преподавателя индивидуальное задание и выполнить постановку для каждой из задач: сформулировать условие, определить входные и выходные данные, их ограничения.
2. Разработать математические модели для каждой из задач: описать с помощью формул и рисунков структуру массивов и процесс их преобразования.
3. Провести структуризацию каждой из задач. С этой целью выделить в них подзадачи, которые будут реализованы в виде отдельных функций (ввод исходных данных, вывод содержимого массива, обработка массива в соответствии с заданием и т.д.). При этом запрещается совмещать в одной функции решение нескольких подзадач.
4. Обязательное требование – введение собственных типов данных, логически точно разделяющих и группирующих информацию, используемую при решении конкретной задачи (тип индекса элемента массива, тип значения элемента массива, тип массива и т.п.).
5. Построить схемы алгоритмов решения задач и основных функций.
6. Составить программу на языке C/C++.
7. Входные данные на этапах тестирования и демонстрации работы преподавателю должны задаваться либо с использованием специально подобранных арифметических формул, либо вводиться с клавиатуры по запросу. Датчики псевдослучайных чисел использовать запрещается.
8. Выходные данные должны выводиться на экран с пояснениями. Операторы вывода результатов работы должны находиться либо в функции main(), либо в специальной функции вывода (например, преобразованного массива), вызов которой осуществляется из функции main().
9. Проверить и продемонстрировать преподавателю работу программы на полном наборе тестов, в том числе с ошибочными входными данными. Входные и выходные массивы должны выводиться в одном и том же формате.
10. Использовать стандартные потоковые объекты ввода/вывода cin и cout.
11. Оформить отчет о лабораторной работе в составе: постановка задачи, математическая модель, схема общего алгоритма решения, схемы алгоритмов основных функций, текст программы, контрольные примеры (скриншоты).
Вариант 28
А. Дан массив a0, a1, a2,…, a2n-1. Определить абсолютную величину суммы значений элементов массива с нечётными номерами, лежащих между последним элементом массива с положительным значением и элементом с номером n-1.
Математическая модель решения
Решение задачи начинается с ввода исходных данных. Прежде всего, необходимо ввести значение (n) размера массива.
После этого необходимо задать значения всех элементов массива. Доступ к элементам массива осуществляется по их индексу (номеру данного элемента массива). Поэтому перебираем все индексы элементов массива от 0 до 2n-1 (нумерация элементов массива начинается с 0) и задаём значения элементов с текущими номерами.
Пусть исходный массив имеет вид (n=10):
0 |
1 |
|
|
|
|
|
|
|
2n-1 |
1 |
8 |
-5 |
-3 |
5 |
7 |
6 |
-9 |
2 |
-11 |
Теперь можно приступать к решению задачи.
Вначале определяем элемента массива, имеющий индекс n-1, для простоты мы вводим переменную с и присваиваем ей значение n-1.
Далее определяем индекс последнего элемента массива с положительным значением. Для этого перебираем элементы массива с индексами от 0 до 2n-1. Если такой элемент в массиве есть, фиксируем факт его обнаружения в переменной flag и индекс этого элемента ipos и прекращаем перебор.
Если ни один элемент массива с положительным значением не найден, выполнение решения всей задачи прекращается.
Если в обоих случаях элементы массива найдены, то результат в нашем случае выглядит следующим образом:
0 |
1 |
|
|
|
|
|
|
|
2n-1 |
|||||
1 |
8 |
-5 |
-3 |
5 |
7 |
6 |
-9 |
2 |
-11 |
|||||
|
|
|
|
c |
|
|
|
ipos |
|
При этом логически возможно три случая: c<ipos, c>ipos и c=ipos.
В первом случае складываем значения элементов c нечетным индексом между c до ipos, а получившуюся сумму sum берем по модулю.
Во втором случае складываем значения элементов c нечетным индексом между ipos до с, а получившуюся сумму sum берем по модулю.
В третьем случае выполнение решения всей задачи прекращается.
Задача решена.
Схема алгоритма поиска индекса последнего элемента массива с положительным значением (функция nomer_pos)
Схема
алгоритма вычисления абсолютной величины
суммы (функция abs_sum)
Код программы:
#include<iostream>
#include<stdlib.h>
#include<locale.h>
using namespace std;
const int RAZ = 20; //предельный размер массива
typedef int telem; //определение типа элементов массива
typedef telem tmas[RAZ];
int nomer_max(const tmas, int);
int nomer_pos(const tmas, int);
int abs_sum(const tmas, int, int);
void inputmas(tmas, int);
void outputmas(const tmas, int);
int main()
{
setlocale(LC_ALL, "Russian");
tmas a;
int n, imax, ipos, c;
telem sum;
cout << "\n Введите переменную n (Не больше 10) <= " << RAZ << " : ";
cin >> n;
c = n - 1;
n = n * 2 - 1;
//Контроль ввода размера массива
if (n > RAZ || n <= 0)
{
cout << "Введено недопустимое значение размера массива" << endl;
return 1;
}
inputmas(a, n);
cout << " Исходный массив:" << endl;
outputmas(a, n);
ipos = nomer_pos(a, n);
cout << "\n Индекс последнего элемента массива с положительным значением = " << ipos << endl;
cout << "\n Индекс элемента массива с номером n-1 = " << c << endl;
sum = abs_sum(a, c, ipos);
cout << "\n Абсолютная величина суммы: " << sum << endl;
return 0;
}
//Поиск индекса последнего элемента массива с положительным значением
int nomer_pos(const tmas a, int n)
{
int ipos,
flag = 0;
for (int i = n-1; i >= 0; i--)
if (a[i] > 0)
{
ipos = i;
flag = 1;
break;
}
if (flag == 1)
{
}
else {
cout << "\n Положительных элементов в массиве нет";
exit(3);
}
return ipos;
}
void inputmas(tmas a, int n)
{
cout << " Введите в одной строке элементы массива, состоящего из " << n;
cout << "\n чисел, и нажмите <Enter>" << endl;
for (int i = 0; i < n; i++)
cin >> a[i];
}
void outputmas(const tmas a, int n)
{
for (int i = 0; i < n; i++)
{
cout.width(4); //ширина поля для вывода значения элемента массива
cout << a[i] << " ";
}
}
telem abs_sum(const tmas a, int c, int ipos)
{
int i;
telem sum;
if (ipos != c)
{
sum = 0;
if (ipos < c)
{
for (i = ipos + 1; i < c; i++)
{
if (i % 2 == 0);
else
sum += a[i];
}
}
else
{
for (i = c + 1; i < ipos; i++)
{
if (i % 2 == 0);
else
sum += a[i];
}
}
}
else
{
cout << "\n Между ними нет элементов";
exit(3);
}
sum = fabs(sum);
return sum;
}
Скриншоты выполнения:
Б. В заданной квадратной матрице размера 2n*2n найти среднее арифметическое значений элементов области [4+5+6+7+8] (см. рисунок).
Математическая модель решения
Решение задачи начинается с ввода исходных данных. Из формулировки задачи понятно, что исходная матрица квадратная с чётным числом (2n) строк и столбцов. Следовательно, прежде всего, необходимо ввести значение (n) половины размера квадратной матрицы
После этого необходимо задать значения всех элементов матрицы. Доступ к элементам двумерного массива (матрицы) осуществляется по двум индексам: номеру строки и номеру столбца, на пересечении которых находится данный элемент массива (нумерация строк и столбцов начинается с 0). Поэтому перебираем все строки (с 0-ой до 2n-1). Внутри каждой строки перебираем все столбцы (с 0-ого до 2n-1) и задаём значения элементов, лежащих на пересечении строки и столбца с текущими номерами.
Пусть в качестве примера исходная матрица имеет вид (n=5):
|
0 |
1 |
|
|
n-1 |
n |
|
|
2n-2 |
2n-1 |
0 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
1 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
|
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
|
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
n-1 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
n |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
|
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
|
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
2n-2 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
2n-1 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
Теперь можно приступать к решению задачи. найти среднее арифметическое значений элементов области [4+5+6+7+8] (выделено зеленым).
Мы поочередно перебираем элементы в зеленой области и суммируем их значения в переменной summ. Так же каждый раз, когда мы это делаем мы увеличиваем счетчик num.
Для нахождения среднего арифметического, получившуюся сумму всех элементов области, делим на их количество, (summ/num), далее результат выводим через переменную sr_arif. Задача решена.
Схема алгоритма вычисления среднего арифметического значения (функция double_arif)
Код программы:
#include<iostream>
#include<locale>
#include <math.h>
using namespace std;
typedef int telem; //определение типа элементов массива
typedef telem* tstr; //определение типа “указатель на telem”
typedef tstr* tmatr; //тип «указатель на указатель на telem»
void check_size(int);
void input_matr(tmatr, int);
void output_matr(tmatr, int);
double arif(tmatr, int);
int main()
{
setlocale(LC_ALL, “Russian”);
tmatr a;
int n; // половина размера матрицы
cout << « Введите половину размера матрицы (не больше 5): n = «;
cin >> n;
check_size(n);
a = new tstr[2 * n]; /*выделение динамической памяти под массив
указателей на строки массива*/
for (int i = 0; i < 2 * n; i++) //выделение памяти под каждую строку:
*(a + i) = new telem[2 * n]; /*каждому элементу массива указателей
на строки присваивается адрес начала
области памяти, выделяемой под строку*/
input_matr(a, n);
output_matr(a, n);
arif(a, n);
cout << endl << “\nДля завершения нажмите <Enter>”;
for (int I = 0; I < n; i++) //Освобождение динамической памяти
delete* (a + i);
delete[]a;
return 0;
}
void check_size(int n)
{
if (n <= 0)
{
cout << «\nТребуется ввод положительного значения половины размера матрицы!\n\n»;
main();
}
if (n > 5)
{
cout << «\nТребуется ввод значения половины размера матрицы не больше 5!\n\n»;
main();
}
}
void input_matr(tmatr a, int n)
{
cout << « Значения элементов массива размера « << n << «x» << n << « при тестировании вводятся автоматически:» << endl;
for (int I = 0; I < 2 * n; i++) //заполнения матрицы
for (int j = 0; j < 2 * n; j++)
*(*(a + i) + j) = 10 * I + j;
}
void output_matr(tmatr a, int n)
{
cout << “ Исходная матрица:\n”;
for (int I = 0; I < 2 * n; i++)
{
for (int j = 0; j < 2 * n; j++)
{
cout.width(3); //ширина поля выводимого параметра
cout << *(*(a + i) + j) << “ “;
}
cout << ‘\n’;
}
}
double arif(tmatr a, int n)
{
double sr_arif= 0.0;
double num = 0.0;
double summ = 0.0;
int k = 1;
for (int I = 0; I < 2 * n; i++)
{
for (int j = 0; j < k; j++)
{
um = um + a[i][j];
num++;
}
if (k < n)
{
k++;
}
else
{
k = 2 * n;
}
}
if (num == 0)
{
return -1;
}
sr_arif = um / num;
cout << “ \nСреднее среднее арифмитическое :” << sr_arif;
}
Скриншот выполнения: