Cin.Getline ( mainstr, m);

cout << "Введіть підрядок" << endl;

Cin.getline ( substr, m);

cout << "Головний рядок: " << mainstr << endl;

cout << "Підрядок: " << substr << endl;

pt = strstr ( mainstr, substr );

cout << "Номер входу підрядка в рядок" << endl;

While (pt)

{

k++;

n = pt - mainstr;

cout << k << " n = " << n << endl;

pt = strstr( ++pt, substr );

cout << k << " ." << *pt << endl;

}

if ( k == 0) cout <<"Підрядок не міститься в рядку" << endl;

}

Приклад 3.8 Знайти заданий символ у рядку.

//P3_8.CPP пошук символів у рядку

#include <string.h>

#include < iostream>

Using namespace std;

Main( )

{

const int m = 25;

char sim, *pt, str[m];

int n, k = 0;

cout << "Введіть рядок" << endl;

Cin.get ( str, m );

cout << "Введіть символ" << endl;

cin >> sim;

pt = strchr ( str, sim );

cout << "Позиції входу символу в рядок" << endl;

While (pt)

{

k++;

n = pt - str;

cout << k << " n = " << n << endl;

pt = strchr(++pt, sim);

}

cout << "К-кість входжень="<<k<<endl;

if(k==0) cout << "Символ не входить у рядок" << endl;

Return 0;

}

Приклад 3.9 Ввести список прізвищ і вивести прізвища які починаються з літер "П" і "Ф" і закінчуються на "ко"

//P3_9.CPP вивести зі списку прізвища, що починаються з

// літер "П" і "Ф" і закінчуються на "ко"

#include <string.h>

#include < iostream>

Using namespace std;

Void main(void)

{

const int n = 5;

char gr [ 5 ] [15], s2[2] = {"оk"};

int і;

cout << "Введіть прізвища" << endl;

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

cin >> gr[i];

cout << "Список прізвищ" << endl;

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

cout << gr[i] << endl;

Strrev ( s2 );

cout << "Прізвища на П и Ф" << endl;

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

if ( ( ( gr [і] [0] == 'П') || ( gr [і] [0] == 'Ф') )

&& ( strncmp ( strrev ( gr[i] ), s2 ,2) == 0))

cout << strrev( gr[i] ) << endl ;

}

3.2 Контрольні питання і завдання

1. Що являє собою значення символьного типу?

2. Як задається тип символьних даних?

3. Що являє собою масив символьного типу?

4. Як уводяться строкові значення?

5. Як порівняти дані строкового типу?

6. Яке строкове дане більше “стіл” або “стілець”?

7. Наведіть приклад використання операції конкатенації?

8. Як визначити кількість символів вхідних у строкове дане?

9. Які функції мови С++ використовуються для виділення підрядку з рядка?

3.4 Варіанти індивідуальних завдань

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

1. Слова в тексті розділені проміжками. Підрахувати кількість слів , які починаються з літер “Do” і “dо”.

2. З тексту вивести слова, що починаються і закінчуються на однакові літери(літеру).

3. З речення вивести саме довге слово.

4. З списку прізвищ вивести прізвища, що починаються і закінчуються на однакові літери(літеру).

5. Визначити, скільки разів літера “а” повторюється у введеному тексті.

6. Ввести текст зі свідомо великою кількістю проміжків між словами. Програмним шляхом видалити з нього зайві проміжки.

7. Вивести слова тексту: “Мед у лісі ведмідь знайшов — мало меду, багато бджіл”, що починаються з літери “м”.

8. В списку з 10 прізвищ визначити саме коротке прізвище.

9. В списку з 10 прізвищ визначити саме найдовше прізвище. .

10. Визначити, на якому місці записане саме довге слово в реченні.

11. Віддрукувати слово, що складається з останніх літер усіх слів тексту.

12. З введеного тексту вивести слова, у яких немає цифр

13. З введеного тексту вивести слова, у яких немає літер “о” і “у”.

14. З введеного тексту вивести саме коротке слово.

15. Ввести список з 10 прізвищ, розташованих у довільному порядку й упорядкувати їх за алфавітом.

