Информатика.ЛБ
.pdf
Ввод xi
(i=0..6)
a=10.5
i=0
y=axi*xi-sin(xi)
Печать xi,y
i=i+1
так
i<7
немає
конец
#include <math.h>
using namespace std;
void main( )
{
const int n =7;
float x[n];
int i;
float a, y;
// Введення масиву
cout<< "Введіть значення масиву:" <<endl;
for ( i=0; i < n; i++)
{
cout << "x [" << i << "] = ";
cin >> x [ i ] ;
cout << x [ i ] << endl;
}
a = 10.5;
// Обчислення функції
for ( i = 0; i < n; i++)
{
y = a*x [ i ] * x [ i ] – sin ( x [ i ] ) ; cout << "При значенні=" << x[i]
<< "y = " << y << endl;
}
}
При запису цього алгоритму у вигляді програми спочатку треба описати масив за допомогою оператора float x [n], ввести його значення в пам'ять
комп'ютера, а потім  | 
	робити  | 
	необхідні  | 
	обчислення.  | 
	
  | 
|
У програмі, що реалізує даний алгоритм, для введення  | 
	елементів масиву  | 
||||
використовується  | 
	оператор  | 
	cin >>  | 
	x [i] ;,  | 
	перед  | 
	цим оператором  | 
знаходиться підказка cout << "x [" << i << "] = "; і зазначен номер елемента x[i], значення якого треба ввести.
21
Особливість виконання оператора введення cin >> x[i] ;  | 
	полягає в  | 
тому, що, зустрівши його в програмі, комп'ютер призупинить її  | 
	виконання  | 
поки не буде введене значення елемента x[i] і натиснута клавіша Enter, після чого обробка програми буде продовжена. Зазначений оператор включений у
цикл, реалізований за допомогою оператора  | 
	for, і повторюваний n разів,  | 
|
для забезпечення введення всіх елементів  | 
	масиву.  | 
|
Оскільки в  | 
	мові С++ індексація елементів масиву починається з нуля, то  | 
|
масив float x[7]  | 
	(n =7 ) із семи елементів включає індексовані елементи x[0],  | 
|
x[1], x[2] … x[6] і при цьому x[0] — звертання до першого елемента, x[1] — звернення до другого елемента масиву і т.д. Пропонована програма використовує два цикли: один — для введення елементів масиву, інший — для обчислення функції. Ці операції можна виконати й в одному циклі, тоді програма буде мати вигляд:
//Р2_2.CPP — введення елементів одновимірного масиву
//і обчислення функції здійснюється в одному циклі
#include < math.h> #include < iostream> using namespace std; float a, y ;
void main ( )
{
const int n =7; float x [ n ]; int i;
float a, y ;
a = 10.5;
for ( i = 0; i < n ; i++)
{
cout << "x [ " << i << "] = "; cin >> x [ i ] ;
y = a * x[ i ]*x[ i ] - sin( x[ i ] );
cout << "При значенні =" << x[і] << " y= " << y << endl;
}
}
Приклад 2.2 Обробити відомість успішності групи студентів з 10 чоловік по програмуванню, підрахувавши середній бал групи і кількість відмінників.
Список оцінок представимо масивом mas[i] (i=0..9), і програма, що реалізує таку задачу, виглядає в такий спосіб :
22
//Р2_3.CPP — використання одновимірних масивів
//Визначення середнього бала групи і кількості відмінників
#include < math.h > #include < iostream> using namespace std;
void main ( )  | 
	
  | 
	
  | 
	
  | 
|
{  | 
	
  | 
	
  | 
	
  | 
	
  | 
const int n = 10;  | 
	// розмірність масиву  | 
|||
float mas[n];  | 
	//  | 
	опис одновимірного масиву  | 
||
int i, k;  | 
	
  | 
	
  | 
	
  | 
|
float s;  | 
	
  | 
	
  | 
	
  | 
|
s = 0 ;  | 
	//  | 
	s - змінна для підсумовування оцінок групи  | 
||
k = 0 ;  | 
	//  | 
	k - змінна для підрахунку кількості відмінників  | 
||
for ( i=0;  | 
	i < n;  | 
	i++ )  | 
||
  | 
	{  | 
	
  | 
	
  | 
	
  | 
cout << " mas [ " << i << "] = ";  | 
||||
cin >> mas [ i ] ;  | 
	
  | 
|||
cout << mas [ i ]  | 
	<< endl;  | 
|||
s  | 
	= s +  | 
	mas [ i ];  | 
||
if  | 
	( mas[ i ] = = 5)  | 
|||
k=k+1;
}
cout << "Середній бал = " << s / float(n ) << endl; cout << "Кількість відмінників =" << k<< endl;
}
У цій програмі змінна s служить для обчислення суми оцінок групи, а змінна k — для підрахунку кількості відмінників. Перед обчисленням треба задати цим змінним початкового нульового значення. Оператор
cout << " mas [ " << i << "] = ";
усередині циклу виконує роль підказки про необхідність введення чергової оцінки, а наприкінці використовується для виведення результатів обчислення ( cout << "Середній бал"<< s / float (n) << endl; cout << "Кількість відмінників =" <<k<< endl;) .
Крім одновимірних масивів, тобто таких, де положення елемента визначається за допомогою одного індексу, у практиці розв‘язання задач часто застосовуються багатовимірні масиви. У них положення елемента визначається шляхом запису декількох індексів. Найбільш широке поширення одержали двовимірні масиви, які називаються матрицями. Матриці являють собою порядковий запис декількох одновимірних масивів, наприклад:
23
  | 
	1,2  | 
	3,4  | 
	5,6  | 
	7,7  | 
	13  | 
