Цель лекции: изучить объявления, выделения и освобождения памяти для одномерных динамических массивов, обращения к элементам, научиться решать задачи с использованием одномерных динамических массивов в языке C++.
При использовании многих структур данных достаточно часто бывает, что они должны иметь переменный размер во время выполнения программы. В этих случаях необходимо применять
В соответствии со
Динамический массив – это массив, размер которого заранее не фиксирован и может меняться во время исполнения программы. Для изменения размера
Под объявлением одномерного
Синтаксис:
Тип * ИмяМассива;
ИмяМассива – идентификатор массива, то есть имя указателя для выделяемого
Тип – тип элементов объявляемого void.
Например:
int *a; double *d;
В данных примерах a и d являются указателями на начало выделяемого участка памяти. Указатели принимают значение адреса выделяемой области памяти для значений типа int и типа double соответственно.
Таким образом, при динамическом распределении памяти для динамических массивов следует описать соответствующий указатель, которому будет присвоено значение адреса начала области выделенной памяти.
Для того чтобы выделить память под одномерный
1) при помощи операции new, которая выделяет для размещения массива участок динамической памяти соответствующего размера и не позволяет инициализировать элементы массива.
Синтаксис:
ИмяМассива = new Тип [ВыражениеТипаКонстанты];
ИмяМассива – идентификатор массива, то есть имя указателя для выделяемого
Тип – тип указателя на массив.
ВыражениеТипаКонстанты – задает количество элементов (
Например:
int *mas;
mas = new int [100]; /*выделение динамической памяти
размером 100*sizeof(int) байтов*/
double *m = new double [n]; /*выделение динамической
памяти размером n*sizeof(double) байтов*/
long (*lm)[4];
lm = new long [2] [4]; /*выделение динамической памяти
размером 2*4*sizeof(long) байтов*/
При выделении динамической памяти размеры массива должны быть полностью определены.
2) при помощи библиотечной функции malloc (calloc), которая служит для выделения динамической памяти.
Синтаксис:
ИмяМассива = (Тип *) malloc(N*sizeof(Тип));
или
ИмяМассива = (Тип *) calloc(N, sizeof(Тип));
ИмяМассива – идентификатор массива, то есть имя указателя для выделяемого
Тип – тип указателя на массив.
N – количество элементов массива.
Например:
float *a; a=(float *)malloc(10*sizeof(float)); // или a=(float *)calloc(10,sizeof(float)); /*выделение динамической памяти размером 10*sizeof(float) байтов*/
Так как функция malloc (calloc) возвращает void *, то необходимо выполнять преобразование полученного
1) при помощи операции delete, которая освобождает участок памяти ранее выделенной операцией new.
Синтаксис:
delete [] ИмяМассива;
ИмяМассива – идентификатор массива, то есть имя указателя для выделяемого
Например:
delete [] mas; /*освобождает память, выделенную под
массив, если mas адресует его начало*/
delete [] m;
delete [] lm;
Квадратные скобки [] сообщают оператору, что требуется освободить память, занятую всеми элементами, а не только первым.
2) при помощи библиотечной функции free, которая служит для освобождения динамической памяти.
Синтаксис:
free (ИмяМассива);
ИмяМассива – идентификатор массива, то есть имя указателя для выделяемого
Например:
free (a); //освобождение динамической памяти
Адресация элементов
Синтаксис:
ИмяМассива[ВыражениеТипаКонстанты];
или
ИмяМассива[ЗначениеИндекса];
Например:
– индекс задается как константа,
– индекс задается как переменная,
array[4*p] – индекс задается как выражение.
Пример 1. Сформировать динамический
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
int *a, n, i;
cout << "Введите n: ";
cin >> n;
cout << ' ';
a = new int [n]; //Выделение памяти под массив
for (i=0; i<n; i++) {
cout << "Введите a[" << i << "]: ";
cin >> a[i];
cout << ' ';
}
int *buf = new int [n];
//Выделение памяти под вспомогательный массив
int j = 0; //Индекс вспомогательного массива
for (i=0; i<n; i+=2) {
//Переписываем элементы с чётным индексом в новый массив
buf[j] = a[i];
j++;
}
for (i=1; i<n; i+=2) {
//Переписываем элементы с нечётным индексом в новый массив
buf[j] = a[i];
j++;
}
cout << "Преобразованный: " << ' ';
for (i=0; i<n; i++)
cout << buf[i] << ' ';
delete [] a; //Освобождаем память
delete [] buf;
system("pause");
return 0;
}
Отметим, что указатель на массив не обязательно должен показывать на начальный элемент некоторого массива. Он может быть сдвинут так, что начальный элемент будет иметь индекс, отличный от нуля, причем он может быть как положительным, так и отрицательным.
Пример 2.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
float *mas;
int m;
scanf("%d",m);
mas=(float *)calloc(m,sizeof(float));
//сейчас указатель q показывает на начало массива
mas[0]=22.3;
mas-=5;
/*теперь начальный элемент массива имеет индекс 5,
а конечный элемент индекс n-5*/
mas[5]=1.5;
/*сдвиг индекса не приводит к перераспределению массива
в памяти и изменится начальный элемент*/
mas[6]=2.5; // это второй элемент
mas[7]=3.5; // это третий элемент
mas+=5;
/*теперь начальный элемент вновь имеет индекс 0,
а значения элементов q[0], q[1], q[2] равны
соответственно 1.5, 2.5, 3.5*/
mas+=2;
/*теперь начальный элемент имеет индекс -2, следующий -1,
затем 0 и т.д. по порядку*/
mas[-2]=8.2;
mas[-1]=4.5;
mas-=2;
/*возвращаем начальную индексацию, три первых элемента
массива q[0],q[1],q[2], имеют значения 8.2, 4.5, 3.5*/
mas--;
/*вновь изменим индексацию. Для освобождения области
памяти, в которой размещен массив q используется
функция free(q), но поскольку значение указателя q
смещено, то выполнение функции free(q) приведет к
непредсказуемым последствиям.
Для правильного выполнения этой функции указатель q
должен быть возвращен в первоначальное положение */
free(++mas);
system("pause");
return 0;
}
Пример 3. Задача Иосифа Флавия или считалка Джозефуса.
Задача в своей основе имеет легенду. Отряд из 41-го сикария, защищавший галилейскую крепость Массада, не пожелал сдаваться в плен блокировавшим его превосходящим силам римлян. Сикарии стали в круг и договорились, что каждые два воина будут убивать третьего, пока не погибнут все. Самоубийство – тяжкий грех, но тот, кто в конце концов останется последним, должен будет его совершить. Иосиф Флавий, командовавший этим отрядом, якобы быстро рассчитал, где нужно стать ему и его другу, чтобы остаться последними. Но не для того, чтобы убить друг друга, а чтобы сдать крепость римлянам. В современной формулировке задачи участвует n воинов и убивают каждого k -го. Требуется определить номера m и t начальных позиций двоих воинов, которые должны будут остаться последними.
#include "stdafx.h"
#include <iostream>
using namespace std;
void kill(int *mass,int n,int i);
void krug(int *mass,int n,int k, int i=0);
int _tmain(int argc, _TCHAR* argv[]){
int n,k,*mass,i;
FILE *f;
f=fopen("input.txt","r");
fscanf(f,"%d %d",n,k);
fclose(f);
mass=(int *)malloc(n*sizeof(int));
for (i=0;i<n;i++) mass[i]=i+1;
f=fopen("output.txt","w");
fprintf(f,"Исходная нумерация: \n");
for (i=0;i<n;i++) fprintf(f,"%d ",mass[i]);
fclose(f);
krug(mass,n,k);
f=fopen("output.txt","a+");
fprintf(f,"\nОставшиеся в живых: \n");
for (i=0;i<k;i++) fprintf(f,"%d ",mass[i]);
fclose(f);
free(mass);
system("pause");
return 0;
}
void kill(int *mass,int n,int i) {
int j;
for (j=i;j<n-1;j++)
mass[j]=mass[j+1];
}
void krug(int *mass,int n,int k,int i) {
int ii;
if (n>k) {
ii=i+k-1;
if (ii>=n) ii=ii%n;
kill(mass,n,ii);
krug(mass,n-1,k,ii);
}
}
Динамический массив – это массив, размер которого заранее не фиксирован и может меняться во время исполнения программы.
Значение указателя на одномерный динамический массив – это адрес выделяемой области динамической памяти.
Одномерный динамический массив – это
Тип одномерного динамического массива – это тип элементов массива.
Указатель на одномерный динамический массив – это указатель на начало выделяемого участка динамической памяти.
Цель работы: изучить объявления, выделения и освобождения памяти для одномерных динамических массивов, обращения к элементам, научиться решать задачи с использованием одномерных динамических массивов в языке C++.
При выполнении лабораторной работы для каждого задания требуется написать программу на языке С++, которая получает на входе числовые данные (в зависимости от постановки задачи), выполняет генерацию, вывод одномерного массива указанного типа. Для хранения оговоренных в условии массивов следует использовать ресурсы динамической памяти. Ввод данных осуществляется с клавиатуры с учетом требований к входным данным, содержащихся в постановке задачи. Ограничениями на входные данные является диапазон используемого числового типа данных в языке С++ и максимально допустимый размер динамической памяти.
Теоретические сведения.
Ознакомьтесь с материалом лекции 25.
Задания к лабораторной работе.
Выполните приведенные ниже задания.
N вещественных чисел. Вычислить сумму чисел, порядковые номера которых являются N вещественных чисел. Найти частное средних арифметических значений элементов с нечетными и четными индексами.new и delete ; 2) с помощью библиотечных функций malloc (calloc) и free.Указания к выполнению работы.
Каждое задание необходимо решить в соответствии с изученными методами работы с динамической памятью и алгоритмами обработки одномерных массивов в языке С++. В задачах количество входных данных заранее не определено, однако, при реализации следует считать, что их размер не превышает максимально допустимого объема динамической памяти. Вывод входных данных и результатов их обработки следует осуществить на экран. Программу для решения каждого задания необходимо разработать методом процедурной абстракции, оформив комментарии к коду.
Следует реализовать каждое задание в соответствии с приведенными этапами:
Требования к отчету.
Отчет по лабораторной работе должен соответствовать следующей структуре.
Контрольные вопросы
Тип* ) malloc(N* sizeof(Тип))?malloc (сalloc) при объявлении массивов?delete [] mass ;?Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.