16. Віддрукувати слово, що складається з перших літер усіх слів тексту.

17. Виділити частину тексту між словами, що вводяться в рядку запиту.

18. Підрахувати скільки разів у вихідному тексті повторюється поєднання літер ТСМ ( або ІМЗ ).

19. Вибрати у вихідному тексті саме довге слово, що не містить сполучення “pro”.

20. Ввести невелику програму на С++. Підрахувати скільки у ній операторів “cоut”.

21. Ввести текст:

“Слава світу на Землі!

Слава хлібу на столі!

От він хлібець запашний.”

Віддрукувати окличні речення.

22. Вибрати з уведеного тексту саме коротке слово, що не містить задану приголосну.

23. Ввести текст:

“Не дозволяй душі лінуватися,

Щоб воду в ступі не товкти,

Душа зобов'язана трудитися ,

І день і ніч, і день і ніч! ”

Вивести слова, що містять літеру “о”.

24. Вибрати з вихідного тексту (див. варіант 23 ) саме довге слово, що містить голосну “і”.

25. У невеликій програмі на С++ підрахувати кількість операторів циклу for.

4 ВИРІШУВННЯ ЗАДАЧ З ВИКОРИСТАННЯМ ДАНИХ ТИПУ СТРУКТУРА

4.1 Ціль роботи

Освоєння заходів розробки і налагодження програм з використанням

даних типу структура

4.2 Методичні рекомендації з організації самостійної

роботи студентів

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

Структура — це сукупність різнотипних елементів, яким привласнюється одне ім'я ( воно може бути відсутнім), що займає одну область пам'яті. Елементи структури називаються полями.

Як і будь-яка змінна, структурна змінна повинна бути описана. Цей опис складається з двох кроків: опис шаблона (тобто складу ) або типу структури й опису змінних структурного типу.

Синтаксис опису структури має вигляд:

struct < ім'я структури >

{ <тип 1 > ім'я поля 1;

< тип 2 > ім'я поля 2. . . . . . . .;

} [ р1, р2. . . .];

де struct — службове слово;

< ім'я структури > — ім'я типу структури ;

<тип 1>, <тип 2> — імена стандартних або визначених типів;

ім'я поля 1, ім'я поля 2, … — імена полів структури;

р1, р2. . . .; — імена перемінних типу структура.

Приклад 4.1. Обробити дані про здачу студентами сесії по предметах: математиці, фізиці і програмуванні, підрахувати середній бал, отриманий студентами по цим курсам.

Визначимо структуру:

Struct stud

{

char fam [25];// прізвище і ініціали

int mat, fiz, prg; //предмети

float sb;// середній бал

} st1,st2;

Змінні st1і st2 можна оголосити окремим оператором, наприклад:

stud st1 st2;

Ініціалізація полів структури може проводитися або при її описі, або в тілі програми. При описі структури ініціалізація полів може виглядати так:

Struct stud

{ char fam [25];

Int mat,fiz, prg;

Float sb;

}

st1 = { " Кравченко И.С.", 4, 5, 5},

st2 = { "Тесленко А.М.", 3, 4, 5};

Якщо ініціалізація полів буде проведена в тілі програми, то для звертання до імен полів треба спочатку записати ім'я структурної змінної, а потім ім'я поля, що відокремлюється крапкою ( складені поля). Отже, у випадку , коли змінна st1з'являється в програмі, для її ініціалізації можна записати

stud st1 = {"Кравченко И.С.",4 ,5 ,5); або ініціалізація здійснюється за допомогою складених полів, як представлено в наступній програмі:

// Р 4_1. СPP — визначення середнього бала

// використання складених полів

#include < string.h >

#include < stdio.h >

#include < iostream>

Using namespace std;

Struct stud

{ char fam [20];

Int mat, fiz, prg;

Float sb;

} st1, st2;

Main ( )

{

strcpy (st1. fam, "Кравченко И.С.");

st1 . mat = 4;

st1. fiz = 5;

st1. prg = 5;

st1. sb = (st1. fiz + st1. mat + st1. prg) / 3;

st2 = st1;

puts (st2. fam); //Виведення прізвища st2;

cout << st2. mat << st2. fiz << st2. prg << st2. sb << endl;

Return 0;

}