|
  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
M  | 
	0,2  | 
	4,6  | 
	20,5  | 
	0  | 
	4,8  | 
	
  | 
  | 
	25  | 
	4,8  | 
	4,9  | 
	9,5  | 
	0  | 
	
  | 
  | 
	
  | 
|||||
Місце розташування кожного елемента визначається за допомогою двох індексів — номера рядка і номери стовпця, тобто порядкового номера в рядку.
Індекси таких масивів записуються в квадратних дужках. Наприклад, запис М[1] [2] вказує на елемент, що знаходиться в другому рядку і третьому стовпці, тобто маючий значення -20.5 (рахунок індексів починається з 0). Для перебору всіх елементів матриці при їхньому введенні-виведенні, а також при обробці в програмі варто передбачати організацію двох циклів: один — для завдання значень індексу рядків, інший -індексу стовпців.
Приклад 2.3 До кожного елемента вищенаведеної матриці M додати число 10.
//Р2_4.CPP — використання двовимірних масивів
//До кожного елемента матриці додати число 10.
#include < iostream> using namespace std; void main ( )
{
const int n = 3; // кількість рядків матриці const int m = 5; // кількість стовпців матриці float M [ n] [m];
int i, k; float s; s = 10 ;
cout << " Введіть значення масиву:" << endl; // Введення значень двовимірного масиву
for ( i = 0; i < n; i++)
for ( k = 0; k < m; k ++)
{
cout << " M [ " << i << "] = " << "[ " << k << ]" ;
cin >> M [ i ] [ k ];  | 
	
  | 
cout << M [ i ] [ k ] <<  | 
	endl;  | 
M [ i ] [ k ] = M [ i ] [ k ]  | 
	+ s ; // Можна M [ i ] [ k ] + = s ;  | 
}  | 
	
  | 
cout << "Нове значення матриці :" << endl;
24
// Виведення матриці в природному вигляді for ( i = 0; i < n; i++)
{
cout << endl;
for ( k = 0; k < m; k++)
cout << M [ i ] [ k ] << " ";
}
}
У програмі при описі матриці в операторі float M[n][m];
вказується діапазон зміни двох індексів, перший з яких призначений для індексування рядків, другий — стовпців.
При введенні, обробці і виведенні матриці для перебору всіх її елементів використовується два цикли, один із яких є вкладеним в іншій. Це дозволяє при кожнім значенні змінної i перебирати всі значення k.
Розглянута програма може бути скорочена шляхом об'єднання всіх трьох блоків циклу в один, але в такому випадку вона буде менш наочною.
2.3 Використання покажчиків
У мові С++ широко використовуються дані, що називаються покажчиками.
Покажчики — це змінні, котрі містять адресу пам'яті, розподіленої для іншої змінної. Усі змінні, розглянуті до цього, зберігали якісь значення (дані). Ці дані могли бути різних типів: символьного, цілого, дійсного і т.д. При оголошенні змінної - покажчика необхідно вказати тип даних, адресу яких буде містити змінна, і ім'я покажчика з попередньою зірочкою.
Загальний формат опису покажчика наступний:
тип * ім'я;
де тип — тип значень, на который буде вказувати покажчик; ім'я — ім'я змінної-покажчика;
* — означає операцію над типом, що читається "покажчик" на тип. Наведемо приклади визначень покажчиків:
int *pn;  | 
	// покажчик на ціле значення;  | 
