русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Динамический массив и динамическое выделение памяти

Массивы являются разумным подходом к хранению данных, но они имеют серьёзный недостаток: мы должны знать при написании программы, насколько большой массив нам нужен. Компилятор С++ требует, чтобы значение размерности массива было константой, поэтому как правило приходится завышать размерность массива, что приводит к перерасходу памяти.

Таким образом, если до начала работы программы неизвестно, сколько в массиве будет элементов, то следует использовать динамические массивы. Динамические массивы создают с помощью операции new, при этом необходимо указать тип и размерность, например:

int n;

… cin >> n;

float *a = new float [n];

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

Динамические массивы нельзя при создании инициализировать, и они не обнуляются. Преимущество динамических массивов состоит в том, что их размерность может быть переменной, т.е. объём памяти выделяемой под массив, определяется не программистом, а на этапе выполнения программы. Доступ к элементам динамического массива осуществляется точно так же, как к статическим, например, к элементу номер 5 приведённого выше массива можно обратиться как а[5] или *(а+5).

Если динамический массив в какой-то момент работы программы перестаёт быть нужным и мы собираемся впоследствии использовать выделенную под него память повторно, необходимо освободить её с помощью операции delete [ ], например: delete [ ] a;. Размерность массива при этом не указывается, но квадратные скобки обязательны.

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

int main() {

int N, i, sum=0;

cout << "Vvedite kol-vo elementov massiva: "; cin >> N;

int *mas = new int [N];

for(i=0; i<N; i++) {

cout << "Vvedite element " << i << ": ";

cin >> mas[i];

}

for(i=0; i<N; i++) {

sum = sum + mas[i];

}

cout << "\nSumma elementov massiva: " << sum << endl;

delete [ ] mas;// эта строка не обязательна, поскольку программа закончила работу

getch(); return 0; }

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

В приведённом примере мы применили операцию освобождения выделенных участков памяти delete [ ], которая на самом деле (в данном случае) и не нужна, так как память автоматически освобождается после завершения программы. Однако предположим, что мы используем операцию new в функции. Если функция использует локальную переменную-указатель на память, выделенную с использованием new, то указатель будет уничтожен по окончании работы функции, но память, в случае отсутствия delete [ ], останется выделенной и при этом недоступной из программы. Поэтому освобождение памяти после того, как она была использована и больше не требуется, является хорошим тоном. При этом надо быть внимательными и не использовать указатели на освобождённую ранее память.

Д/З Написать программу, которая позволяет вводить динамический вещественный массив и с помощью "возвращающей" функции определять сумму его элементов, расположенных правее последнего отрицательного элемента. В случае исключительной ситуации должно выводиться соответствующее сообщение. Функция должна возвращать соответствующее значение, если она вычислила сумму элементов правее последнего отрицательного, если в массиве нет отрицательных элементов и если отрицательный элемент последний.
Ответ int N; float sumppo(float arr[], int N);   int main() { int i; cout << "Vvedite kol-vo elementov massiva: "; cin >> N; float *mas = new float [N]; for(i=0; i<N; i++) { cout << "Vvedite element " << i << ": "; cin >> mas[i]; } if((sumppo(mas, N)) >= 0.) cout << "\n Summa elementov pravee posl. otricatelnogo: " << sumppo(mas, N); if((sumppo(mas, N)) == -1) cout << "\n V massive net otricat. elementov!"; if((sumppo(mas, N)) == -2) cout << "\n Otricatelniy element posledniy!"; delete [] mas; getch(); return 0; } //--------------------------------------------------------------------------- float sumppo(float arr[], int N) { float sum = 0, res; int k=0; for(int j=N-1; j>=0; j--) { if(arr[j] < 0) { k++; break; } sum = sum + arr[j]; } if(k == 0) res = -1; if(k == 1 && arr[N-1] < 0.) res = -2; if(k == 1 && arr[N-1] >= 0.) res = sum; return res; }

Естественно можно осуществлять динамическое выделение памяти и для многомерных массивов. Существует несколько способов решения этого вопроса. Более универсальный и безопасный способ выделения памяти под двумерный массив заключается в том, что обе его размерности задаются на этапе выполнения программы. Рассмотрим пример.

int main() {

int Nstr, Nstb, i, j;

cout << "Vvedite kol-vo strok i stolbcov: ";

cin >> Nstr >> Nstb;

int **mas = new int *[Nstr];// 1

for(i=0; i<Nstr; i++)// 2

mas[i] = new int [Nstb];// 3

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

for(j=0; j<Nstb; j++) {

cout << "Vvedite element stroki " << i << ", stolbca " << j << ": ";

cin >> mas[i][j];

}

Здесь, в операторе 1 объявляется переменная типа "указатель на указатель на int" и выделяется память под массив указателей на строки массива. В операторе 2 организуется цикл для выделения памяти под каждую строку массива. В операторе 3 каждому элементу массива указателей на строки присваивается адрес начала участка памяти, выделенного под строку двумерного массива. Каждая строка состоит из Nstb элементов типа int.

Д/З Допишите приведенную выше программу, чтобы она позволяла выводить на экран введённую матрицу в отформатированном наглядном виде с помощью функции. При передаче массива в функцию используйте указатели, а размерность массива передавайте по ссылке. Применение глобальных переменных запрещено.
Ответ … #include <iomanip> using namespace std; //--------------------------------------------------------------------------- void show(int** ptr, int& Kstr, int& Kstb); int main() { int i, j, Nstr, Nstb; cout << "Vvedite kol-vo strok i stolbcov: "; cin >> Nstr >> Nstb; int **mas = new int *[Nstr]; for(i=0; i<Nstr; i++) mas[i] = new int [Nstb]; for(i=0; i<Nstr; i++) for(j=0; j<Nstb; j++) { cout << "Vvedite element stroki " << i << ", stolbca " << j << ": "; cin >> mas[i][j]; } show(mas, Nstr, Nstb); delete [] mas; getch(); return 0; } //--------------------------------------------------------------------------- void show(int** ptr, int& Kstr, int& Kstb) { int i, j; cout << "\nVvedena matrica: " << endl; for(i=0; i<Kstr; i++) { for(j=0; j<Kstb; j++) cout << setw(3) << ptr[i][j]; cout << endl; } }

Лекция 8(17 стр.)

Просмотров: 1117


Вернуться в оглавление



Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.