У цій програмі всім полям структури st1 привласнені відповідні значення. Треба звернути увагу, що поле st1.fam одержує значення шляхом використання функції strcpy (st1.fam, "Кравченко И.С.");. Структурна змінна st2має ту ж структуру, що і st1, тому справедлива операція st2 = st1; . Якщо в одній функції використовується тільки один структурний тип, то цей тип можна повідомляти без імені. Наприклад, раніше розглянуту структуру можна оголосити в такий засіб:

Struct

{ char fam [25];

Int mat, fiz, prg;

Float sb;

} st1, st2;

Якщо при описі структур у деякій функції або в межах "видимості" змінних у різних функціях мається багато (але не усі) однакових полів, то ці однакові поля можна об'єднати в окрему структуру і використовувати її при описі інших структур, тобто поля структури можуть самі мати тип "структура". Це називається вкладеністю структур. Наприклад, якщо треба обробляти списки студентів і викладачів університету, причому в студентських списках містяться дані: прізвище і иниціали, дата ( день, місяць, рік) народження, група і середній бал успішності, а в списках викладачів обробляються такі дані: прізвище і ініціали, дата народження, кафедра, посада.

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

Struct stud

{ char fio [25];

Int den,god;

char mes [10];

Char grup;

Float sb;

}

і

Struct prep

{ char fio [25];

Int den, god;

char mes [10];

Char kaf, dolg;

}

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

— загальна структура:

Struct spd

{ char fio [25];

Int den,god;

char mes[10];

};

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

Struct stud

{ spd dr;

Char grup;

Float sb

} st1,st2;

— структура для опису інформації про викладачів:

Struct prep

{ spd dr;

char kaf [10] ;

char dolg [15];

} pr1,pr2;

У структурах stud і prep для оголошення поля, що містить дані про прізвище і дату народження використовується раніше описаний тип spd. Тепер до поля fio, den, god, mes можна звернутися, використовуючи запис наступного вигляду:

St1 . dr . fio

Наприклад, при записі функції введення — gets (st1 . dr . fio); або pr1 . dr . fio .

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

Struct stud

{ char fam [25];

Int mat, fiz, prg;

Float sb;

} st1, *pst;

Тепер доступ до полів може здійснюватися двома способами :

—використовуючи оператор (*) , наприклад,

gets ((*pst) . fam); (*pst) . fiz = 5;

використовуючи спеціальний покажчик на структуру "->", наприклад,

gets ( pst->fam); pst -> fiz = 5;і т.д.

Крім того до змінної st1 можна звертатися, указуючи поля через символ крапка, як це робилося раніше.

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

Struct stud

{ char fam [25];

Int mat, fiz, prg;

Float sb;

} spis[15], *sp = &spis[0];

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

stud spis [15]; .

Доступ до елементів масиву може виконуватися з використанням індексу або через покажчик — константу, яким є ім'я масиву:

strcpy( spis [1] . fam, " ");

spis [1] . fiz = 5;

або

strcpy ((sp +1) -> fam, " ");

(sp + 1) -> fiz = 5;

Це можна записати також у вигляді:

strcpy ((* (spis +1 )) . fam, " ");

(*(spis+1)) . fiz = 5;

Тут потрібно зовнішня пара дужок, тому що операція (.) —" крапка" має пріоритет вище, ніж операція за адресою (*).

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

Приклад 4.2. Ввести в комп'ютер відомість успішності студентів групи з 25 чоловік, які сдають сесію по предметах: фізиці, математиці, і програмуванню і підрахувати:

—середній бал, отриманий кожним студентом;

—середній бал групи за кожним предметом;

—вивести на екран відмінників по програмуванню.

Програма буде мати вигляд:

// P4_2. CPP ¾ обробка відомості успішності

// Використання даних типу структура

#include < string.h >

#include < stdio.h >

#include < iomanip >

#include < iostream >

Using namespace std;

Struct stud

{ char fam[25];

Int mat, fiz, prg;

Float sb;

};