float *pf1, *pf2 ; // два покажчики на дійсні значення;
25
Покажчики не прив'язують дані до якого-небудь визначеного імені змінної і можуть містити адреси будь-якого неіменованого значення. Існує адресна константа NULL , що означає "порожню" адресу.
У мові С++ знаходиться усього два оператори, що відносяться до покажчиків:
―&‖ — оператор " адреса значення "; ―* ― — оператор "значення за адресою".
Оператор "*" , використовуваний разом з покажчиками, витягає значення, на яке вказує змінна, розташована безпосередньо після нього.
Оператор "&" , використовуваний разом з покажчиками, повертає адресу змінної, розташованої безпосередньо після нього.
Покажчики можна оголосити одним з наступних способів:
<тип> *ptr;
<тип> *ptr = <перемінна - покажчик>;
<тип> *ptr =&<ім'я змінної>; // адреса змінної
У програмі це може виглядати в такий спосіб:
int *ptx ,b ; float y; // оголошені перемінна - покажчик ptx і звичайні змінні b і
y;  | 
	
  | 
float *sp = &y;  | 
	// покажчику sp привласнюється адреса змінної y  | 
float *p = sp;  | 
	// покажчику p привласнюється значення (адреса значення),  | 
// яке міститься в змінній sp, тобто адреса змінної y.
При оголошенні покажчиків символ "*" може розташовуватися або перед ім'ям покажчика або записуватися відразу після оголошення типу покажчика і поширює свою дію тільки на одну змінну - покажчик, перед якою він знаходиться, наприклад:
long *pt; long* Uk; int * ki, x, h ; // оголошення описів
У разі потреби опису покажчика на комірку довільного типу, замість ідентифікатора типу записується слово void, наприклад:
void *p, *pt; // описані два покажчики на довільний тип даних
Перш ніж використовувати покажчик у програмі, йому обов'язково треба присвоїти адресу якого - небудь даного, тобто проініціалізувати, інакше можуть бути непередбачені результати.
Для доступу до значення змінної, адреса якої зберігається в покажчику, досить у відповідному операторі програми записати ім'я покажчика із символом "*" , наприклад:
26
int *p, *p1;  | 
	// Оголошені два покажчики на комірку пам'яті  | 
int;  | 
	
  | 
int x =12, y=5, m [7 ];  | 
	// Оголошені змінні x,y і масив m,  | 
  | 
	// змінні x,y ініціалізовані  | 
p = &y;  | 
	// Покажчику p привласнена адреса змінної y.  | 
Тепер, якщо написати оператор виведення на екран у вигляді :
cout << "Адреса р " << p << "Значення по цій адресі= " <<*p;  | 
	,  | 
||||||
тоді виведеться адреса комірки пам'яті, де записана змінна y  | 
	і значення цієї  | 
||||||
змінної (тобто 5).  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
|
Використовуючи запис  | 
	x = *p; ,  | 
	одержуємо x=5,  | 
	тому що *p = y  | 
||||
= 5; .  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
Змінити значення  | 
	y можна таким чином:  | 
	
  | 
	
  | 
	
  | 
|||
  | 
	y = 10;  | 
	//  | 
	чи *p = 10;  | 
	
  | 
	
  | 
	
  | 
	
  | 
і виконавши операцію  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
|
  | 
	*p= *p+5;  | 
	// це рівнозначно операції y = y + 5; тобто y = 15.  | 
|||||
При  | 
	оголошенні  | 
	покажчиків, їм  | 
	потрібно  | 
	привласнювати  | 
	початкові  | 
||
значення (  | 
	ініціалізувати ), при цьому можна або  | 
	привласнювати  | 
	адресу  | 
||||
об'єкта (змінної), або адресу конкретного місця пам'яті (масиву), або число 0 (нуль), наприклад:
int  | 
	*pt = (char *) 0x00147;  | 
	// Привласнюється адреса комірки  | 
int  | 
	*arrpt = new int [10];  | 
	// Визначається початкова адреса розміщення  | 
  | 
	
  | 
	// динамічного масиву  | 
сhar *p = 0;  | 
	// Ініціалізація нулем  | 
|
Оскільки покажчики — це спеціальні змінні, то в операціях з іншим покажчиками вони можуть використовуватися без символу "*", тобто без розкриття посилання, наприклад:
float *pt1, *pt2 , x=15, m[5];
pt1=&x;
pt2=pt1;
pt1 = m;  | 
	// або pt1 = &m[0];  | 
	m — це ім'я масиву, що  | 
27
// розглядається як спеціальний покажчик – константа.
Наиведемо програму з використанням покажчиків:
// P2_5.CPP — застосування покажчиків
#include < iostream> using namespace std;
int main ( )
{
int x = 10;
int *px = &x;
cout << " x =" << x << endl; cout << "*px =" << *px << endl; x* = 2; // або x = x*2;
cout << " Нове значення* px =" << *px << endl;
*px += 2; // або *px =*px + 2;
cout << " Нове значення* px=, тобто х=" << x << endl; return 0;
}
Результат виконання програми:
x = 10 *px = 10
Нове значення *px = 20
Нове значення*px, тобто x = 22
Сам покажчик-змінна має свою адресу, тому буде справедливим наступний запис:
int *pt1, *pt2;  | 
	
  | 
	
  | 
	
  | 
