Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка по ospk-2_Си_v11.doc
Скачиваний:
9
Добавлен:
08.11.2019
Размер:
593.92 Кб
Скачать

Лабораторная работа № 5 Тема: «Обработка двухмерных динамических массивов»

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

Теоретические сведения

5.1. Особенности применения указателей

Обращение к объектам любого типа в языке C может проводиться по имени (прямая адресация) и по указателю (косвенная адресация).

Указатель – это переменная, которая может содержать адрес некоторого объекта в памяти компьютера, например, адрес другой переменной. Через указатель, установленный на переменную, можно обращаться к участку оперативной памяти (ОП), отведенной компилятором под ее значение.

Указатель объявляется следующим образом:

тип * ID указателя;

Перед использованием указатель должен быть инициирован либо конкретным адресом, либо значением NULL (0) – отсутствие указателя.

С указателями связаны две унарные операции: & и *. Операция & означает «взять адрес», а операция разадресации * – «значение, расположенное по адресу».

Пример 5.1. Объявление и использование указателей.

int x, *y; //х – переменная типа int, у – указатель типа int

y = &x; // y – содержит адрес переменной x

*y = 1; // по адресу y записать 1, в результате x = 1

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

Операции сложения, вычитания и сравнения (больше/меньше) имеют смысл только для последовательно расположенных данных – массивов. Операции сравнения «==» и «!=» имеют смысл для любых указателей, т.е. если два указателя равны между собой, то они указывают на одну и ту же переменную.

5.2. Связь указателей с массивами

Указатели и массивы тесно связаны между собой. Идентификатор массива является указателем на его первый элемент, т.е. для массива int a[10], выражения a и a[0] имеют одинаковые значения, т.к. адрес первого (с индексом 0) элемента массива – это адрес начала размещения его элементов в памяти.

Пример 5.2. Пусть объявлены – массив из 10 элементов и указатель типа double:

double a[10], *p;

если p = a; (установить указатель p на начало массива a), то следующие обращения: a[i] , *(a+i) и *(p+i) эквивалентны, т.е. для любых указателей можно использовать две эквивалентные формы доступа к элементам массива: a[i] и *(a+i). Очевидна эквивалентность следующих выражений:

&a[0]  &(*p)  p

Декларация многомерного массива:

тип ID[размер 1][размер 2]…[размер N];

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

Пример 5.3. Объявления многомерного массива:

int a[2][3] = {{0,1,2},{3,4,5}};

такой массив в оперативной памяти будет размещен следующим образом: a[0][0]=0, a[0][1]=1, a[0][2]=2, a[1][0]=3, a[1][1]=4, a[1][2]=5.

Если в списке инициализаторов данных не хватает, то соответствующему элементу присваивается значение 0.

5.4. Указатели на указатели

Связь указателей и массивов с одним измерением справедливо и для массивов с большим числом измерений.

Если рассматривать массив (int a[2][3];) как массив двух массивов размерностью по три элемента каждый, то обращение к элементу а[i][j] соответствует эквивалентное выражение *(*(а+i)+j), а объявление этого массива с использованием указателей будет иметь вид:

int **а;

Таким образом, имя двухмерного массива – идентификатор указателя на указатель.

5.5. Динамическое размещение данных

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

- void *malloc(size) и void *calloc(n, size) – выделяют блок памяти размером size и n х size байт соответственно; возвращают указатель на выделенную область, при ошибке – значение NULL;

- void free(bf); – освобождает ранее выделенную память с адресом bf.

Пример 5.4. Динамическое размещение одномерного массива. Ввести массив действительных чисел размером n и вывести на экран.

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

int main() { int i,n; double *a;

puts(“\n Введите размер массива n:”); scanf(“%d”,&n); a=(double*)calloc(n,sizeof(double)); // Захват памяти printf(“\n Введите элементы массива a: \n”);

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

scanf(“%lf”,(a+i)); // scanf(“%lf”,&a[i]);

printf(“\n Массив a \n”);

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

printf(“ %6.3lf \n“, a[i]);

free(a); // Освобождение памяти

getch();

}

Пример 5.5. Динамическоее размещение двухмерного массива. Ввести массив действительных чисел размером n x m и вывести на экран.

#include<stdio.h>

#include<stdlib.h>

#include<conio.h>

int main(void) {

int i,j,n,m; float **a;

puts(“\n Введите n,m:”);

scanf(“%d %d”,&n,&m);

a=(float **)calloc(n,sizeof(float*)); // Захват памяти n x m

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

a[i]=(float *)calloc(m,sizeof(float));

for (i=0;i<n; i++) // сканирование элементов массива n x m

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

{

scanf(" %f",&a[i][j]);

printf(“ %6.3lf \n“, a[i][j]);

}

for(i=0; i<n; i++) free(a[i]); // Освобождение памяти

free(a);

getch();

}

Порядок выполнения лабораторной работы

1) Запустить программу Dev-C++.

2) Составить алгоритм решения задачи по работе с двумерным динамическим массивом в соответствие с индивидуальным заданием.

3) Составить программу решения индивидуального задания по работе с двумерным динамическим массивом.

4) Выполнить пошаговую отладку программы (Debug) с использованием слежения за переменными (Add Watch).

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

Индивидуальные задания

В двухмерном целочисленном массиве (размеры массива N, M и значения его элементов вводить с клавиатуры) найти указанное значение. Значение элементов массива вводит пользователь. Массив в памяти разместить динамически.

1) Найти сумму элементов, расположенных на главной диагонали.

2) Найти произведение элементов, расположенных на главной диагонали.

3) Найти максимальный элемент и поменять его с первым элементом.

4) Найти минимальный элемент и поменять его с первым элементом.

5) Найти максимальный элемент и поменять его с последним элементом.

6) Найти минимальный элемент и поменять его с последним элементом.

7) Найти количество отрицательных и положительных элементов массива.

8) Найти количество 0-й и 1-ц в массиве, а также сумму единиц.

9) Найти число элементов массива, больших T (вводится с клавиатуры) и просуммировать эти элементы.

10) Найти число элементов массива > Т и их произведение.

11) Найти число элементов массива < T и их сумму.

12) Найти число элементов массива < T и перемножить эти элементы.

13) Найти число элементов массива = T и сложить эти элементы.

14) Найти число элементов массива = T и перемножить эти элементы.

15) Найти максимальный элемент среди лежащих ниже главной диагонали.

16) Найти минимальный элемент среди лежащих выше главной диагонали.

Контрольные вопросы

1) Дайте определение понятию «указатель».

2) Приведите пример объявления и использования указателей.

3) Приведите пример объявления многомерного массива.

4) Что такое указатель на указатель и для чего он используется?

5) Какие основные функции используются для работы с динамической памятью?