Void main(void)

{

const k = 5;

int n = 1, i;

Float sm, sf, sp;

stud ved[k];

sm = sf = sp = 0;

cout << "Введіть прізвище й оцінки mat, fiz, prg \n " ;

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

{

gets ( ved[i]. fam );

cin >> ved[i]. mat >> ved[i]. fiz >> ved[i]. prg ;

ved[i]. sb = ( ved[i]. mat + ved[i]. fiz + ved[i]. prg) / 3;

sm += ved[i]. mat;

sf += ved[i]. fiz;

sp += ved[і]. prg;

}

cout << "\t Відомість успішності групи \n\n";

cout << "\t";

for ( i = 0; i < 47; i++) cout << "-"; //Верхня риса

cout << "\n";

cout << "\t \t прізвище\t мат фіз прогр порівн.бал \n";

for ( i = 0; i < 47; i++) cout << "-";// Верхня риса

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

{

cout << "\t" << i + 1 << " " << setw(17)

<< setiosflags ( ios :: left ) << ved[i]. fam;

cout << ved[i]. mat << " " << ved[i]. fiz <<

" " << ved[i]. prg << " " << ved[i]. sb << "\n";

}

cout << "\t";

for ( i = 0; i < 47; i++) cout << "-";// Нижня риса

cout << "\n\t" << setw(16) << setiosflags ( ios :: right )

<< "Порівн. бал";

cout << " " << sm / k << " " << sf / k << " " << sp / k << "\n\n";

cout << "\t Відмінники по програмуванню: \n\n";

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

if ( ved[i]. prg == 5)

{

cout << "\t" << n << " " << ved[i]. fam << "\n";

n++;

}

}

Результат роботи програми буде мати вигляд:

Відомість успішності студентів

_______________________________________________

прізвище мат фіз прогр порівн.бал

_______________________________________________

Авдєєв И.М. 3 4 4 3.7

Биків Т.Б. 5 5 4 4.6

Волков А.П. 4 5 5 4.6

_______________________________________________

Порівн. бал 3.8 4.6 4.8

Відмінники по програмуванню:

Волков А.П.

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

Struct stud1

{ char fam [25];

int pr [3];

Float sb

} st1 [10], *pst = &st1 [0]; ,

тепер до полів можна звертатися одним з наступних способів:

((*pst). fam)// gets (( *pst) .fam);

( pst -> pr [0] ) // cin >> pst -> pr[0] >> pst -> pr[1];

// або cin >> pst -> * (pr +1).

У бібліотеці <stdlib.h> для пошуку і сортування структурних змінних маються спеціальні функції. Так , функція швидкого сортування структурних елементів масиву по заданому полю має вигляд :

#include < stdlib.h >

void qsort (void *base , n , width,

int (* fcmp ) (const void *elem 1, const void -> elem2)) ,

де base— покажчик на перший елемент масиву;

n— кількість елементів масиву;

width -довжина елементів масиву в бітах.

При виконанні сортування функція qsort( ) звертається до заданого користувачем функції.

Функція задається покажчиком на функцію:

int (*fcmp) ( const void *elem1, const void *elem2) .

Функція, на яку вказує fcmp , виконує порівняння двох елементів масиву, на які вказує elem1 і elem2.

Функція повинна повертати значення:

< 0, якщо *elem1 < *elem2;

= 0, якщо *elem1 = *elem2;

> 0, якщо *elem1 > *elem2;

Якщо *elem1 > *elem2 , то елемент, на який указує elem1 розташовується в масиві раніш; "колишній" елемент розташовується в упорядкованому масиві пізніше.

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

У бібліотеці <stdlib.h> існує також функція пошуку змінних структурного типу в масиві цих змінних.

4.3 Контрольні питання

1. Що таке дані типу структура і які типи даних вони містять?

2. Як описуються дані типу структура?

3. Які існують засоби ініціалізації полів структури?

4. Що таке “вкладеність“ структур?

4.4. Індивідуальні завдання

1. З відомості працівників цеху визначити, скільки в цеху чоловіків-токарів?

2. Скільки в групі студентів-відмінників (всі оцінки 5) і студентів невстигаючих?