pt1 = (int*) &pt2; //  | 
	тут покажчику pt1 привласнюється адреса пам'яті,  | 
||
//  | 
	де  | 
	розташована  | 
	змінна pt2  | 
Це має сенс у ситуації,  | 
	коли :  | 
	
  | 
|
int y,*pt1, *pt2 =&y;  | 
	
  | 
||
pt1 = (int*) & pt2;  | 
	.  | 
||
Існують наступні обмеження на використання операції взяття адреси "&":
—не можна визначати адресу константи ( оскільки їй не приділяється комірка пам'яті), тобто неприпустимий запис : vp = &345;
—не можна визначати адресу результату арифметичного виразу, тому
наступний запис невірний : vp = & (x + y); .
28
Для змінних – покажчиків дозволені операції:
—присвоювання;
—інкремент і декремент;
—додавання і віднімання;
—порівняння покажчиків однакового типу.
Наприклад, демонстраційна програма з використанням зміннихпокажчиків може мати вигляд:
//P2_6.CPP — використання зміннихпокажчиків
#include < iostream> using namespace std; void main ( void )
{
int *ptr1 = (int*)100 ; int *ptr2 = (int*) 200; ptr1++;
ptr2 -= 10;
cout << "ptr1=" << ptr1 << endl; cout << "ptr2=" << ptr2 << endl;
cout << "ptr2 - ptr1=" << ptr2 - ptr1 << endl;
}
Результат виконання програми : ptr1 = 00000068
ptr2 = 000000A0 ptr2 - ptr1 = 14
У програмі операція ptr1++ збільшить адресу на 4 байта , оскільки дані типу int займають 4 байти , операція ptr2-=10 зменьшує адресу на 40 байтів. Адреси виводяться на екран в шістнадцятковому вигляді.
2.4 Використання масивів і покажчиків
У мові С++ масиви і покажчики зв'язані між собою. При оголошенні масиву у вигляді : int mas [20]; ім'я масиву mas визначається як покажчикконстанта на перший (нульовий) елемент масиву, тобто на адресу першого елемента масиву &mas[0].
Для доступу до елементів масиву існує два способи:
29
— використання індексу елемента масиву, наприклад, mas[2] або
mas[i];
— використання адресного виразу тобто виразу з покажчиком на масив, наприклад, *( mas +2 ) чи *( mas+i ).
Ім'я масив-покажчик, можна записати в наступному вигляді:
int mas [20]; int *ptr1;
ptr1 = mas; // чи ptr1 = &mas[0];
Після оголошення масиву int mas [20]; вираз &mas[0] і mas є еквівалентними.
Для обнуління елементів оголошеного масиву досить ініціалізувати його перший елемент: int mas[10] = {0} ; При цьому першому елементу не обов'язково привласнювати значення 0. Якщо в оголошеному масиві ініціалізується трохи перших елементів, то інші ініціалізуються нулями.
Наприклад, у випадку коли float mas [10] ={ 12.2, 34.56 }; , останні вісім елементів одержать значення 0.
Глобальні масиви автоматично ініціалізуються двійковими нулями, у тому числі і символьні.
При оголошенні масивів можна використовувати одну з форм запису :
< тип > < ім'я > [n]  | 
	//  | 
	Оголошення одновимірного  | 
|||
  | 
	
  | 
	//  | 
	масиву з n елементів  | 
||
< тип > < ім'я > [n]  | 
	= { значення }  | 
	//  | 
	Значення елементів масиву  | 
||
< тип > < ім'я > [ ]  | 
	
  | 
	= { значення }  | 
	//  | 
	розділені комою  | 
|
Наприклад:  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
float m[6];  | 
	
  | 
	
  | 
	
  | 
	
  | 
	
  | 
float m[6]  | 
	= { 3.4,  | 
	4.5, 5.6,  | 
	6.7, 8.9, 10.3 };  | 
||
float m[ ]  | 
	= { 3.45,  | 
	4.56, 5.67,  | 
	6.78 };  | 
||
Двовимірні і багатовимірні масиви описуються аналогічним образом, тобто правомірний запис :
int mas [2][5] ={ 1, 2, 3, 4, 5,
10, 11, 13, 14, 25 };
int mas [2][5] ={ {1, 2, 3, 4, 5},
30
