Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичні_рекомендації_практика_навчальна.doc
Скачиваний:
54
Добавлен:
07.02.2016
Размер:
7.54 Mб
Скачать

1 Теоретичні відомості

1.1 Практика з програмування на персональному ком’пютері

Алгоритмічна конструкція розгалуження.

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

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

Повна форма:

Умовний оператор.

Умовний оператор має скорочену і повну форму запису.

if (умова) оператор; //скорочена форма

В якості умови можуть використовуватися арифметичні вирази, відношення і логічні вирази.

Якщо значення умови не нульове (тобто правдиве), то виконується оператор. Наприклад:

if (x<y&&x<z)min=x;

if ( умова ) оператор1; //повна форма

else оператор2;

Якщо значення умови не нульове, то виконується оператор1, а при нульовому значенні умови виконується оператор2. Наприклад:

if (d>=0)

{

x1=(-b-sqrt(d))/(2*a);

x2=(-b+sqrt(d))/(2*a);

cout<< “\nx1=”<<x1<<“x2=”<<x2;

}

else cout<<“\nРешения нет”;

Алгоритмічна конструкція циклу.

Цикл – управляюча структура, що організує багатократне виконання вказаних дій.

Розрізняють:

  1. Цикл з передумовою.

+

дія

  1. Цикл з післяумовою.

дія

+

  1. Цикл с параметром.

дія

2 Оператори циклу мови програмування С++.

1. Цикл з передумовою

while (умова)

оператор;

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

Приклад:

while (a!=0)

{

cin>>a;

s=s+a;

}

2. Цикл з післяумовою:

do

оператор

while (умова);

Тіло циклу виконується до тих пір доки умова правдива.

Приклад:

do

{

cin>>a;

s=s+a;

}

while(a!=0);

3. Цикл з параметром:

for (вираз_1;умова;вираз_3)

оператор;

Вираз_1 и вираз_3 можуть складатися з декількох виразів, розділених комами. Вираз_1 – задає початкову умову для циклу (ініціалізація). Умова визначає умову виконання циклу, якщо воно не дорівнює 0, цикл виконується, а потім виконується вираз_3. Вираз_3 задає зміну параметру циклу або інших змінних (корекція). Цикл виконується до тих пір, доки умова не стане 0. Будь-який вираз може бути відсутнім, але «;», що їх розділяє повинна бути обов’язково.

Приклади:

for ( n=10; n>0; n--)

{ оператор};

число ітерацій:

for ( num=1;num*num*num<216; num++)

{ оператор };

Зі збільшення об’єму програм не можливо в пам’яті утримувати всі деталі. Щоб зменшити складність програми її розбивають на частини. У С++ задача може бути розділена на під задачі за допомогою функцій. Розділення задачі також дозволяє позбутися надлишку коду, так як функція записується один раз, а викликається багатократно.

Функція – це іменована послідовність описів і операторів, що виконують закінчену дію.

Будь-яка функція повинна бути оголошена і визначена.

Оголошення функції (прототип, заголовок) задає ім’я змінної, тип значення, повертається і список параметрів, що передаються.

Масив – це впорядкована послідовність змінних одного типа. Кожному елементу масиву відводиться один елемент пам'яті. Елементи одного масиву займають послідовно розташовані елементи пам'яті. Всі елементи мають одне ім'я - ім'я масиву і відрізняються індексами – порядковими номерами в масиві. Кількість елементів в масиві називається його розміром. Щоб відвести в пам'яті потрібну кількість вічок для розміщення масиву, треба заздалегідь знати його розмір. Резервування пам'яті для масиву виконується на етапі компіляції програми.

Визначення масиву в Си/Си++:

int а[100];//массив з 100 елементів цілого типа

Щоб звернутися до елементу масиву, треба вказати ім'я масиву і номер елементу в масиві (індекс):

а[0] – індекс задається як константа,

а[55] – індекс задається як константа,

а[I] – індекс задається як змінна,

а[2*i] – індекс задається як вираження.

Елементи масиву можна задавати при його визначенні:

int а[10]={1,2,3,4,5,6,7,8,9,10} ;

int а[10]={1,2,3,4,5};

Якщо кількість початкових значень менша, ніж оголошена довжина масиву, то початкові елементи масиву отримають лише перші елементи.

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

Довжина масиву розраховується компілятором по кількості значень, перерахованих при ініціалізації.

Багатовимірний масив це масив, елементами якого служать масиви.

Ініціалізація багатовимірних масивів виконується аналогічно одновимірним масивам. Приклади:

int а[3][4]= {{11,22,33,44},{55,66,77,88},{99,110,120,130}}; //проініціалізовані всі елементи масиву

int b[3][4]= {{1},{2},{3}};

// проініціалізовані перші елементи кожного рядка

int с[3][2]={1,2,3,4,5,6}; // проініціалізовані всі елементи масиву

При традиційному визначенні масиву: тип ім'я_масиву [кількість_елементів]; загальна кількість пам'яті, виділюваної під масив, задається визначенням і дорівнює кількість_елементів * sizeof(тип).

Але іноді буває потрібно щоб пам'ять під масив виділялася для рішення конкретного завдання, причому її розміри заздалегідь не відомі й не можуть бути фіксовані.

Формування масивів зі змінними розмірами можна організувати за допомогою покажчиків і засобів динамічного розподілу пам'яті двома способами:

  1. с використанням бібліотечних функцій, описаних у заголовних файлах alloc.h й stdlib.h (стандартний Си);

  2. с використанням операцій new й delete (Си++).

