Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Указатели и динамические массивы




Лабораторная работа 9

 

Цель работы – получить практические навыки работы с указателями, овладеть навыками выделения, перераспределения и освобождение памяти при работе с динамическими массивами.

Теория

Язык Си++ отличается от других структурированных языков прежде всего широким использованием указателей. До некоторой степени именно наличие в языке Си++ указателей сделало его очень удобным для системного программирования.

Указатель – это некоторая переменная, которая в отличие от других переменных не содержит значения данного. Напротив, она указывает на переменную, которая содержит значение. То есть указатель содержит в себе не значение переменной, а ее адрес.

Нотация для указателей в языке Си++ следующая. Символ операции &, поставленный перед некоторой переменной, показывает, что нам нужен адрес этой переменной, а не ее текущее значение. Например, выражение &var1 означает адрес переменной var1, а не значение, которое эта переменная имеет. Следовательно, оператор присваивания вида

 

ptr=&var1;

 

означает «взять адрес переменной var1 и присвоить его значение переменной с именем ptr». Переменная ptr называется переменной-указателем. Зачем это делается? Так как переменная var1 содержит некоторое значение данных (пусть это будет значение x), после такой операции значение x становится доступно программе через переменную-указатель ptr, поскольку ptr теперь содержит адрес значения x. Операция & называется операцией получения адреса.

Операция * в языке Си++ отсылает к содержимому ячейки памяти, на которую указывает переменная, стоящая после символа *. Например, *ptr можно описать словами как «то, что содержится в ячейке с адресом, хранящимся в ptr». Операция * называется операцией доступа по указателю.

 

Пример

Два оператора присваивания

ptr=&var1;

var2=*ptr;

выполняют то же самое, что и один оператор

var2=var1;

 

Рассмотрим программу, демонстрирующую использование указателей. Эта программа печатает символ 'X'.

 

#include <iostream.h>

main()

{

char a, *b, c;

a='X';

b=&a;

c=*b;

cout<<c;

}

 

Результат: X.

 

Указателям могут присваиваться строки.

 

Пример

#include <iostream.h>

main()

{

char *ptr1="Привет", *ptr2;

ptr2=ptr1;

while(*ptr2!='\0')

{

++ptr2;

cout<<*ptr2;

}

}

 

Результат: Привет.

 

С помощью указателей осуществляется доступ к участкам динамической памяти, которые называются динамическими переменными. Динамические переменные создаются с помощью специальных функций и операций. Они существуют либо до конца работы программ, либо до тех пор, пока не будут уничтожены с помощью специальных функций или операций.

Для создания динамических переменных используют операцию new, определенную в C++:

 

указатель = new имя_типа[инициализатор];

 

Операция new позволяет выделить и сделать доступным участок динамической памяти, который соответствует заданному типу данных. Если задан инициализатор, то в этот участок будет занесено значение, указанное в инициализаторе.

 

Пример

int* x=new int(5);

 

Для удаления динамических переменных используется операция delete, определенная в C++:

 

delete указатель;

 

где указатель содержит адрес участка памяти, ранее выделенный с помощью операции new.

 

Пример

delete x;

 

Операция new при использовании с массивами имеет следующий формат:

new тип_массива

 

Такая операция выделяет для размещения массива участок динамической памяти соответствующего размера, но не позволяет инициализировать элементы массива. Операция new возвращает указатель, значением которого служит адрес первого элемента массива. При выделении динамической памяти размеры массива должны быть полностью определены.

 

Пример

//выделение динамической памяти 100*sizeof(int) байт

int* a = new int[100];

 

При формировании матрицы сначала выделяется память для массива указателей на одномерные массивы, а затем в цикле с параметром выделяется память под n одномерных массивов.

 

Пример

/*выделение динамической памяти под двумерный динамический массив*/

int** form_matr(int n,int m)

{

int **matr=new int*[n];//выделение памяти под

//массив указателей

for(int i=0;i<n;i++) //выделение памяти

//для массива значений

matr[i]=new int [m];

return matr;//возвращение указателя на массив указателей

}

 

Изменять значение указателя на динамический массив надо аккуратно, т. к. этот указатель затем используется при освобождении памяти с помощью операции delete.

 

 

