Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Methods_AP_LABS_II

.pdf
Скачиваний:
17
Добавлен:
17.03.2016
Размер:
1.05 Mб
Скачать

5.1.7 Передача масивів у функції

Одномірні масиви

Масиви можуть бути параметрами функцій, і функції як результат можуть повертати вказівник на масив. Розглянемо ці можливості.

Якщо в якості параметра функції передається лише ім’я масиву, то виникає необхідність визначення в тілі функції кількості елементів масиву.

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

визначити ще пару параметрів – вказівник на перший елемент результуючого масиву (ім’я масиву) і його розмірність.

При роботі з рядками — масивами типу char[], проблема розв'язується просто, оскільки останній елемент рядка має значення '\0'. Тому при обробці масиву-аргументу кожен його елемент аналізується на наявність символу кінця рядка.

Потрібно скласти програму, що містить функцію, яка підраховує кількість елементів у рядку. Можливий варіант програми має вид (лістинг

5.9):

Лістинг 5.9

//Масиви у функціях

#include <iostream>;

using namespace std;

int dl(char[]);//прототип функції dl int main()

{

char p[]="кафедра";

cout << "\n Довжина рядка дорівнює:" << dl(p); return 0;

}

int dl(char c[])

{

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

if (c[i]=='\0') break; return i;

}

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

Довжина рядка дорівнює: 7.

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

Нехай потрібно скласти програму, у якій функція обчислює суму елементів масиву, що складає з 5 елементів. Можливий варіант програми має вид (лістинг 5.10):

Лістинг 5.10

// Одномірний масив як параметр

#include <iostream>

using namespace std;

int sum(float x[5])

{

float s=0;

for(int i=0;i<5;i++) s=s+x[i]; return s;

}

int main()

{

float z[5], y; for(int i=0;i<5;i++)

{

cout<<"\n Введіть черговий елемент масиву:";

cin >> z[i];

}

y=sum(z);

cout<<"\n Сума елементів масиву:”<< y;

return 0;

}

Урезультаті виконання програми на екран буде виведене значення суми елементів масиву z.

Уприведеному прикладі заздалегідь відоме число елементів — 5, тому

уфункції всього один параметр — масив x. Оскільки у функції існує значення, що повертається, то виклик функції може бути тільки виразом чи частиною виразу. У програмі оператор присвоювання y=sum(z); містить такий вираз у правій частині. Тут аргументом функції є масив z.

Нехай потрібно скласти програму зі звертанням до функції, яка повертає максимальний елемент одномірного масиву з довільною кількістю елементів (лістинг 5.11).

Лістинг 5.11

// Пошук максимального елемента

#include <iostream>

using namespace std;

float max(int n,float a[])

{

float m=a[0]; for(int i=1;i<n;i++) if (m<a[i]) m=a[i]; return m;

}

int main()

{

float z[6];

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

{

cout<<"\n Введіть черговий елемент масиву:"; cin >> z[i];

}

cout <<"\n Максимальний елемент масиву:"<< max(6,z); return 0;

}

У результаті виконання програми на екран монітора буде видане повідомлення зі значенням максимального елемента масиву z, який у даному прикладі складається із шести елементів.

Ім'я масиву являє собою константний вказівник на адресу нульового елемента масиву. Тому у будь-якого масиві, використовуваного як параметр функції, можна здійснювати зміну його елементів при виконанні тіла функції.

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

(лістинг 5.12):

Лістинг 5.12

//Вказівники на масив як параметри

#include <iostream>

using namespace std;

void maxl(int,int*,int*,int*); // прототип функції int main()

{

int a[] = {0,1,2,3,4}; int b[]={5,6,0,7,1}; int d[5]; maxl(5,a,b,d) ;

cout << "\n";

for (int i=0;i<5;i++) cout << "\t" << d[i]; return 0;

}

void maxl(int n,int *x,int *y,int *z)

{

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

z[i]=x[i]>y[i] ? x[i]:y[i];

}

У результаті виконання програми на екран монітора будуть видані елементи результуючого масиву d: 5 6 2 7 4.

Багатовимірні масиви

Особливістю мови С++ є несамовизначеність масивів, тому за іменем масиву неможливо довідатися його розмірність і розміри за кожним виміром.

Крім того, у С++ багатовимірні масиви не визначені. Наприклад, якщо оголошений масив float d[3][4][5], те це не тривимірний, а одномірний масив d, що включає три елементи, кожний з який має тип float [4][5]. У

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

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

(ця мірність повинна бути самою лівою).

Нехай потрібно скласти програму з функцією, що підраховує суму елементів матриці (лістинг 5.13).

Лістинг 5.13. Двовимірний масив як параметр функції

#include <iostream>

using namespace std;

float summa(int n,float a[][3])

{

float s=0;

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

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

s=s+a[i][j];

return s;

}

void main()

{

float z[4][3]={0,1,2,3,4,5,6,7,7,6,5,4 };

cout<< "\n Сума елементів матриці дорівнює" << summa(4,z);

}