Покажчик - це змінна, значенням якої є адреса деякого об'єкта (звичайно іншої змінної) у пам'яті комп'ютера.

Загальна форма оголошення покажчика наступна:

тип *ім'я;

У мові З визначені дві операції для роботи з покажчиками: * й &.

Оператор & - це унарний оператор, що повертає адресу свого операнда. Наприклад, оператор

m = &count;

привласнює змінній m адреса змінної count.

Оператор * - це унарний оператор, що повертає значення змінної, розташованої по зазначеній адресі. Наприклад, оператор

q = *m;

привласнює змінної q значення змінної count.

У мові С припустимі тільки чотири арифметичні операції над покажчиками: інкрементування, декрементування, додавання із числом, вирахування. Наприклад, що випливають операції над покажчиками p1 й p2 припустимі:

p1++; p1--; p1+7; p1-p2;

Покажчик завжди вказує на перший байт об'єкта. Після збільшення (зменшення) покажчик посилається на наступний об'єкт такого ж типу.

Стандартом С допускається порівняння двох покажчиків. Наприклад, якщо оголошені два покажчики р и q, те наступний оператор є правильним:

if(p < q) printf("p посилається на меншу адресу, чим q\n");

Як правило, порівняння покажчиків може виявитися корисним, тільки тоді, коли два покажчики посилаються на загальний об'єкт, наприклад, на масив.

Поняття покажчиків і масивів тісно зв'язані. Розглянемо наступний фрагмент програми:

char str[80], *p1;

p1 = str;

Тут p1 указує на перший елемент масиву str. Звернутися до п'ятого елемента масиву str можна за допомогою кожного із двох виражень:

str[4]

* (p1+4)

У мові С існують два методи звертання до елемента масиву: адресна арифметика й індексація масиву. Розглянемо два приклади реалізації однієї й тієї ж функції, що виводить рядок на екран:

Приклад

void putstr(char *s) // Індексація покажчика s як масиву.

{

for(int t=0; s[t]; t++) putchar(s[t]);

}

void putstr(char *s) // Використання адресної арифметики

{

while(*s) putchar(*s++);

}

Покажчики використовуються для динамічного виділення пам'яті комп'ютера для зберігання даних. Основу системи динамічного розподілу в Зі становлять функції malloc() і free().Функція malloc() виділяє пам'ять, а free() - звільняє неї. У програму, що використає ці функції, повинен бути включений заголовний файл <stdlib.h>.

Прототип функції malloc:

void *malloc(кількість_байтів);

Для підвищення мобільності використається оператор sizeof. У наступному прикладі виділяється пам'ять для 50 цілих:

int *p;

p = (int *) malloc(n*sizeof(int));

Тому що функція malloc повертає результат типу void необхідно явне перетворення типів (int *). Оператор sizeof(int) повертає кількість байтів, що приділяються на тип int тобто 4

Функція free() має наступний прототип:

void free(void *p)

Тут р - покажчик на ділянку пам'яті, виділена перед цим функцією malloc(). Функцію free() у жодному разі не можна викликати з неправильним аргументом, це миттєво зруйнує всю систему розподілу пам'яті.

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

int (*p)[10];

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

Формування динамічних масивів з використанням бібліотечних функцій

Для виділення й звільнення динамічної пам'яті використаються функції

Функція

Прототип і короткий опис

malloc

void * malloc(unsigned s)

Повертає покажчик на початок області динамічної пам'яті довжиною в s байт, при невдалому завершенні повертає NULL

calloc

void * calloc(unsigned n, unsigned m)

Повертає покажчик на початок області динамічної пам'яті для розміщення n елементів довжиною по m байт кожний, при невдалому завершенні повертає NULL

realloc

void * realloc(void * p, unsigned s)

Змінює розмір блоку раніше виділеної динамічної пам'яті до розміру s байт, р- адреса початку змінюваного блоку, при невдалому завершенні повертає NULL

free

void *free(void p)

Звільняє раніше виділену ділянку динамічної пам'яті, р - адреса першого байта

Приклад:

Функція для формування одномірного динамічного масиву

int * make_mas(int n)

(

int *mas;

mas=(int*)malloc(n*sizeof(int));

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

mas[i]=random(10);

return mas;

}

Для виділення пам'яті використається функція malloc, параметром якої є розмір виділюваної ділянки пам'яті рівний n*sizeof(int). Тому що функція malloc повертає нетипізований покажчик void*, те необхідно виконати перетворення отриманого нетипізованого покажчика в покажчик int*.

Звільнити виділену пам'ять можна функцією free(mas).

Формування динамічних масивів з використанням операцій new й delete

Для динамічного розподілу пам'яті використаються операції new й delete. Операція

new ім'я_типу

або

new ім'я_типу инициализатор

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

Приклади:

1) int *i;

i=new int(10);

2) float *f;

f=new float;

  1. int *mas=new[5];

У прикладах 1, 2 показано як виділити пам'ять під скалярні змінні, приклад 3 показує виділення пам'яті під масив змінних.

Операція delete покажчик звільняє ділянку пам'яті раніше виділений операцією new.

Приклад:

Функція для формування двовимірного динамічного масиву

int ** make_matr(int n)

{

int **matr;

int i,j;

matr=new int*[n];

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

{

matr[i]=new int[n];

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

matr[i][j]=random(10);

}

return matr;

}

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

**matr

*matr[1]

*matr[2]

*matr[3]

. . . .

*matr[n]

Щоб звільнити пам'ять необхідно виконати цикл для звільнення одномірних масивів

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

delete matr[i];

Після цього звільняємо пам'ять на яку вказує покажчик matr

delete [] matr;