*matr[0] *matr[1] *matr[2] ….. *matr[n]

 

 

Рис. 9

 

Пример

/*освобождает память, выделенную под массив, если а адресует его начало*/

delete[] a;

 

Удаление из динамической памяти двумерного массива осуществляется в порядке обратном его созданию, т. е. сначала освобождается память, выделенная под одномерные массивы с данными, а затем память, выделенная под одномерный массив указателей.

 

Пример

int find(int **matr,int m,int I)

{

for(int i=0;i<m;i++)

if(matr[I][i]<0) return 1;

return 0;

}

 

При удалении из динамической матрицы строк или столбцов создается новая матрица нужного размера, в которую переписываются данные из старой матрицы. Затем старая матрица удаляется.

Пример

int **del(int **matr,int &n,int m)

{

//удаление четных строк

int k=0,t=0;

for(int i=0;i<n;i++)

if(i % 2!=0) k++; //количество нечетных строк

//выделяем память под новую матрицу

int **matr2=form_matr(k,m);

for(i=0;i<n;i++)

if(i % 2!=0)

{

//если строка нечетная, то переписываем ее в новую матрицу

for(int j=0;j<m;j++)

matr2[t][j]=matr[i][j];

t++;

}

n=t; //изменяем количество строк

//возвращаем указатель на новую матрицу как результат //функции

return matr2;

}

Задание

1. Запустите C++Builder.

2. Наберите программу, формирующую динамический массив, заполните его случайными числами и выведите на печать. Выполните указанное в варианте задание.

3. Для выделения памяти, заполнения массивов, удаления и добавления элементов (строк, столбцов) написать отдельные функции. В функции main() должны быть размещены только описания переменных и обращения к соответствующим функциям.

4. Выполните компиляцию программы. При наличии ошибок внесите исправления.

5. Сдайте отчет преподавателю.

 

Варианты

с Одномерный массив Двумерный массив
  Удалить первый четный элемент Добавить строку с заданным номером
  Удалить первый отрицательный элемент Добавить столбец с заданным номером
  Удалить элемент с заданным ключом (значением) Добавить строку в конец матрицы
  Удалить элемент равный среднему арифметическому элементов массива Добавить столбец в конец матрицы
  Удалить элемент с заданным номером Добавить строку в начало матрицы
  Удалить N элементов, начиная с номера K Добавить столбец в начало матрицы
  Удалить все четные элементы Добавить К строк в конец матрицы
  Удалить все элементы с четными индексами Добавить К столбцов в конец матрицы
  Удалить все нечетные элементы Добавить К строк в начало матрицы
  Удалить все элементы с нечетными индексами Добавить К столбцов в начало матрицы
  Добавить элемент в начало массива Удалить строку с номером К
  Добавить элемент в конец массива Удалить столбец с номером К
  Добавить К элементов в начало массива Удалить строки, начиная со строки К1 и до строки К2
  Добавить К элементов в конец массива Удалить столбцы, начиная со столбца К1 и до столбца К2
  Добавить К элементов, начиная с номера N Удалить все четные строки
  Добавить после каждого отрицательного элемента его модуль Удалить все четные столбцы
  Добавить после каждого четного элемента элемент со значением0 Удалить все строки, в которых есть хотя бы один нулевой элемент
  Добавить по К элементов в начало и в конец массива Удалить все столбцы, в которых есть хотя бы один нулевой элемент
  Добавить элемент с номером К Удалить строку, в которой находится наибольший элемент матрицы
  Удалить элемент с заданным номером Добавить строки после каждой четной строки матрицы

 

Продолжение табл.

Одномерный массив Двумерный массив
  Удалить N элементов, начиная с номера K Добавить столбцы после каждого четного столбца матрицы
  Удалить все четные элементы Добавить К строк, начиная со строки с номером N
  Удалить все элементы с четными индексами Добавить К столбцов, начиная со столбца с номером N
  Удалить все нечетные элементы Добавить строку после строки, содержащей наибольший элемент
  Удалить все элементы с нечетными индексами Добавить столбец после столбца, содержащего наибольший элемент

 





Поделиться с друзьями:


Дата добавления: 2015-08-31; Просмотров: 2556; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.033 сек.