Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab_10.doc
Скачиваний:
13
Добавлен:
16.11.2019
Размер:
75.26 Кб
Скачать

ЛАБОРАТОРНА РОБОТА № 10

Тема: Вказівники і масиви

Мета: отримання практичних навичок в роботі із вказівниками і з адресною арифметикою в мові C++.

Завдання для виконання

Виконати завдання лабораторної роботи №8 з такими додатковими умовами:

  • розмір масиву визначається на початку виконання програми як випадкове число в діапазоні 50 - 200;

  • у тексті програми забороняється застосовувати операцію індексації.

Приклад рішення задачі

№ варіанту

Розмірність масиву

Діапазон значень

Що треба зробити

30

100

-50 - 50

У усіх послідовностях негативних чисел обмежити значення тих елементів, абсолютне значення яких перевищує абсолютне середнє для цієї послідовності

Розробка алгоритму рішення.

На початку виконання, після ініціалізації датчика випадкових чисел, треба отримати випадкове число в діапазоні 50 - 200 (назвемо його size) і виділити пам'ять для масиву цілих чисел розміром size. Перед самим виходом з програми ми повинні звільнити виділену пам'ять.

Простіше за усе завдання могло б бути виконано простою заміною в усіх місцях операції індексації на операцію адресації, маючи на увазі тотожність:

Ar[i] *(Ar+i)

Це відповідало б букві завдання, але не духу мови C. Якщо ми переходимо від індексації до адресації, у нас усувається необхідність в індексах і навіть в змінних, які їх представляють. Це призводить до іншого способу реалізації усіх циклів. Якщо ім'я масиву Ar є покажчиком на його початок, то замість циклу, в якому індекс i міняється від 0 до size, ми можемо організувати цикл, в якому деякий поточний покажчик Cr міняється від Ar до Ar+size. Також, коли нам треба запам'ятати початок негативної послідовності, ми можемо запам'ятовувати не індекс відповідного елементу, а його адресу - покажчик на нього.

Визначення змінних програми

Пам'ять для масиву цілих чисел в нашій роботі не виділяється на етапі компіляції, так що нам досить оголосити в програмі тільки змінну - покажчик на початок масиву :

int *Ar;

Розмірність масиву визначається при виконанні програми, так що для її збереження потрібна окрема змінна:

int size;

Замість змінних, які є індексами елементів масиву, ми застосовуватимемо покажчики:

int *Cr; це буде покажчик на поточний елемент масиву при його повному переборі;

int *Ir; у цьому покажчику зберігатиметься адреса початку негативної послідовності, а потім - при обробці послідовності - адреса поточного її елементу.

Змінні для збереження суми елементів і середнього значення і кількості елементів в послідовності:

int av;

int nn;

Розробка тексту програми

Підключаємо заголовні файли:

# #include <stdio.h>

# #include <time.h>

# #include <stdlib.h>

включаємо також файл alloc.h, в якому знаходяться описи функцій динамічного виділення/звільнення пам'яті :

# #include <alloc.h>

Починаємо головну функцію і оголошуємо в ній змінні. Кодова частина програми починається з ініціалізації датчика випадкових чисел і отримання випадкового числа для розміру масиву :

randomize();

size=random(151)+50;

Функція rand повертає нам число в діапазоні 0 - 150, збільшенням до нього 50 ми переводимо його в діапазон 50 - 200. Отриманий розмір масиву відразу виводиться на екран:

printf("size =%d\n", size);

Звертаємося до функції виділення пам'яті :

Ar=(int far *) malloc(size*sizeof(int));

Функція malloc() вимагає параметр - розмір запитаної пам'яті в байтах. Змінна size - це кількість елементів в масиві; для завдання розміру пам'яті в байтах множимо її на розмір одного елементу. Функція malloc() повертає покажчик, що не типізується, ми перетворимо його в покажчик на int і записуємо в змінну Ar.

