Device . put (char_var); , 2 страница

 

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

 

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

Підказка: де

 

22. Увести координати п'яти крапок і визначити яка з них потрапить в окружність з радіусом R і координатами центра (а, в).

Підказка: рівняння окружності має вид:

 

23. Увести п'ять шестирозрядних цілих чисел і знайти для яких з них сума «лівих» трьох цифр більше суми «правих» трьох.

 

24. Підрахувати скільки разів функція

приймає негативне значення, якщо .

25. Обчислити функцію у вигляді формули

для кожного значення i.

 


2 РОЗВ’ЯЗАННЯ ЗАДАЧ C ВИКОРИСТАННЯМ ОДНОВИМІРНИХ І ДВОВИМІРНИХ МАСИВІВ

 

2.1 Ціль роботи

 

Прищепити студентам навички розв’язання задач з використанням одновимірних і двовимірних масивів, складних циклів і використання покажчиків.

 

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

 

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

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

 

Приклад 2.1Обчислити функціюy = axi2 – sin xi, де x1=-1, x2=-0,93, x3=-0,49, x4=0, x5=1,13, x6=0,96, x7=1,75.

 

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

У схемі алгоритму розв‘язання задачі спочатку передбачається введення значень всіх елементів оброблюваного масиву x[n] (n =7 ).Число в дужках визначає кількість елементів масиву. Нумерація елементів масиву починається з 0ізакінчується n –1 .Далі введені елементи використовуються при обчисленні функції, шляхом вказівки індексу відповідного елемента.

Схема алгоритму розв’язання цієї задачі і програма виглядають наступним чином:

//P2_1.CPP -обчислення значень функції

// використання одновимірного масиву

#include <iostream>

 
 


 

a=10.5

 

i=0

 

y=axi*xi-sin(xi)

i=i+1

так

немає

#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], значення якого треба ввести.

Особливість виконання оператора введення 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), і програма, що реалізує таку задачу, виглядає в такий спосіб :

 

// Р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;) .

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

 

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

Індекси таких масивів записуються в квадратних дужках. Наприклад, запис М[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;

//Виведення матриці в природному вигляді

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 ; //два покажчики на дійсні значення;

Покажчики не прив'язують дані до якого-небудь визначеного імені змінної і можуть містити адреси будь-якого неіменованого значення. Існує адресна константа 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; // описані два покажчики на довільний тип даних

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

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

 

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— це ім'я масиву, що

//розглядаєтьсяяк спеціальний покажчик – константа.

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

// 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); .

 

Для змінних – покажчиківдозволені операції:

— присвоювання;

— інкремент і декремент;

— додавання і віднімання;

— порівняння покажчиків однакового типу.

Наприклад, демонстраційна програма з використанням змінних-покажчиків може мати вигляд:

 

//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].

Для доступу до елементів масиву існує два способи:

— використання індексу елемента масиву, наприклад, 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},

{10, 11, 13, 14, 25} };

int mas [ ][5] ={ 1, 2, 3, 4, 5,

10, 11, 13, 14, 25 }; .

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

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

Оскільки для масивів завжди в пам'яті приділяється суцільний блок комірок пам'яті, у яких розташовуються елементи, то адресу наступного елемента mas[1] можна вказати шляхом збільшення покажчика на 1, тобто якщо p = &mas[0] , тоді p=p + 1 або( p += 1)адля i елемента масиву адреса може бути визначена як p + i; . При цьому автоматично виконується операція збільшення адреси з урахуванням типу масиву і кількості, що відводиться, байт для кожного його елемента, отже :

адреса х[і] = адреса x[0] + і*sizeof ( тип ); .

Якщо два покажчики р1ір2указують на елементи одного масиву, то до них застосовні операції відносини: == , != , < , <= , > , >= .

Наприклад, відношення вигляду р1 < р2 істинно, якщо р1указує на більш ранній елемент, ніж р2 . Всякий покажчик можна порівняти з нулем.

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