У результаті виконання програми на екран буде виведене повідомлення: “Сума елементів матриці дорівнює 50”.

Потрібно скласти програму з функцією, що повертає як результат мінімальний елемент матриці розміром mxn.

Можливий варіант програми має вид (лістинг 5.14):

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

#include <iostream> using namespace std;

float min(int k, int t, float **p); int main()

{

int m,n; float **r; cin>>m>>n;

r=new float*[m];

for (int i=0;i<m;i++) r[i]=new float[n]; for (int i=0;i<m;i++) for (int j=0;j<n;j++)

cin>>r[i][j];

cout <<"\n Мінімальний елемент матриці дорівнює "<< min(m,n,r);

for (int i=0;i<m;i++) delete []r[i];

delete []r; return 0;

}

float min(int k, int t, float **p)

{

float x=p[0][0];

for (int i=0;i<k;i++) for (int j=0;j<t;j++)

if (x>p[i][j]) x=p[i][j]; return x;

}

Інший варіант цієї програми з використанням допоміжного масиву

вказівників на масив як параметр функції (лістинг 5.15):

Лістинг 5.15

#include <iostream> using namespace std;

float min(int m,int n,float *p[]); int main()

{

float d[3][4]={1,2,-2,4, 5,0,-3,18, -9,6,7,9};

float *r[]=

{

d[0], d[1], d[2] };

int m=3; int n=4;

cout <<"\n Мінімальний елемент матриці дорівнює "<< min(m,n,r);

return 0;

}

float min(int m,int n,float *p[])

{

float x=p[0][0];

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

if (x>p[i][j]) x=p[i][j]; return x;

}

5.1.8 Вказівники на функцію

З функціями можна роботи дві речі: викликати та отримати її адресу.

Вказівник, отриманий шляхом взяття адреси функції, можна використовувати для її виклику. Наприклад:

void error (string s) {/*... */}

void (*efct) (string); // вказівник на функцію

void f()

{

efct = &error; // efct вказує на функцію error efct("помилка"); // виклик функції error через

вказівник efct

}

Компілятор розпізнає, що efct є вказівником та викликає функцію, на яку він вказує. Тобто, розіменування вказівника на функцію за допомогою оператора * не є обов’язковим. Аналогічно, необов’язково використовувати

& для отримання адреси функції:

Аргументи вказівників на функцію оголошуються таким самим чином,

як і аргументи самих функцій. При присвоюванні типи функцій повинні точно співпадати. Наприклад:

void (*pf) (string); // вказівник на void(string) void f1 (string); // void(string)

int f2 (string); // int(string) void f3 (int*); // void(int*)

void f*(){

pf = &fl; // коректно

pf = &f2; // помилка: не той повертаємий тип pf = &f3; // помилка: не той тип аргументу pf(“НТУУ КПІ”); //коректно

pf(0); // помилка: не той тип аргументу

int i = pf(“НТУУ КПІ”); // помилка: присвоювання void змінній int

}

Правила передачі аргументів при виклику функцій через вказівники ті самі, що і при безпосередньому виклику функцій.

Дуже часто корисно використовувати масив вказівників на функції. Це може бути, наприклад, система меню в редакторі. Вона може бути реалізована з використанням масиву вказівників на функції, які виконують відповідні операції. Розглянемо загальну ідею.

typedef void (*PF) ();

PF edit_ops[] = { // команди редагування

&cut, &paste, &copy, search };

PF file_ops[] = { // файлові операції

&open, &append, &close, &write };

Тепер ми можемо визначити та ініціалізувати вказівники для дій, які вибираються із меню та зв’язані з ними кнопками:

PF* button2 = edit_ops;

PF* button3 = file_ops;

Тобто при натисканні кнопки button2 будуть ініціалізовані команди редагування тексту, а button3 — файлові операції. Коли користувач вибере пункт меню, наприклад пункт 3, з нажатою кнопкою 2, буде виконана наступна операція (виклик відповідної функції):

button2[2](); // виклик третьої функції button2,

тобто copy()

5.1.9 Засоби аналізу продуктивності програм

При написанні складних програмних систем часто виникає задача оптимізації її функціонування, наприклад, за часом виконання та використаною пам’яттю. Для того, щоб визначити «вузькі місця» програми,

що розробляється, необхідно використовувати спеціальні засоби, за допомогою яких можна проаналізувати її продуктивність. Такі засоби називаються профайлерами (profiling programs).

Одним із популярних профайлерів є програмний продукт Intel® VTune™ Performance Analyzer. Даний засіб не залежить від компілятора та може застосовуватися для програм, які написано на різних мовах програмування, наприклад, C, C++, Fortran, C#, Java, тощо. Варто відзначити,

що існують версії цього продукту для різних операційних систем, зокрема

Windows та Linux.

5.2 Практичні завдання

Реалізувати наступні завдання з використанням статичних та динамічних масивів. Для доступу до елементів динамічного масиву використати два підходи: через явне розіменування вказівника та через індекси.

1. Знайти мінімальний елемент матриці заданого розміру та добуток всіх її додатних елементів.

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