Далі організовуємо цикл перебору масиву. У одному циклі і отримуємо випадкові числа, і виводимо початковий масив на екран. Заголовок цього циклу :

for (Cr=Ar; Cr<Ar+size; Cr++){

У початкових установках циклу ми записуємо в змінну Cr адресу початку масиву, тобто Cr показує на елемент з індексом 0. У кінці кожної ітерації Cr збільшується на 1, тобто показує на наступний елемент масиву. Остання ітерація відбувається при значенні Cr=Ar+size - 1, тобто Cr показуватиме на останній елемент. У кожній ітерації ми звертаємося до поточного елементу масиву як *Cr, тобто звертаємося до того, на що показує покажчик Cr.

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

У тілі циклу до поточного елементу масиву ми звертаємося через покажчик на нього: *Cr. Там, де нам вимагається запам'ятати початок негативної послідовності, ми просто зберігаємо поточне значення покажчика Cr в змінній-покажчику Ir.

Внутрішній цикл, в якому обробляється негативна послідовність, :

for (av/=nn; Ir<Cr; Ir++)

if (*Ir<av) *Ir=av;

Початкові установки цього циклу - тільки усереднювання значення в av, змінна Ir вже містить в собі покажчик на перший елемент негативної послідовності. У кінці кожної ітерації Ir збільшується на 1, тобто показує на наступний елемент послідовності (звернення до цього елементу - *Ir). Остання ітерація відбувається при значенні Ir=Cr - 1, оскільки Cr показує на перший позитивний елемент за негативною послідовністю.

Передостанній оператор - звернення до функції free() для звільнення пам'яті, яка була виділена функцією malloc(), : free(Ar);

Повний текст програми приведений нижче.

/****************************************************/

/* /* Лабораторна робота ╧11 */

/* /* Покажчиків і масиви */

/* /* Приклад виконання. Варіант ╧30. */

/****************************************************/

##include <stdio.h>

##include <time.h>

##include <stdlib.h>

##include <alloc.h>

int main(void){

int size; /* розмір масиву */

int *Ar; /* покажчик на початок масиву */

int *Cr, *Ir; /* поточних покажчиків */

int av, nn; /* середнє значення і

кількість елементів в послідовності */

randomize(); /* ініціалізація rand */

size=random(151)+50;

printf("size =%d\n", size);

/* /* виділень пам'яті */

Ar=(int far *) malloc(size*sizeof(int));

/* /* заповнення масиву випадковими числами і

виведення початкового масиву */

printf("Початковий масив:\n");

for (Cr=Ar; Cr<Ar+size; Cr++){

* *Cr=random(101) - 50;

printf("%3d ",*Cr);

}

putchar('\n');

/* /* перебір масиву */

for (nn=0, Cr=Ar; Cr<Ar+size; Cr++){

if (*Cr<0)

/* /* обробка негативного елементу */

if (!nn){

/* /* початок послідовності : запам'ятати адресу

почала в Ir, встановити початкове значення

накопичувача суми і лічильнику елементів */

Ir=Cr; av=*Cr; nn=1;

}

else {

/* /* підрахунок суми і кількості елементів */

av+=*Cr; nn++;

}

/* /* кінець обробки негативного елементу */

else /* обробка позитивного елементу */

if (nn){

/* /* якщо є необроблена негативна послідовність:

усереднювання і перебір з обмеженням */

for (av/=nn; Ir<Cr; Ir++)

if (*Ir<av) *Ir=av;

nn=0; /* послідовність оброблена */

} /* кінець якщо необроблена.. */

} /* кінець перебору масиву */

if (nn) /* якщо не оброблена остання

негативна послідовність */

for (av/=nn; Ir<Cr; Ir++)

if (*Ir<av) *Ir=av;

/* /* виведення результатів */

printf("Масив-результат:\n");

for (Cr=Ar; Cr<Ar+size; printf("%3d ",*Cr++));

putchar('\n');

/* /* звільнення пам'яті */

free(Ar);

return 0;}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]