3. Є чи в групі студенти, що грають у волейбол , зріст яких більше 180 см?

4. Список студентів відсортувати за зменщенням середнього бала.

5. Ввести в довільному порядку відомості про студентів групи. Вивести прізвища студентів по групах: встигають ”добре”,” задовільно”,” незадовільно”.

6. Віддрукувати список робітників-жінок ціху пенсійного віку.

7. Ввести в пам'ять розклад електропоїздів прямуючих з Харкова через Мерефу. Які з потягів прямують тільки до Мерефи?

8. Хто зі студентів групи має самий великий зріст і вагу ?

9. Ввести відомості про дату народження студентів групи, вивести дані в такому порядку: спочатку - про народжених в 1-ої декаді, потім у 2-ий і 3-їй декадах.

10. Зі списку студентів групи вивести на екран два списки: перший містить прізвища дівчин, другий — прізвища юнаків.

11. Список студентів групи ввести в довільному порядку, а вивести на екран по групах, кожна група належить до якого-небудь знака зодіаку.

12. За яким предметом в студента з заданим номером по журналу краща оцінка за підсумками сесії?

13. Ввести в пам'ять результати змагань по лижних гонках. Показати п'ять кращих результатів окремо для юнаків і дівчат.

14. За результатами лижних змагань у трьох групах сформувати збірну команду з 7 чоловік.

15. Ввести списки двох студентських груп, упорядкованих за зменшенням середнього бала. Виконати злиття списків в один список, упорядкований за тою же відзнакою.

16. В одному списку інформація про студентів, що приймали участь в олімпіаді по математиці, в іншому — по інформатиці. Сформувати третій список з учнями, що брали участь в обох олімпіадах.

17. З якого предмета в заданого студента краща оцінка за підсумками навчального року ?

18. Хто зі студентів-спортсменів здав усі випускні іспити на "добре" і "відмінно" ?

19. Хто краще учиться в групі - дівчата або юнаки?

20. Є чи в групі студенти, що мають оцінку 4 або 5 по інформатиці і грають в шахи ?

21. Знаючи прізвища улюблених письменників ваших друзів, надрукувати прізвища п'яти найбільш популярних письменників.

22. Обчислити середній бал групи і роздрукувати список студентів, що мають середній бал вище за середнє бала групи.

23. Роздрукувати список студентів, прізвища яких починаються з букви "А", і їхньої оцінки за час навчання.

24. За підсумками останньої сесії роздрукувати список відмінників і тих, що вчаться добре упорядкований за алфавітом.

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

5 ВИКОРИСТАННЯ ФУНКЦІЙ ПРИ РОЗРОБЦІ ПРОГРАМ

5.1 Ціль роботи

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

5.2 Методичні вказівки з організації самостійної роботи

студентів

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

Функція ¾ це логічно завершена сукупність описів і операторів, призначених для виконання визначеної задачі.

У мові С++немає розподілу на основну програму і підпрограми, на процедури і функції і т.д. Однак серед функцій повинна бути одна з ім'ям main, що може знаходитися в будь-якому місці програми. Ця функція виконується завжди першою і закінчується останньою. Будь-яка функція має однакову структуру, що має вигляд :

[тип результату ] ім'я функції ([список формальних аргументів])

{

// тіло функції

Опис даних ;

Оператори ;

[return] [вираз];

}

тут квадратні дужки [ ],як звичайно вказують, що розташованана в них конструкція може бути відсутньою ;

тип результату¾ будь-який базовий або раніше описаний тип значення, яке повертається функцією (необов'язковий параметр), якщо він відсутній, тоді тип результату буде цілий (int); цей параметр може бути описаний ключовим словом (void), у цьому випадку функція не повертає ніякого значення (результату). Якщо параметр заданий із зірочкою (*) ¾ функція повертає покажчик на об'єкт, або на одержання адреси об'єкта (& ) (в операторі return);

ім'я функції¾ будь-яке ім'я, що складається з літер, цифр і знака "_"(підкреслення), що починається літерою або знаком "_", або ім'я main,за ім'ям функції завжди повинна стояти пара круглих дужок ( ), у яких записуються формальні параметри, а якщо їх немає, тоді ¾ порожні дужки. Варто мати на увазі, що фактично ім'я функції ¾ це особливий вигляд покажчика на функцію, його значенням є адреса початку входу у функцію;

список формальних аргументів¾ визначає кількість, тип і порядок проходження переданих у функцію вхідних аргументів, що друг від друга розділяються комою. У випадку, коли список відсутній, це поле буде порожнім ( ), або містити ключове слово ( void) . Формальні параметри функції цілком локалізовані в ній і недоступні для будь-яких інших функцій.

Список формальних аргументів повинний мати наступний вигляд:

( [const] тип 1 [параметр 1] , [const] тип 2 [параметр 2],. . . )

У цьому списку не можна групувати параметри одного типу, указавши їх тип один раз, для кожного параметра треба вказувати його тип. Слово const повідомляє компілятору, що значення параметра не повинне змінюватися функцією ( це необов'язковий атрибут). За замовчуванням усі формальні параметри передаються за значенням, тобто якщо вони змінюються в тілі функції, то за її межами залишаються без зміни, оскільки передаються не самі значення, а їхні копії. Ці копії створюються усередині функції, це ілюструє, наприклад, такий фрагмент програми:

Void fun ( int p)

{

++ p;

cout << " p=" << p << endl;

}

Void main ( )

{

int x = 10;

fun (x);// викликфункції

cout << "x=" << x << endl;

}

У результаті роботи цього фрагмента програми буде виведено: р=11, х = 10, оскільки для виклику функції fun(x) до неї передається копія значення рівного 10, під час виконання цієї функції значення p збільшується на 1, тобто (++р) і, тому виводиться р = 11, але за межами функції зазначене значення не змінюється. Якщо треба змінити змінну оригінал, тобто передати зміну параметра за межами тіла функції, то можна передати значення параметра за посиланням або використовувати параметр-покажчик. Тоді, використовуючи параметр- посилання, одержимо :

// Використання параметра - посилання

void fun (int &р)

{ ++p;

cout << "p = " << р << endl;

}

Void main ( )

{

int x = 10;

Fun( x );

cout << "x=" << x << endl;

}

У результаті буде виведена інформація: р=11і х=11.

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

// Використання параметра - покажчика

void fun2 (int *p)

{

++*р;

cout << "*p = " << *p << endl;

}

Void main ( )

{

int x = 10;

fun2 ( &x );

cout << "x = " << x << endl;

}

У цьому випадку одержуємо той же результат, тобто р = 11іх = 11.

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

Тіло функціїможе складатися з описів змінних і операторів. Змінні, котрі використовуються при виконанні функції, можуть бути глобальні і локальні. Якщо змінні описані (визначені) за межами функції, вони будуть глобальними. З їхньою допомогою можна передавати дані у функцію, не включаючи до складу формальних аргументів. У тілі функції їх можна змінювати і потім отримані значення передавати в інші функції.

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

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

static int x, y; або static float p = 3.25;

Статична змінна схожа на глобальну, але доступна тільки в тій функції, у якій вона оголошена.

Таким чином, можна зробити висновок:

¾параметри функції передаються в неї за значенням, тому за межами функції вони не змінюються, тобто їх не можна використовувати для передачі результату роботи функції;

¾ при передачі результату функції за її межі використовуються: або передача параметрів за посиланням (&р); або передача за покажчиком (*р), у цьому випадку під час звертання до функції застосовується символ адреси &, тобто (&р); або як параметр функції варто використовувати глобальні змінні;

¾ локальні (звичайні) змінні використовуються в тілі функції, існують тільки під час роботи функції, а при виході з неї знищуються, тому такі змінні називаються автоматичними і їх можна використовувати тільки для перетворень усередині функції;

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

static char st[ ]= "Тесленко А.М.";

¾ у якості вхідних (і вихідних) формальних аргументів функцій можуть використовуватися масиви як фіксованої довжини, так і змінної; якщо використовується в якості формальний масив змінної довжини, то обов'язково серед аргументів функції повинна бути змінна, що вказує длину масиву, наприклад:

int minmas (int mas [ 50]); // Масив фіксованої довжини

int minmas (int mas [ ], int n); //Масив змінної довжини

int minmas (int *mas, int n); //Масив змінної довжини

¾ усі масиви ¾ формальні аргументи передаються за адресою, тобто як покажчики;

¾ на початку програми записується заголовок використовуваної функції, який називається прототипом , наприклад:

double sgr (double);// Прототип функції sqr

. . . . . . . . .

Int main ( )

{

cout << "5**2 = " << sgr (5) << endl; // Виклик функції

}

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

¾ в останніх версіях мови С++ з'явилася можливість передавати дані за замовчуванням. У цьому випадку при написанні функції аргументам присвоюються початкові значення, що можуть мати всі аргументи або частину з них. У результаті задовольняються наступні вимоги: якщо якому-небудь аргументу надане значення за замовчуванням, то всі аргументи, що стоять за цим параметром (тобто записаним праворуч), повинні мати значення за замовчуванням. Таким чином, список параметрів поділяється на дві частини: параметри, що не мають значення за замовчуванням, і параметри, що мають такі значення.

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

void funct1 ( float x, int y, int z =80 )

{

cout << "x = " << x << " y= " << y << "z=" << z << endl;

}

void funct2 ( float x, int y = 25 , int z = 100 )

{

cout << "x=" << x << "y=" << y << "z=" << z << endl;

}

void funct3 ( float x=3.5 , int y= 40, int z =200 )

{

cout << "x = " << x << "y = " << y << "z = " << z << endl;

}

Main ( )

{

funct1 ( 5.1 , 10 );// за замовчуванням один аргумент ¾ z

funct2 ( 10.2 );// за замовчуванням два аргументи ¾ y ,z

funct3 ( );// за замовчуванням всі аргументи

}

На екрані буде виведено: x =5.1 y = 10 z = 80

x =10.2 y = 25 z = 100

x =3.5 y = 40 z = 200

З цих ілюстраційних програм видно, що аргумент за замовчуванням ¾ це той, значення якого задане при описі заголовка функції, а при її виклику цей аргумент можна не вказувати. Якщо замість параметра, заданого за замовчуванням при звертанні до функції, записується інше значення фактичного параметра, то значення за замовчуванням заміюються заданим фактичним значенням. Так, наприклад, в останньому програмному фрагменті при виклику функції funct (13.5, 75);на екрані буде виведено :

x = 13.5 y =75 z = 80, тобто z- прийнято за замовчуванням.

5.2.1 Використання покажчиків на функцію

Синтаксис мови С++ дозволяє використовувати покажчик на функцію. Ім'я будь-якої константи ¾ це покажчик – константа, дорівнює адресі початку входу у функцію, тобто адресі її першої машинної команди. Крім констант можна також описувати покажчики - змінні на функцію у вигляді:

type (*name) (список аргументів); ,

де type ¾ тип значення, що повертається функцією, ;

name ¾ ім'я змінної - покажчика на функцію.

Покажчики на функцію використовуються в наступних основних випадках :

¾ при використанні їх як формальні аргументи в інших функціях;

¾ для непрямого виклику інших (резидентних) функцій (програм), початок входу в який записується у відоме місце ОП.

Приклад 5.1Обчислення суми і різниці двох чисел програмно реалізувати з використанням покажчика на функцію для доступу до інших функцій

//P5_1.CPP –використання покажчика на функцію для доступу

// до інших функцій¾difference( )іsum( ).

#include < iostream >

Using namespace std;

int difference ( int, int ); //Прототип функції

Int sum ( int, int );

Void main ( )

{

int (*fun) (int, int );

int x = 20, y = 5, z ;

fun = difference ; //Присвоювання адреси одного покажчика - іншому

z = fun (x, y);

cout << "z = " << z << еndl;

fun = sum; //Присвоювання нової адреси покажчика

z = fun (x , y );

cout << "z = " << z << endl;

}

int difference (int a , int b) //Опис функції

{ return (a - b);

}

Int sum ( int a, int b )

{ return (a + b);}

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

int god ( const void*, const void * ) ;

int chena ( const void*, const void *) ;

int nazv ( const void*, const void * ) ;

int avtor ( const void*, const void * ) ; ,

то можна описати функцію

int (*fcmp[4]) () {god, chena, nazv, avtor} ; .

У результаті вийшов масив функцій, доступ до елементів цього масиву звичайний, наприклад:

int i =0;

fcmp [i] ( pt1,pt2 ); //це виклик функціїgod ( pt1, pt2);

Варто звернути увагу, що замінивши індекс, можна викликати іншу функцію і т.д.

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

Операція разіменування "*"означає, що функція повертає адресу на об'єкт. Функції в такому випадку з'являються як покажчики на функцію, тобто в наступному вигляді:

type * fname(список формальних аргументів) .

Описані в такий спосіб функції повинні повертати покажчик на тип (адреса), наприклад:

сhar* dayweek (int data)

{

static char *weekday[ ] = {"Sunday", "Monday", "Tuesday",

"Weduesday", "Thursday", "Friday", "Saturday"}

return weekday [data % 7];

}

Тут функція dayweek одержує значення data,тобто число днів, що пройм

ли з якоїсь визначеної дати, і повертає день тижня у вигляді покажчика на char*оскільки weekday ¾ це масив покажчиків на char, що належить типу char*.

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

type *funame (список формальних аргументів)

{

Static type x;

//далі виникаєтіло функції

return &x;

}

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

type& funame (список формальних аргументів) .

5.2.2 Використання масивів - параметрів функцій

Як аргументи (параметрів) функцій можуть бути не тільки змінні, але і масиви. У цьому випадку можна використовувати як масиви фіксованого розміру, так і невизначеного (масиви змінної довжини). При використанні масивів фіксованої довжини в заголовку функції в списку формальних аргументів указується тип масиву і його розмір, наприклад:

vоid sort (int mas [ 30 ]); .

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

void sort ( int mas [ ], int n ) ; .

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

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

//P5_2.CPP –використання масивів – параметрів функцій

#include < string.h >

#include < iostream >

Using namespace std;

void fun1 (char st [15]);

Int main ( )

{

char p[15] ="стіл ";

Fun1 (p);

cout << "p=" << p << endl;// p="стілець "

Return 0;

}

void fun1 ( char st[15] )

{

cout <<"p=" << st << endl; //стіл

strcpy (st, "стілець ");

}

Результати виконання програми :

р=стіл

р=стілець

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

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

void fun1 (int mat [7][10]);// використовується матриця mat(7,10)

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

void fun2 ( int mat [ ] [10], int rows, int cols );

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

// P5_3.CPP –обчислення середнього значення

// кожного стовпця матриці

#include < iostream >

Using namespace std;

const int mincol = 1;

const int maxcol = 20;

const int minrow = 2;

const int maxrow = 30;

//Функція getnum ( )для введення кількості рядків і стовпців

int getnum (const char *elemtype , int low , int high )

{

Int n;

Do

{

cout << " Введіть кількість " << elemtype

<< "Nвід[" << low << "]до[" << high << "] : ";

cin >> n;

}

while (( n<low) || (n>high));

Return n;

}

// Функція inmatr ( ) введення елементів матриці

void inmatr ( float matr [ ] [maxcol], int rows , int cols);

{

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

{

cout << "Введіть"<<i<< "рядок матриці " << endl;

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

cin >> matr [i][j];

}

cout << endl;

}

// Функціяsrcols ( ) одержання середніх значень стовпців

void srcols ( float matr [ ] [maxcol] , int rows , int cols )

{

Float sum , sr;

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

{

sum =0.0;

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

sum += matr [i][j];

sr = sum / rows;

cout << "середнє значення стовпця" << j << " = " << sr << endl;

}

}

// Головна програма

Int main ( )

{

float matr [maxrow] [maxcol];

Int rows, cols;

// Уведення кількості рядків і стовпців

rows = getnum ( "rows", minrow, maxrow );

cols = getnum ( "colnums" , mincol , maxcol);

// Уведення матриці

Наши рекомендации