Professional Documents
Culture Documents
ЗО 14 1 Основи алгоритмізації та програмування Частина 1 Курс лекцій
ЗО 14 1 Основи алгоритмізації та програмування Частина 1 Курс лекцій
Курс лекцiй
Навчальний посiбник
Укладач М.М.Чепiлко
Київ
КПI iм. Iгоря Сiкорського
2022
Рецензент: Смiрнов С.А., канд.фiз.-мат.наук, доцент, навчально - науковий фiзико - те-
хнiчний iнститут
Змiст
Вступ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1 Алгоритми та їх властивостi . . . . . . . . . . . . . . . . . . . . 8
1.1 Алгоритми та правила їх графiчного запису . . . . . . . 8
1.2 Програмне забезпечення для реалiзацiї алгоритмiв . . . . 15
1.3 Питання та завдання для самоконтролю знань . . . . . . 17
2 Основи мови програмування С/С++ . . . . . . . . . . . . . . . . 18
2.1 Алгоритмiзацiя структури для програми у мовi С/С++ . 18
2.2 Введення i виведення у консолi . . . . . . . . . . . . . . . 20
2.3 Змiннi у мовi програмування C++ . . . . . . . . . . . . . 23
2.4 Формалiзм функцiй у мовi програмування С/С++ . . . . 26
2.5 Питання та завдання для самоконтролю знань . . . . . . 27
3 Типи данних та арифметичнi операцiї у мовi програмування
С/С++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.1 Основнi типи данных у мовi програмування С/С++ та
їх призначення . . . . . . . . . . . . . . . . . . . . . . . . 27
3.2 Статична типiзацiя i перетворення типiв . . . . . . . . . 32
3.3 Константи . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
3.4 Арифметичнi операцiї та привласнення . . . . . . . . . . 36
3.5 Посилання . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.6 Простори iмен i using . . . . . . . . . . . . . . . . . . . . 42
3.7 Питання та завдання для самоконтролю знань . . . . . . 43
4 Оператори управлiння у мовi програмування С/С++ . . . . . . 44
4.1 Умовнi вирази та операцiї вiдношення . . . . . . . . . . . 44
4.2 Логiчнi операцiї . . . . . . . . . . . . . . . . . . . . . . . . 45
4.3 Побiтовi операцiї . . . . . . . . . . . . . . . . . . . . . . . 46
4.4 Порозряднi операцiї . . . . . . . . . . . . . . . . . . . . . 47
4
Вступ
1. Алгоритми та їх властивостi
• вербальний (словесний);
• алгебраїчний (за допомогою лiтерно-цифрових позначень виконуваних
дiй);
• графiчний;
• з допомогою алгоритмiчних мов програмування.
• Менший геометричний розмiр символу слiд обирати з ряду 10, 15, 20, . . .
мм (тобто a = 10, 15, 20, . . . мм;
• Спiввiдношення бiльшого та меншого розмiрiв має становити 1.5 (тобто
b = 1.5 a).
• Початок i кiнець алгоритму зображуються за допомогою овалiв (див.
рис. 1.1). Усерединi овалу записується ”початок” або ”кiнець”.
• Уведення початкових даних i виведення результатiв зображуються пара-
лелограмом (див. рис. 1.2). Усерединi нього пишеться слово ”уведення”
або ”виведення” i перераховуються змiннi, що пiдлягають введенню або
виведенню.
• Виконання операцiй зображується за допомогою прямокутникiв (див.
рис. 1.3) у яких записано вираз/операцiю. Для кожної окремої операцiї
використовується окремий блок.
• Ранiше створенi i окремо описанi функцiї та пiдпрограми зображуються
у виглядi прямокутника з бiчними лiнiями (див. рис. 1.4). Усерединi та-
кого ”подвiйного” прямокутника указуються iм’я функцiї (пiдпрограми),
параметри, при яких вона повинна бути виконана.
• Блок вибору, що визначає шлях, по якому пiдуть цi дiї (наприклад, об-
числення) далi, залежно вiд результату аналiзу даних, зображується у
виглядi ромбу (див. рис. 1.5). Сама умова записується усерединi ромба.
Якщо умова, що перевiряється, виконується, тобто має значення ”iсти-
на”, то наступним виконується етап по стрiлцi ”так”. Якщо умова не ви-
конується (”хибнiсть”), то здiйснюється перехiд по стрiлцi ”нi”. Стрiлки
повиннi бути пiдписанi.
• Шестикутник (див. рис. 1.6) використовують для змiни параметра змiн-
ної, яка керує виконанням циклiчного алгоритму, також зазначаються
умови завершення циклу.
• Стрiлками зображуються можливi шляхи алгоритму, а малими п’яти-
кутниками (див. рис. 1.7) – розриви цих шляхiв потоку з переходом на
наступну сторiнку.
11
Рис. 1.1 — Блок початок-кiнець. Вхiд Рис. 1.2 — Блок вводу - виводу даних. Вве-
- вихiд з програми, початок - кiнець дення даних з клавiатури або виведення на
функцiї екран результату
Рис. 1.3 — Обчислювальний блок. Об- Рис. 1.4 — Визначений процес. Виконан-
числення та послiдовнiсть обчислень ня пiдпрограми (функцiї)
Iнструкцiї
У цьому блоцi коду двi iнструкцiї, якi виводять на консоль певний рядок.
Функцiя main
}
I пiсля списку параметрiв йде блок коду, який i мiстить у виглядi iнструкцiй
власне тi дiї, виконуванi функцiєю main.
Директиви препроцесора
Коментарi
Виведення на консоль
i n t main ( )
{
i n t age = 3 3 ;
double weight = 8 1 . 2 3 ;
s t d : : cout << "Name : " << "Tom" << "\n " ;
s t d : : cout << "Age : " << age << s t d : : e n d l ;
s t d : : cout << " Weight : " << weight << s t d : : e n d l ;
return 0;
}
Введення з консолi
i n t main ( )
{
i n t age ;
double weight ;
s t d : : cout << " Input age : " ;
s t d : : c i n >> age ;
s t d : : cout << " Input weight : " ;
s t d : : c i n >> weight ;
s t d : : cout << "Your age : " << age <<
"\ t your weight : " << weight << s t d : : e n d l ;
return 0;
}
Тут пiсля запрошень до введення програма чекає введення значень для змiн-
них age i weight.
Приклад роботи програми:
Input age : 32
Input weight : 6 7 . 4 5
Your age : 32 your weight : 6 7 . 4 5
Варто вiдзначити, що так оператор введення у першому випадку додаватиме
данi у цiлочисельну змiнну age, то вiн чекає введення числа. У випадку iз
змiнною weight оператор введення чекає дробове число, причому роздiльни-
ком цiлої i дробової частини повинна бути крапка. Тому ми не можемо ввести
будь-якi значення, наприклад, рядки. У цьому випадку програма може вида-
ти некоректний результат.
Оператор введення » повертає лiвий операнд - об’єкт cin, тому ми можемо по
ланцюжку прочитувати данi у рiзнi змiннi:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
i n t age ;
double weight ;
s t d : : cout << " Input age : " ;
s t d : : c i n >> age >> weight ;
23
Пiсля введення одного iз значень треба буде ввести пропуск i потiм вводити
наступне значення.
Тут визначена змiнна age, яка має тип int. Оскiльки визначення змiнної є
iнструкцiєю, то пiсля нього ставиться крапка з комою.
Також варто враховувати, що C++ - регiстрозалежна мова, а це значить, що
регiстр символiв має велике значення. Тобто у наступному кодi визначатиму-
ться двi рiзнi змiннi:
i n t age ;
i n t Age ;
Iнiцiалiзацiя
return 0;
}
Iнiцiалiзацiя за умовчанням
Змiна значення
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
int x = 6;
x = 8;
x = 10;
s t d : : cout <<"X = " << x ; // X = 10
return 0;
}
}
Типом функцiї, що повертається, є тип int, тому функцiя повинна використо-
вувати оператор return i повертати яке-небудь значення, яке вiдповiдає типу
int. Значення, що повертається, ставиться пiсля оператора return.
Але якщо функцiя має тип void, то їй не треба нiчого повертати.
Кожна змiнна має певний тип. I цей тип визначає, якi значення може мати
змiнна, якi операцiї з нею можна проводити i скiльки байт у пам’ятi вона
займатиме. В мовi C++ визначенi наступнi базовi типи даних:
• bool: логiчний тип. Може приймати одну з двох значень true (iстина) i
false (брехня). Розмiр займаної пам’ятi для цього типу точно не визна-
чений.
• char: представляє один символ в кодуваннi ASCII. Займає в пам’ятi 1
байт (8 бiт). Може берегти будь-яке значення з дiапазону вiд -128 до 127,
або вiд 0 до 255
28
Таким чином, всi типи даних за винятком void можуть бути роздiленi на
три групи: символьнi (char, wchar_t, char16_t, char32_t), цiлочисельнi
(short, int, long, long long) i типи чисел з плаваючою крапкою (float,
double, long double).
Символьнi типи
Цiлочисельнi типи
u n s i g n e d s h o r t b= 1 0 ;
i n t c = −30;
unsigned i n t d = 60;
l o n g e = −170;
unsigned long f = 45;
long long g = 89;
У вище приведеному списку для кожного типу вказаний розмiр, який вiн за-
ймає в пам’ятi. Проте варто вiдзначити, що граничнi розмiри для типiв роз-
робники компiляторiв можуть вибирати самостiйно, виходячи з апаратних
можливостей комп’ютера. Стандарт встановлює лише мiнiмальнi значення,
якi повиннi бути. Наприклад, для типiв int i short мiнiмальне значення -
16 бiт, для типу long - 32 бiти, для типу long double. При цьому розмiр
типу long повинен бути не менше розмiру типу int, а розмiр типу int - не
менше розмiру типу short, а розмiр типу long double повинен бути бiльше
double. Наприклад, компiлятор g++ пiд Windows для long double викори-
стовує 12 байт, а компiлятор, вбудований в Visual Studio i також працюючий
пiд Windows, для long double використовує 8 байт. Тобто навiть в рамках
однiєї платформи рiзнi компiлятори можуть по рiзному пiдходити до розмiрiв
деяких типiв даних. Але в цiлому використовуються тi розмiри, якi вказанi
вище при описi типiв даних.
Проте бувають ситуацiї, коли необхiдно точно знати розмiр певного типу.
I для цього в С/С++ є оператор sizeof(), який повертає розмiр пам’ятi в
байтах, яку займає змiнна:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
l o n g double number = 2 ;
s t d : : cout << " s i z e o f ( number)=" << s i z e o f ( number ) ;
32
return 0;
}
Специфiкатор auto
Iнодi важко визначити тип виразу. I згiдно останнiм стандартам можна на-
дати компiлятору самому виводити тип об’єкту. I для цього застосовується
специфiкатор auto. При цьому якщо ми визначаємо змiнну iз специфiкатором
auto, ця змiнна повинна обов’язково iнiцiалiзувати яким-небудь значенням:
auto number = 5 ;
У даному випадку числовiй змiннiй типу int привласнюється символ ’g’. Цей
символ автоматично перетворюватиметься в число. По факту змiнна одер-
жить числовий код цього символу в таблицi ASCII.
Змiнної letter, навпаки, привласнюється число, хоча ця змiнна представляє
тип char. Це число перетворюватиметься в символ, i у результатi змiнна
letter берегтиме символ, чий код в таблицi ASCII рiвний 103, тобто символ
’g’.
Результатом цiєї програми буде наступний консольний вивiд:
i n ASCII i s 103
Як виконуються перетворення:
— Змiннiй типу bool привласнюється значення iншого типу. В цьому випадку
змiнна одержує false, якщо значення рiвне 0. У всiй рештi випадкiв змiнна
одержує true.
bool а = 1; // t r u e
bool b = 0; // f a l s e
bool c = ’g ’ ; // t r u e
bool d = 3.4; // t r u e
3.3. Константи
int b = 7;
int c = а ∗ b; // 70
int d = b ∗ 5; // 35
При дiленнi варто бути уважним, оскiльки якщо в операцiї беруть участь
два цiлi числа, то результат дiлення округлятиметься до цiлого числа, навiть
якщо результат привласнюється змiнної float або double:
double k = 10 / 4 ; // 2
s t d : : cout << k ;
Також є двi унарнi арифметичнi операцiї, якi проводяться над одним числом:
++ (iнкремент) i – (декремент). Кожна з операцiй має два рiзновиди: пре-
фiксна i постфiксна:
Префiксний iнкремент Збiльшує значення змiнної на одиницю i одержа-
ний результат використовується як значення виразу ++x
int а = 8;
int b = ++a ;
std : : cout << а << "\n " ; // 9
std : : cout << b << "\n " ; // 9
int а = 8;
int b = 7;
int c = ( а + 5) ∗ ++b ; // 104
std : : cout << c ;
Операцiї привласнення
Приклади операцiй:
41
int a = 5;
a += 1 0 ; // 15
a −= 3 ; // 12
a ∗= 2 ; // 24
a /= 6 ; // 4
a <<= 4 ; // 64
a >>= 2 ; // 16
3.5. Посилання
i n t main ( )
{
i n t number = 5 ;
i n t &refNumber = number ;
s t d : : cout << refNumber << s t d : : e n d l ; // 5
refNumber = 2 0 ;
s t d : : cout << number << s t d : : e n d l ; // 20
42
return 0;
}
Змiни по посиланню неминуче позначаться i на тому об’єктi, на який поси-
лається посилання.
Можна визначати не тiльки посилання на змiннi, але i посилання на констан-
ти. Але при цьому посилання саме повинне бути константним:
c o n s t i n t number = 5 ;
c o n s t i n t &refNumber = number ;
s t d : : cout << refNumber << s t d : : e n d l ; // 5
// refNumber = 2 0 ; изменять значение по ссылке нельзя
Iнiцiалiзувати неконстантне посилання константним об’єктом ми не можемо:
c o n s t i n t number = 5 ;
i n t &refNumber = number ; // ошибка
Також константне посилання може указувати i на звичайну змiнну, тiльки
значення по такому посиланню ми не зможемо змiнити:
i n t number = 5 ;
c o n s t i n t &refNumber = number ;
s t d : : cout << refNumber << s t d : : e n d l ; // 5
// refNumber = 2 0 ; изменять значение
// по ссылке на константу нельзя
// но мы можем изменить саму переменную
number = 2 0 ;
s t d : : cout << refNumber << s t d : : e n d l ; // 20
У даному випадку не дивлячись на те, що ми не можемо напряму змiнити
значення по константному посиланню, проте ми можемо змiнити сам об’єкт,
що приведе природно до змiни константного посилання.
i n t main ( )
{
i n t age ;
s t d : : cout << " Input age : " ;
s t d : : c i n >> age ;
s t d : : cout << "Your age : "
<< age << s t d : : e n d l ;
return 0;
}
Тут використовуються вiдразу три об’єкти з програнства iмен std: cout, cin i
endl. Перепишемо програму з використанням using:
#i n c l u d e <i o s t r e a m >
using std : : cin ;
u s i n g s t d : : cout ;
using std : : endl ;
i n t main ( )
{
i n t age ;
cout << " Input age : " ;
c i n >> age ;
cout << "Your age : "
<< age << e n d l ;
return 0;
}
Для кожного об’єкту з простору std визначається свiй вираз using. При цьому
програма працюватиме також як i ранiше.
Умовнi вирази є деякою умовою i повертають значення типу bool, тобто зна-
чення true (якщо умова iстинна), або значення false (якщо умова помилкова).
До умовних виразiв вiдносяться операцiї вiдношення i логiчнi операцiї.
У мовi програмування C++ є наступнi операцiї вiдношення:
— == Операцiя ”рiвно”. Повертає true, якщо обидва операнди рiвнi, i false,
якщо вони не рiвнi:
int a = 10;
int b = 4;
b o o l c = a == b ; // f a l s e
b o o l d = a == 1 0 ; // t r u e
— > Операцiя ”бiльш нiж”. Повертає true, якщо перший операнд бiльше дру-
гого, i false, якщо перший операнд менше другого:
int a = 10;
int b = 4;
bool c = a > b ; // t r u e
45
— < Операцiя ”менше нiж”. Повертає true, якщо перший операнд менше дру-
гого, i false, якщо перший операнд бiльше другого:
b o o l c = 10 < 4 ; // f a l s e
— <= Операцiя ”менше або рiвно”. Повертає true, якщо перший операнд мен-
ше або рiвно другому, i false, якщо перший операнд бiльше другого:
b o o l c = 10 <= 4 ; // f a l s e
b o o l d = 10 <= 1 4 ; // t r u e
— >= Операцiя ”бiльше або рiвно”. Повертає true, якщо перший операнд
бiльше або рiвно другому, i false, якщо перший операнд менше другого:
b o o l c = 10 >= 4 ; // t r u e
b o o l d = 10 >= 1 4 ; // f a l s e
bool a = true ;
bool b = false ;
bool c = a || b; // t r u e
bool d = b || false ; // f a l s e
Вживання операцiй:
int a = 5 | 2; // 101 | 010 = 111 − 7
int b = 6 & 2; // 110 & 010 = 10 − 2
int c = 5 ^ 2; // 101 ^ 010 = 111 − 7
int d = ~9; // −10
Вiзьмемо iнший вираз 6 & 2. Число 6 в двiйковому записi рiвно 110, а число
2 - 10 або 010. Помножимо вiдповiднi розряди обох чисел. Твiр обох розря-
дiв рiвний 1, якщо обидва цi розряди рiвнi 1. Iнакше твiр рiвний 0. Тому
одержуємо:
1 1 0
0 1 0
0 1 0
Конструкцiя if
i n t main ( )
{
int x = 60;
i f ( x > 50)
{
s t d : : cout << "x i s g r e a t e r than 50 \n " ;
}
49
i f ( x < 30)
{
s t d : : cout << "x i s l e s s than 30 \n " ;
}
Тут визначено двi умовнi конструкцiї if. Вони перевiрять бiльше або мен-
ше значення змiнної x, нiж певне значення. Як iнструкцiя в обох випадках
виконується виведення деякого рядка на консоль.
У першому випадку x > 50 умова iстинна, оскiльки значення змiнної x дiйсне
бiльше 50, тому ця умова поверне true, i, отже, будуть виконаються iнструкцiї,
якi входять в блок if.
У другому випадку операцiя вiдношення x < 30 поверне false, оскiльки умова
помилкова, тому подальший блок iнструкцiй виконуватися не буде. У резуль-
татi при запуску програми виведення консолi виглядатиме таким чином:
x g r e a t e r than 50
End o f Program
У даному випадку умова x > 60 помилково, тобто повертає false, тому вико-
нуватиметься блок else. I у результатi на консоль буде виведений рядок ”x is
less or equal 60 n”.
50
i f ( x > 60)
{
s t d : : cout << "x i s g r e a t e r than 60 \n " ;
}
e l s e i f ( x < 60)
{
s t d : : cout << "x i s l e s s than 60 \n " ;
}
else
{
s t d : : cout << "x i s e q u a l 60 \n " ;
}
i f ( x > 60)
s t d : : cout << "x i s g r e a t e r than 60 \n " ;
e l s e i f ( x < 60)
s t d : : cout << "x i s l e s s than 60 \n " ;
else
s t d : : cout << "x i s e q u a l 60 \n " ;
Конструкцiя switch
default : iнструкцiї ;
}
i n t main ( )
{
int x = 2;
switch (x)
{
case 1:
s t d : : cout << "x = 1" << "\n " ;
break ;
case 2:
s t d : : cout << "x = 2" << "\n " ;
break ;
case 3:
s t d : : cout << "x = 3" << "\n " ;
break ;
default :
s t d : : cout << "x i s u n d e f i n e d " << "\n " ;
break ;
}
return 0;
}
наступний рядок
x = 2
Варто вiдзначити важливiсть використовування оператора break. Якщо ми
його не вкажемо в блоцi case, то пiсля цього блоку виконання перейде до
наступного блоку case. Наприклад, приберемо з попереднього прикладу всi
оператори break:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
int x = 2;
switch (x)
{
case 1:
std : : cout << "x = 1" << "\n " ;
case 2:
std : : cout << "x = 2" << "\n " ;
case 3:
std : : cout << "x = 3" << "\n " ;
default :
std : : cout << "x i s u n d e f i n e d " << "\n " ;
}
return 0;
}
У цьому випадку знову ж таки виконуватиметься оператор case 2:, оскiльки
змiнна x=2. Проте оскiльки цей блок case не завершується оператором break,
то пiсля його завершення виконуватиметься набiр iнструкцiй пiсля case 3:
навiть не дивлячись на те, що змiнна x як i ранiше рiвна 2. У результатi ми
одержимо наступний консольний вивiд:
x = 2
x = 3
x i s undefined
i n t main ( )
{
s e t l o c a l e (LC_ALL, " " ) ;
int x = 5;
int y = 3;
char s i g n ;
s t d : : cout << " Введiть знак о п е р а ц i ї : " ;
s t d : : c i n >> s i g n ;
i n t r e s u l t = s i g n ==’+’?x + y : x − y ;
s t d : : cout << " Результат : " << r e s u l t << "\n " ;
return 0;
}
Для виконання деяких дiй множина разiв залежно вiд певної умови викори-
стовуються цикли. В мовi C++ є наступнi види циклiв:
• for
• while
• do...while
Цикл while виконує деякий код, поки його умова iстинна, тобто повертає true.
Вiн має наступне формальне визначення:
w h i l e ( умова )
{
// виконання коду
}
Пiсля ключового слова while в дужках йде умовний вираз, який повертає true
або false. Потiм у фiгурних дужках йде набiр iнструкцiй, якi складають тiло
циклу. I поки умова повертає true, виконуватимуться iнструкцiї в тiлi циклу.
Наприклад, виведемо квадрати чисел вiд 1 до 9:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
int i = 1;
w h i l e ( i < 10)
{
s t d : : cout << i << " ∗ " << i
<< " = " << i ∗ i << s t d : : e n d l ;
i ++;
}
return 0;
}
55
Тут поки умова i < 10 iстинно, виконуватиметься цикл while, в якому виводи-
ться на консоль квадрат числа i инкрементируется змiнна i. В якийсь момент
змiнна i збiльшиться до 10, умова i < 10 поверне false, i цикл завершиться.
Консольне виведення програми:
1 ∗ 1 = 1
2 ∗ 2 = 4
3 ∗ 3 = 9
4 ∗ 4 = 16
5 ∗ 5 = 25
6 ∗ 6 = 36
7 ∗ 7 = 49
8 ∗ 8 = 64
9 ∗ 9 = 81
i n t main ( )
{
f o r ( i n t i =1; i < 1 0 ; i ++)
{
s t d : : cout << i << " ∗ " << i
<< " = " << i ∗ i << s t d : : e n d l ;
}
return 0;
}
Перша частина оголошення циклу - int i = 1 - створює i iнiцiалiзував лi-
чильник i. Фактично це те ж саме, що i оголошення i iнiцiалiзацiя змiнної.
Лiчильник необов’язково повинен представляти тип int. Це може бути i iн-
ший числовий тип, наприклад, float. I перед виконанням циклу його значення
буде рiвне 1.
Друга частина - умова, при якiй виконуватиметься цикл. В даному випадку
цикл виконуватиметься, поки змiнна i не стане рiвна 10.
I третя частина - прирiст лiчильника на одиницю. Знову ж таки нам необо-
в’язково збiльшувати на одиницю. Можна зменшувати: i–. Можна змiнювати
на iнше значення: i+=2.
У результатi блок циклу спрацює 9 разiв, поки змiнна i не стане рiвна 10. I
кожного разу це значення збiльшуватиметься на 1. I по сутi ми одержимо той
же самий результат, що i у випадку з циклом while:
1 ∗ 1 = 1
2 ∗ 2 = 4
3 ∗ 3 = 9
4 ∗ 4 = 16
5 ∗ 5 = 25
6 ∗ 6 = 36
7 ∗ 7 = 49
8 ∗ 8 = 64
9 ∗ 9 = 81
Необов’язково указувати всi три вирази у визначеннi циклу, ми можемо одне
або навiть все з них опустити:
int i = 1;
57
Формально визначення циклу залишилося тим же, тiльки тепер перше i третє
вирази у визначеннi циклу вiдсутнi: for (; i < 10;). Змiнна-лiчильник визначена
i iнiцiалiзувала зовнi циклу, а її прирiст вiдбувається в самому циклi.
Можна визначати вкладенi цикли. Наприклад, виведемо таблицю множення:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
f o r ( i n t i =1; i < 1 0 ; i ++)
{
f o r ( i n t j = 1 ; j < 1 0 ; j ++)
{
s t d : : cout << i ∗ j << "\ t " ;
}
s t d : : cout << s t d : : e n d l ;
}
return 0;
}
5.3. Цикл do
Наприклад:
58
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
int i = 6;
do
{
s t d : : cout << i << s t d : : e n d l ;
i −−;
}
w h i l e ( i >0);
return 0;
}
Хоча у нас змiнна i менше 0, цикл все одно один раз виконається.
i n t main ( )
{
int i = 1;
for ( ; ; )
{
59
Тут коли значення змiнної i досягне 10, здiйснюється вихiд з циклу за допо-
могою оператора break.
На вiдмiну вiд оператора break, оператор continue проводить перехiд до насту-
пної iтерацiї. Наприклад, нам треба порахувати суму тiльки непарних чисел
з деякого дiапазону:
#i n c l u d e <i o s t r e a m > main ( )
{
int result = 0;
f o r ( i n t i =0; i <10; i ++)
{
i f ( i % 2 == 0) c o n t i n u e ;
r e s u l t +=i ;
}
s t d : : cout << " r e s u l t = " << r e s u l t
<< s t d : : e n d l ; // 25
return 0;
}
Пiсля типу змiнної йде назва масиву, а потiм в квадратних дужках його роз-
мiр. Наприклад, визначимо масив з 4 чисел:
i n t numbers [ 4 ] ;
Даний масив має чотири числа, але всi цi числа мають невизначене значення.
Проте ми можемо виконати iнiцiалiзацiю i привласнити цим числам деякi
початковi значення через фiгурнi дужки:
i n t numbers [ 4 ] = { 1 , 2 , 3 , 4 } ;
i n t main ( )
{
i n t numbers [ 4 ] = { 1 , 2 , 3 , 4 } ;
i n t first_number = numbers [ 0 ] ;
s t d : : cout << first_number << s t d : : e n d l ; // 1
numbers [ 0 ] = 3 4 ; // изменяем элемент
s t d : : cout << numbers [ 0 ] << s t d : : e n d l ; // 34
return 0;
}
i n t main ( )
{
i n t numbers [ 4 ] = { 1 , 2 , 3 , 4 } ;
i n t s i z e = s i z e o f ( numbers )/ s i z e o f ( numbers [ 0 ] ) ;
f o r ( i n t i =0; i < s i z e ; i ++)
s t d : : cout << numbers [ i ] << s t d : : e n d l ;
return 0;
62
}
Щоб пройтися по масиву в циклi, спочатку треба знайти довжину масиву.
Для знаходження довжини застосовується оператор sizeof. По сутi довжина
масиву рiвна сукупнiй довжинi його елементiв. Всi елементи представляють
один i той же тип i займають один i той же розмiр в пам’ятi. Тому за допо-
могою виразу sizeof(numbers) знаходимо довжину всього масиву в байтах, а
за допомогою виразу sizeof(numbers[0]) - довжину одного елементу в байтах.
Роздiливши два значення, можна одержати кiлькiсть елементiв в масивi. А
далi за допомогою циклу for перебираємо всi елементи, поки лiчильник i не
стане рiвним довжинi масиву. У результатi на консоль будуть виведенi всi
елементи масиву:
1
2
3
4
Але також є i ще одна форма циклу for, яка призначена спецiально для роботи
з колекцiями, у тому числi i з масивами. Ця форма має наступне формальне
визначення:
f o r ( тип змiнна : колекцiя )
{
iнструкцiї ;
}
Використовуємо цю форму для перебору масиву:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
i n t numbers [ 4 ] = { 1 , 2 , 3 , 4 } ;
f o r ( i n t number : numbers )
s t d : : cout << number << s t d : : e n d l ;
return 0;
}
При переборi масиву кожний перебираний елемент помiщатиметься в змiнну
number, значення якої в циклi виводиться на консоль.
Якщо нам невiдомий тип об’єктiв в масивi, то ми можемо використовувати
специфiкатор auto для визначення типу:
f o r ( auto number : numbers )
63
Такий масив складається з трьох елементiв, при цьому кожний елемент пред-
ставляє масив з двох елементiв. Iнiцiалiзували подiбний масив:
i n t numbers [ 3 ] [ 2 ] = { {1 , 2} , {4 , 5} , {7 , 8} } ;
i n t main ( )
{
c o n s t i n t rows = 3 , columns = 2 ;
i n t numbers [ rows ] [ columns ] = { {1 , 2} , {3 , 4} , {5 , 6} } ;
f o r ( i n t i =0; i < rows ; i ++)
{
f o r ( i n t j =0; j < columns ; j ++)
64
{
s t d : : cout << numbers [ i ] [ j ] << "\ t " ;
}
s t d : : cout << s t d : : e n d l ;
}
return 0;
}
i n t main ( )
{
c o n s t i n t rows = 3 , columns = 2 ;
i n t numbers [ rows ] [ columns ] = { {1 , 2} , {3 , 4} , {5 , 6} } ;
return 0;
}
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
s t d : : s t r i n g h e l l o = " H e l l o World ! " ;
s t d : : cout << h e l l o << "\n " ;
return 0;
}
Тип string визначений в стандартнiй бiблiотецi i при його використовуваннi
треба указувати простiр iмен std.
Або можна використовувати вираз using, щоб не указувати префiкс std:
using std : : s t r i n g ;
У даному випадку значення змiнної hello, яка представляє тип string, виво-
диться на консоль.
При компiляцiї через g++ може бути потрiбно вказати прапор -static. Тобто
якщо код визначений у файл hello.cpp, то команда на компiляцiю для g++
може виглядати таким чином:
g++ h e l l o . cpp −o h e l l o −s t a t i c
Для iнiцiалiзацiї рядкiв можна використовувати рiзнi способи:
#i n c l u d e <s t r i n g >
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
std : : s t r i n g s1 ; // пустая строка
std : : s t r i n g s2 = " h e l l o " ; // h e l l o
std : : s t r i n g s3 (" welcome " ) ; // welcome
std : : s t r i n g s4 ( 5 , ’ h ’ ) ; // hhhhh
std : : s t r i n g s5 = s2 ; // h e l l o
hello
welcome
hhhhh
hello
Якщо при визначеннi змiнної типу string ми не привласнюємо їй нiякого зна-
чення, то за умовчанням дана змiнна мiстить порожнiй рядок:
s t d : : s t r i n g s1 ;
Також можна iнiцiалiзувати змiнну рядковим лiтералом, який полягає в по-
двiйнi лапки:
s t d : : s t r i n g s2 = " h e l l o " ;
Як альтернатива можна передавати рядок в дужках пiсля визначення змiн-
ної:
s t d : : s t r i n g s3 (" welcome " ) ;
Якщо необхiдно, щоб рядок мiстив визначену кiлькiсть визначених символiв,
то можна вказати в дужках кiлькiсть символiв i сам символ:
s t d : : s t r i n g s4 ( 5 , ’ h ’ ) ;
I також можна передати змiннiй копiю iншого рядка:
s t d : : s t r i n g s5 = s2 ;
Конкатенацiя рядкiв
i n t main ( )
{
s t r i n g s1 = " h e l l o " ;
s t r i n g s2 = " world " ;
s t r i n g s3 = s1 + " " + s2 ; // h e l l o world
cout << s3 << e n d l ;
return 0;
}
67
Порiвняння рядкiв
b o o l r e s u l t = s1 == s2 ; // f a l s e
r e s u l t = s1 == " H e l l o " ; // f a l s e
r e s u l t = s1 == " h e l l o " ; // t r u e
b o o l r e s u l t = s1 != s2 ; // t r u e
r e s u l t = s1 != " H e l l o " ; // t r u e
r e s u l t = s1 != " h e l l o " ; // f a l s e
Решта базових операцiй порiвняння < <= > >= порiвнюють рядки залежно
вiд регiстра i алфавiтного порядку символiв. Наприклад, рядок "b"умовно
бiльший рядка "a оскiльки символ "b"за абеткою йде пiсля символу "а". А
рядок "a"бiльше рядка "A". Якщо першi символи рядка рiвнi, то порiвнюю-
ться подальшi символи:
s t d : : s t r i n g s1 = " Aport " ;
s t d : : s t r i n g s2 = " A p r i c o t " ;
b o o l r e s u l t = s1 > s2 ; // f a l s e
У даному випадку умова s1 > s2 помилкове, тобто s2 бiльш нiж s1, оскiльки
при рiвностi перших двох символiв ("Ар") третiй символ другого рядка ("o")
стоїть в алфавiтi до третього символу другого рядка ("p"), тобто "o"менше
нiж "p".
Розмiр рядка
i n t main ( )
{
s t d : : s t r i n g name ;
s t d : : cout << " Input your name : " ;
s t d : : c i n >> name ;
s t d : : cout << "Your name : " << name << s t d : : e n d l ;
return 0;
}
Консольне введення
Проте якщо при даному способi введення рядок мiститиме пiдрядки, роздi-
ленi пропуском, то std::cin використовуватиме тiльки перший пiдрядок:
Input your name : Tom Smith
Your name : Tom
i n t main ( )
{
69
s t d : : s t r i n g name ;
s t d : : cout << " Input your name : " ;
g e t l i n e ( s t d : : cin , name ) ;
s t d : : cout << "Your name : " << name << s t d : : e n d l ;
return 0;
}
Метод getline приймає два об’єкти - std::cin i змiнну, в яку треба занести
рядок.
Консольне виведення:
Input your name : Tom Smith
Your name : Tom Smith
i n t main ( )
{
char l e t t e r s [ ] = { ’ h ’ , ’ e ’ , ’ l ’ , ’ l ’ , ’ o ’ , ’ \ 0 ’ } ;
s t d : : cout << l e t t e r s << s t d : : e n d l ;
return 0;
}
Даний код виведе на консоль рядок "hello". Подiбне визначення масиву ряд-
кiв буде також еквiвалентне наступному:
char l e t t e r s [ ] = " h e l l o " ;
70
Визначення функцiї
Виконання функцiї
Оголошення функцiї
}
exchange ( double c u r r a t e , double sum )
{
double r e s u l t = sum / c u r r a t e ;
s t d : : cout << " Rate : " << c u r r a t e << "\tSum : " << sum
<< "\ t R e s u l t : " << r e s u l t << s t d : : e n d l ;
}
return 0;
} square ( int x)
{
s t d : : cout << " Square " << x << " i s e q u a l
to " << x ∗ x << s t d : : e n d l ;
}
d i s p l a y ( s t d : : s t r i n g name , i n t age )
{
s t d : : cout << "Name : " << name << "\ tAge : " <<
age << s t d : : e n d l ;
}
75
Функцiя display приймає параметри типiв string i int. При виклику цiєї фун-
кцiї в неї спочатку передається рядок (”Tom”), оскiльки параметр типу string
йде першим, а потiм число (33), оскiльки параметр типу int йде другим: di-
splay(”Tom”, 33)
Функцiя square приймає число i виводить на консоль його квадрат. Пара-
метр функцiї представляє тип int, проте при її виклику їй передається число
з плаваючою крапкою, тобто значення типу double. Тому проводиться пе-
ретворення вiд типу double до типу int, дробова частина вiдкидається, i у
результатi функцiя одержує число 4.
При оголошеннi прототипу подiбної функцiї вiн теж може мiстити значення
за умовчанням для параметра. I в цьому випадку ми можемо не визнача-
ти у функцiї значення за умовчанням для параметра - воно братиметься з
прототипу:
#i n c l u d e <i o s t r e a m >
m u l t i p l y ( i n t n , i n t m=3);
main ( )
76
{
multiply (4 , 5);
multiply ( 4 ) ;
return 0;
}
m u l t i p l y ( i n t n , i n t m)
{
i n t r e s u l t = n ∗ m;
s t d : : cout << "n ∗ m = " << r e s u l t << s t d : : e n d l ;
return 0;
} square ( int а , int b)
{
а = а ∗ а;
b = b ∗ b;
s t d : : cout << " In s q u a r e :
а = " << а << "\ tb=" << b << s t d : : e n d l ;
}
return 0;
} s q u a r e ( i n t &a , i n t &b )
{
а = а ∗ а;
b = b ∗ b;
s t d : : cout << " In s q u a r e :
а = " << а << "\ tb=" << b << s t d : : e n d l ;
}
78
return 0;
} square ( int а , int b)
{
а = а ∗ а;
b = b ∗ b;
s t d : : cout << " In s q u a r e :
а = " << а << "\ tb=" << b << s t d : : e n d l ;
}
s q u a r e : а = 16 b = 25
square : а = 4 b = 5
Константнi параметри
}
void square ( const i n t а , const i n t b)
{
// a = а ∗ а ; так не можна зробити
//b = b ∗ b ; так не можна зробити
s t d : : cout << " In s q u a r e : а ∗ b = " << а ∗ b << s t d : : e n d l ;
}
Вiд цiєї ситуацiї слiд вiдрiзняти передачу констант як аргументи для некон-
стантних параметрiв:
#i n c l u d e <i o s t r e a m >
void square ( int , i n t ) ;
i n t main ( )
{
const int а = 4;
const int b = 5;
square (а , b ) ; // 400
return 0;
}
void square ( i n t а , i n t b)
{
а = а ∗ а;
b = b ∗ b;
s t d : : cout << " In s q u a r e : а ∗ b = " << а ∗ b << s t d : : e n d l ;
}
Константнi посилання
return 0;
}
v o i d s q u a r e ( c o n s t i n t &a , c o n s t i n t &b )
{
// а = а ∗ а ; так не можна зробити
// b = b ∗ b ; так не можна зробити
s t d : : cout << " In s q u a r e : а ∗ b = " << а ∗ b << s t d : : e n d l ;
}
void f a c t o r i a l ( i n t n)
{
i f ( n<1)
{
s t d : : cout << " I n c o r r e c t number" << s t d : : e n d l ;
return ;
}
int result = 1;
f o r ( i n t i = 1 ; i <=n ; i ++)
82
{
r e s u l t ∗= i ;
}
s t d : : cout << " F a c t o r i a l " << n <<
" i s e q u a l to " << r e s u l t << s t d : : e n d l ;
}
int f a c t o r i a l ( int n)
{
int result = 1;
f o r ( i n t i = 1 ; i <=n ; i ++)
{
r e s u l t ∗= i ;
}
return r e s u l t ;
}
int f a c t o r i a l ( int n)
{
i f ( n>1)
r e t u r n n ∗ f a c t o r i a l ( n −1);
return 1;
}
5 ∗ 4 ∗ f a c t o r i a l (3)
5 ∗ 4 ∗ 3 ∗ f a c t o r i a l (2)
5 ∗ 4 ∗ 3 ∗ 2 ∗ f a c t o r i a l (1)
5 ∗ 4 ∗ 3 ∗ 2 ∗ 1
Глобальнi об’єкти
void pri nt ( )
{
n++;
s t d : : cout << "n=" << n << s t d : : e n d l ;
}
Локальнi об’єкти
Об’єкти, якi створюються усерединi блоку коду (вiн може представляти фун-
кцiю або яку-небудь конструкцiю типу циклiв), називаються локальними. Та-
кi об’єкти доступнi в межах тiльки того блоку коду, в якому вони визначенi.
Автоматичнi об’єкти
Локальнi об’єкти, якi iснують тiльки пiд час виконання того блоку, в якому
вони визначенi, є автоматичними.
При входi в блок для подiбних змiнних видiляється пам’ять, а пiсля завер-
шення роботи цього блоку, видiлена пам’ять звiльняється, а об’єкти вiддаля-
ються.
#i n c l u d e <i o s t r e a m >
void pri nt ( i n t ) ;
i n t main ( )
{
int z = 2;
p r i n t ( z ) ; // n=10
//n++; так зробити не можна ,
// оскiльки n визначена у функцiї p r i n t
return 0;
}
void pri nt ( i n t x )
{
int n = 5 ∗ x ;
// z++; так зробити не можна ,
// оскiльки z визначена у функцiї main
s t d : : cout << "n=" << n << s t d : : e n d l ;
}
Так само за допомогою блоку коду можна визначити вкладенi областi види-
мостi:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
int n = 2;
{
int x = 5;
s t d : : cout << "x=" << x << s t d : : e n d l ;
n++; // так можна ,
// оскiльки n визначена в зовнiшньому к о н т е к с т i
}
//x++; // так зробити не можна ,
// оскiльки x визначена в блоцi коду
s t d : : cout << "n=" << n << s t d : : e n d l ;
return 0;
}
Для кожної областi видимостi доступнi всi тi об’єкти, якi визначенi в зов-
нiшнiй областi видимостi або в зовнiшньому контекстi. Глобальна область
видимостi є зовнiшньою для функцiї, тому функцiя може використовувати
глобальнi змiннi. А фукция є зовнiшнiм контекстом для вкладеного блоку
коду, тому блок коду може використовувати змiнну n, яка визначена у фун-
кцiї зовнi цього блоку. Проте змiннi, визначенi в блоцi коду, зовнi цього блоку
використовувати не можна.
Заховування об’єктiв
{
int n = 20;
s t d : : cout << "n=" << n << s t d : : e n d l ; // n=20
88
}
return 0;
}
Статичнi об’єкти
return 0;
}
return 0;
}
До змiнної був додано ключове слово static, тому при завершеннi роботи
функцiї display змiнна не знищується, її пам’ять не очищається, навпаки, вона
зберiгається в пам’ятi. I вiдповiдно результат роботи програми буде iншим:
i =1
i =2
i =3
Зовнiшнi об’єкти
Окрiм функцiй зовнiшнi файли можуть мiстити рiзнi об’єкти - змiннi i кон-
станти. Для пiдключення зовнiшнiх об’єктiв у файл коду застосовується клю-
чове слово extern.
Для оголошення об’єктiв визначимо файл objects.h з наступним вмiстом:
extern const int x ;
e x t e r n double у ;
const int x = 5;
double у = 3 . 4 ;
return 0;
}
8.1. Покажчики
Поки покажчик не посилається нi на який об’єкт. При цьому на вiдмiну вiд по-
силання покажчик необов’язково iнiцiалiзувати яким-небудь значенням. Те-
пер привласнимо покажчику адресу змiнної:
i n t x = 1 0 ; // визначаємо змiнну
i n t ∗p ; // визначаємо покажчик =
p = &x ; // покажчик одержує адресу з м i н н о ї
Консольний висновок:
Address = 0 x 6 0 f e 9 8
Value = 10
return 0;
}
Привласнення
Покажчику можна привласнити або адресу об’єкту того ж типу, або значення
iншого покажчика.
Привласнення покажчику адреси вже розглядалося в минулiй темi. Для отри-
мання адреси об’єкту використовується операцiя &:
int а = 10;
i n t ∗pa = &a ; // покажчик pa береже адресу з м i н н о ї а
При цьому покажчик i змiнна повиннi мати один i той же тип, в даному
випадку це тип int.
Привласнення покажчику iншого покажчика:
#i n c l u d e <i o s t r e a m >
u s i n g s t d : : cout ;
using std : : endl ;
i n t main ( )
{
int а = 10;
int b = 2;
i n t ∗pa = &a ;
i n t ∗pb = &b ;
return 0;
}
Нульовi покажчики
Посилання на покажчики
i n t ∗p = 0 ; // покажчик
i n t ∗&pRef = p ; // посилання на покажчик
pRef = &a ; // через посилання покажчику p
// привласнюється адреса з м i н н о ї а
s t d : : cout << "p v a l u e=" << ∗p << s t d : : e n d l ; // 10
∗ pRef = 7 0 ; // змiнюємо значення за адресою ,
// на яку указує покажчик
s t d : : cout << "а v a l u e=" << а << s t d : : e n d l ; // 70
return 0;
}
96
Розiменування покажчика
i n t ∗pa = &a ;
i n t ∗pb = pa ;
∗pa = 2 5 ;
return 0;
}
Адреса покажчика
Операцiї порiвняння
i f ( pa > pb )
cout << "pa (" << pa << ") i s
g r e a t e r than pb ("<< pb << ")" << e n d l ;
else
cout << "pa (" << pa << ") i s
l e s s or e q u a l pb ("<< pb << ")" << e n d l ;
return 0;
}
Приведення типiв
{
char з = ’N ’ ;
char ∗pc = &c ;
i n t ∗pd = ( i n t ∗) pc ;
v o i d ∗pv = ( v o i d ∗) pc ;
s t d : : cout << "pv=" << pv << s t d : : e n d l ;
s t d : : cout << "pd=" << pd << s t d : : e n d l ;
return 0;
}
i n t ∗ p t r = &n ;
s t d : : cout << " a d d r e s s=" << p t r <<
99
p t r ++;
s t d : : cout << " a d d r e s s=" << p t r <<
"\ t v a l u e=" << ∗ p t r << s t d : : e n d l ;
ptr −−;
s t d : : cout << " a d d r e s s=" << p t r <<
"\ t v a l u e=" << ∗ p t r << s t d : : e n d l ;
return 0;
}
double d = 1 0 . 6 ;
double ∗pd = &d ;
s t d : : cout << " P o i n t e r pd :
a d d r e s s : " << pd << s t d : : e n d l ;
pd++;
s t d : : cout << " P o i n t e r pd :
a d d r e s s : " << pd << s t d : : e n d l ;
char з = ’N ’ ;
char ∗pc = &c ;
s t d : : cout << " P o i n t e r pc :
a d d r e s s : " << ( v o i d ∗) pc << s t d : : e n d l ;
pc++;
s t d : : cout << " P o i n t e r pc :
a d d r e s s : " << ( v o i d ∗) pc << s t d : : e n d l ;
return 0;
}
char з = ’N ’ ;
char ∗pc = &c ;
s t d : : cout << " P o i n t e r pc :
a d d r e s s : " << ( v o i d ∗) pc << s t d : : e n d l ;
pc = pc − 3 ;
s t d : : cout << " P o i n t e r pc :
a d d r e s s : " << ( v o i d ∗) pc << s t d : : e n d l ;
return 0;
}
return 0;
}
pa : a d d r e s s=0x 6 0 f e 9 4 v a l u e =10
b : v a l u e =6356864
pa : a d d r e s s=0x 6 0 f e 9 8 v a l u e =6356864
Покажчики та константи
return 0;
}
Тут покажчик pa указує на константу а. Тому навiть якщо ми схочемо змi-
нити значення за адресою, яка бережеться в покажчику, ми не зможемо це
зробити, наприклад так:
∗pa = 3 4 ;
У цьому випадку ми просто одержимо помилку пiд час компiляцiї.
Можлива також ситуацiя, коли покажчик на константу насправдi указує на
змiнну:
#i n c l u d e <i o s t r e a m >
i n t main ( )
{
int а = 10;
c o n s t i n t ∗pa = &a ;
s t d : : cout <<"v a l u e=" << ∗pa << s t d : : e n d l ; // 10
а = 22;
s t d : : cout <<"v a l u e=" << ∗pa << s t d : : e n d l ; // 22
//∗ pa = 3 4 ; // так робити не можна
return 0;
105
Константний покажчик
return 0;
}
int а = 10;
c o n s t i n t ∗ c o n s t pa = &a ;
// ∗pa = 2 2 ; так зробити не можна
int b = 45;
// pa = &b ; так зробити не можна
Наприклад, хай у нас буде найпростiша функцiя, яка збiльшує число на оди-
ницю:
#i n c l u d e <i o s t r e a m >
void increment ( i n t ) ;
i n t main ( )
{
int n = 10;
increment (n ) ;
s t d : : cout << "main f u n c t i o n :
" << x << s t d : : e n d l ;
return 0;
}
void increment ( i n t x )
{
x++;
s t d : : cout << " i n c r e m e n t f u n c t i o n :
" << x << s t d : : e n d l ;
}
void increment ( i n t ∗ ) ;
i n t main ( )
{
int n = 10;
i n c r e m e n t (&n ) ;
s t d : : cout << "main f u n c t i o n :
" << n << s t d : : e n d l ;
return 0;
}
108
v o i d i n c r e m e n t ( i n t ∗x )
{
(∗ x)++;
s t d : : cout << " i n c r e m e n t f u n c t i o n :
" << ∗x << s t d : : e n d l ;
}
void increment ( i n t ∗ ) ;
i n t main ( )
{
int n = 10;
i n t ∗ p t r = &n ;
increment ( ptr ) ;
s t d : : cout << "main f u n c t i o n :
" << n << s t d : : e n d l ;
return 0;
}
v o i d i n c r e m e n t ( i n t ∗x )
{
int z = 6;
x = &z ; // переустанавлюємо адрес покажчика x
s t d : : cout << " i n c r e m e n t f u n c t i o n :
" << ∗x << s t d : : e n d l ;
}
109
У даному випадку визначений покажчик, який має iм’я message. Вiн може
указувати на функцiї без параметрiв, якi повертають тип void (тобто нiчого
не повертають).
Використовуємо покажчик на функцiю:
#i n c l u d e <i o s t r e a m >
void h e l l o ( ) ;
v o i d goodbye ( ) ;
i n t main ( )
{
110
v o i d (∗ message ) ( ) ;
message=h e l l o ;
message ( ) ;
message = goodbye ;
message ( ) ;
return 0;
}
void h e l l o ( )
{
s t d : : cout << " H e l l o , World" << s t d : : e n d l ;
}
v o i d goodbye ( )
{
s t d : : cout << "Good Bye , World" << s t d : : e n d l ;
}
v o i d ∗ message ( ) ;
У другому випадку визначений не покажчик на функцiю, а прототип функцiї
message, яка повертає покажчик типу void*.
Розглянемо ще один покажчик на функцiю:
#i n c l u d e <i o s t r e a m >
i n t add ( i n t , i n t ) ;
int subtract ( int , int ) ;
i n t main ( )
{
int a = 10;
int b = 5;
int result ;
i n t (∗ o p e r a t i o n ) ( i n t a , i n t b ) ;
o p e r a t i o n=add ;
result = operation (a , b ) ;
// r e s u l t = (∗ o p e r a t i o n ) ( a , b ) ;
// альтернативний варiант
s t d : : cout << " r e s u l t =" << r e s u l t <<
s t d : : e n d l ; // r e s u l t =15
operation = subtract ;
result = operation (a , b ) ;
s t d : : cout << " r e s u l t =" << r e s u l t <<
s t d : : e n d l ; // r e s u l t =5
return 0;
}
i n t add ( i n t x , i n t y )
{
r e t u r n x+y ;
}
int subtract ( int x , int y)
{
r e t u r n x−y ;
}
Тут визначений покажчик operation, який може указувати на функцiю з дво-
ма параметрами типу int, що повертає також значення типу int. Вiдповiдно
112
Наприклад:
double (∗ a c t i o n s [ ] ) ( i n t , i n t )
v o i d add ( i n t , i n t ) ;
void subtract ( int , i n t ) ;
void multiply ( int , i n t ) ;
i n t main ( )
{
int a = 10;
int b = 5;
v o i d (∗ o p e r a t i o n s [ 3 ] ) ( i n t , i n t ) =
{add , s u b t r a c t , m u l t i p l y } ;
return 0;
}
113
v o i d add ( i n t x , i n t y )
{
s t d : : cout << "x + y = " << x + y << s t d : : e n d l ;
}
void subtract ( i n t x , i n t y )
{
int result = x − y ;
s t d : : cout << "x − y = " << x − y << s t d : : e n d l ;
}
void multiply ( i n t x , i n t y )
{
s t d : : cout << "x ∗ y = " << x ∗ y << s t d : : e n d l ;
}
Тут масив operations мiстить три функцiї add, subtract i multiply, якi по-
слiдовно викликаються в циклi через перебiр масиву у функцiї main.
Консольне виведення програми:
x + y = 15
x − y = 5
x ∗ y = 50
i n t add ( i n t , i n t ) ;
int subtract ( int , int ) ;
int operation ( int (∗)( int , int ) , int , int ) ;
i n t main ( )
{
int a = 10;
int b = 5;
int result ;
r e s u l t = o p e r a t i o n ( add , a , b ) ;
s t d : : cout << " r e s u l t : " << r e s u l t << s t d : : e n d l ;
r e s u l t = operation ( subtract , a , b ) ;
114
i n t add ( i n t x , i n t y )
{
return x + y ;
}
int subtract ( int x , int y)
{
return x − y ;
}
i n t o p e r a t i o n ( i n t (∗ op ) ( i n t , i n t ) , i n t a , i n t b )
{
r e t u r n op ( a , b ) ;
}
i n t isEven ( i n t ) ;
int isPositive ( int );
void action ( i n t ( ∗ ) ( i n t ) , i n t [ ] , i n t ) ;
i n t main ( )
{
i n t nums [ ] = { −5, −4, −3, −2, −1, 0 , 1 , 2 , 3 , 4 , 5 } ;
i n t n = s i z e o f ( nums )/ s i z e o f ( nums [ 0 ] ) ;
return 0;
}
i n t isEven ( i n t x )
{
r e t u r n x % 2 == 0 ;
}
int isPositive ( int x)
{
r e t u r n x >0;
}
v o i d a c t i o n ( i n t (∗ c o n d i t i o n ) ( i n t ) , i n t numbers [ ] , i n t n )
{
f o r ( i n t i = 0 ; i <n ; i ++)
{
i f ( c o n d i t i o n ( numbers [ i ] ) != 0)
{
s t d : : cout << numbers [ i ] << "\ t " ;
}
}
s t d : : cout << s t d : : e n d l ;
}
v o i d goodmorning ( ) ;
v o i d goodevening ( ) ;
v o i d (∗ message ( i n t ) ) ( ) ;
i n t main ( )
{
v o i d (∗ a c t i o n ) ( ) ;
// покажчик на вибрану функцiю
a c t i o n = message ( 1 5 ) ;
action ( ) ;
// виконуємо одержану функцiю
return 0;
}
v o i d (∗ message ( i n t hour ) ) ( )
{
i f ( hour > 12)
r e t u r n goodevening ;
else
r e t u r n goodmorning ;
}
v o i d goodmorning ( )
{
s t d : : cout << "Good Morning ! " << s t d : : e n d l ;
}
v o i d goodevening ( )
{
s t d : : cout << "Good Evening ! " << s t d : : e n d l ;
}
Тут визначена функцiя message, яка залежно вiд переданого числа повертає
одну з двох функцiй goodmorning або goodevening. Розглянемо оголоше-
117
i n t add ( i n t , i n t ) ;
int subtract ( int , int ) ;
int multiply ( int , int ) ;
i n t (∗ s e l e c t ( ) ) ( i n t , i n t ) ;
i n t main ( )
{
118
int x = 8;
int y = 5;
s t d : : cout << "x = " << x <<
"\ t y = " << y << s t d : : e n d l ;
s t d : : cout << " 1 : Add" << s t d : : e n d l ;
s t d : : cout << " 2 : S u b t r a c t " << s t d : : e n d l ;
s t d : : cout << " 3 : M u l t i p l y " << s t d : : e n d l ;
s t d : : cout << " 4 : Exit " << s t d : : e n d l ;
return 0;
}
i n t (∗ s e l e c t ( ) ) ( i n t , i n t )
{
i n t c h o i c e ; // вибраний пункт
// масив покажчикiв на функцiї , я к i повертатимуться
i n t (∗ a c t i o n s [ ] ) ( i n t x , i n t y ) =
{add , s u b t r a c t , m u l t i p l y } ;
//
s t d : : cout << " Enter a c t i o n ( 1 , 2 , 3 , 4 ) : " ;
s t d : : c i n >> c h o i c e ;
// повертаємо потрiбну функцiю
i f ( c h o i c e >0 && c h o i c e <4)
return actions [ choice − 1 ] ;
else
r e t u r n NULL;
}
i n t add ( i n t x , i n t y )
{
119
return x + y ;
}
int subtract ( int x , int y)
{
return x − y ;
}
int multiply ( int x , int y)
{
return x ∗ y ;
}
Iм’я масиву по сутi є адресою його першого елементу. Вiдповiдно через опе-
рацiю разiменування ми можемо набути значення за цiєю адресою:
i n t a [ ] = {1 , 2 , 3 , 4 , 5 } ;
s t d : : cout << "а [ 0 ] = " << ∗a << s t d : : e n d l ; // а [ 0 ] = 1
return 0;
}
Iм’я масиву завжди береже адресу найпершого елементу. I нерiдко для пере-
мiщення по елементах масиву використовуються окремi покажчики:
int a [ 5 ] = {1 , 2 , 3 , 4 , 5 } ;
int ∗ ptr = a ;
int a2 = ∗( p t r +2);
std : : cout << " v a l u e : " << a2 <<
std : : e n d l ; // v a l u e : 3
i n t ∗end = а [ 0 ] + n ∗ m − 1 ;
// покажчик на самий
// останнiй елемент 0 + 3 ∗ 4 − 1 = 11
f o r ( i n t ∗ p t r=a [ 0 ] , i =1; p t r <= end ; p t r ++, i ++)
{
s t d : : cout << ∗ p t r << "\ t " ;
// якщо залишок в i д цiлочисельного розподiлу рiвний 0
123
return 0;
}
i n t main ( )
{
i n t a [ 3 ] [ 4 ] = { {1 , 2 , 3 , 4} ,
{5 , 6 , 7 , 8} , {9 , 10 , 11 , 1 2 } } ;
i n t n = s i z e o f ( a )/ s i z e o f ( a [ 0 ] ) ; // число рядкiв
i n t m = s i z e o f ( a [ 0 ] ) / s i z e o f ( a [ 0 ] [ 0 ] ) ; // число с т о в б ц i в
i n t ∗end = a [ 0 ] + n ∗ m − 1 ;
// покажчик на самий останнiй елемент
// 0 + 3 ∗ 4 − 1 = 11
f o r ( i n t ∗ p t r=a [ 0 ] , i =0; i <m∗n ; )
{
s t d : : cout << ∗ p t r++ << "\ t " ;
// якщо залишок в i д цiлочисельного розподiлу рiвний 0
// переходимо на новий рядок
i f (++ i%m == 0)
{
s t d : : cout << s t d : : e n d l ;
}
}
1 2 3 4
5 6 7 8
9 10 11 12
i n t main ( )
{
char l e t t e r s [ ] = " h e l l o " ;
char ∗p = l e t t e r s ;
s t d : : cout << p << s t d : : e n d l ; // h e l l o
return 0;
}
void pri nt ( i n t [ ] ) ;
i n t main ( )
125
{
i n t nums [ ] = {1 , 2 , 3 , 4 , 5 } ;
p r i n t ( nums ) ;
return 0;
}
v o i d p r i n t ( i n t numbers [ ] )
{
s t d : : cout << " F i r s t number :
" << numbers [ 0 ] << s t d : : e n d l ;
}
void pri nt ( i n t ∗ ) ;
i n t main ( )
{
i n t nums [ ] = {1 , 2 , 3 , 4 , 5 } ;
p r i n t ( nums ) ;
return 0;
}
v o i d p r i n t ( i n t ∗numbers )
{
s t d : : cout << " F i r s t number :
" << ∗numbers << s t d : : e n d l ;
}
Обмеження
i n t s i z e = s i z e o f ( numbers ) / s i z e o f ( numbers [ 0 ] ) ;
s t d : : cout << s i z e << s t d : : e n d l ;
}
v o i d p r i n t ( char [ ] ) ;
i n t main ( )
{
char c h a r s [ ] = " H e l l o " ;
print ( chars ) ;
return 0;
}
v o i d p r i n t ( char c h a r s [ ] )
{
f o r ( i n t i = 0 ; c h a r s [ i ] != ’ \ 0 ’ ; i ++)
{
s t d : : cout << c h a r s [ i ] << "\ t " ;
}
}
#i n c l u d e <i o s t r e a m >
void pri nt ( i n t [ ] , i n t ) ;
i n t main ( )
{
i n t nums [ ] = {1 , 2 , 3 , 4 , 5 } ;
i n t n = s i z e o f ( nums )/ s i z e o f ( nums [ 0 ] ) ;
p r i n t ( nums , n ) ;
return 0;
}
v o i d p r i n t ( i n t numbers [ ] , i n t n )
{
f o r ( i n t i =0; i < n ; i ++)
{
s t d : : cout << numbers [ i ] << "\ t " ;
}
}
void pri nt ( i n t ∗ , i n t ∗ ) ;
i n t main ( )
{
i n t nums [ ] = { 1 , 2 , 3 , 4 , 5 } ;
i n t ∗ b e g i n = s t d : : b e g i n ( nums ) ;
i n t ∗end = s t d : : end ( nums ) ;
128
p r i n t ( begin , end ) ;
return 0;
}
v o i d p r i n t ( i n t ∗ begin , i n t ∗end )
{
f o r ( i n t ∗ p t r = b e g i n ; p t r != end ; p t r++)
{
s t d : : cout << ∗ p t r << "\ t " ;
}
}
Константнi масиви
i n t main ( )
{
i n t nums1 [ ] = { 1 , 2 , 3 , 4 , 5 } ;
i n t ∗ b e g i n = s t d : : b e g i n ( nums1 ) ;
i n t ∗end = s t d : : end ( nums1 ) ;
p r i n t ( begin , end ) ;
s t d : : cout << s t d : : e n d l ;
i n t nums2 [ ] = { 1 , 2 , 3 , 4 , 5 } ;
b e g i n = s t d : : b e g i n ( nums2 ) ;
end = s t d : : end ( nums2 ) ;
t w i c e ( begin , end ) ;
f o r ( i n t ∗ p t r = b e g i n ; p t r != end ; p t r++)
{
s t d : : cout << ∗ p t r << "\ t " ;
}
s t d : : cout << s t d : : e n d l ;
129
return 0;
}
v o i d p r i n t ( c o n s t i n t ∗ begin , c o n s t i n t ∗end )
{
f o r ( c o n s t i n t ∗ p t r = b e g i n ; p t r != end ; p t r++)
{
s t d : : cout << ∗ p t r << "\ t " ;
}
}
v o i d t w i c e ( i n t ∗ begin , i n t ∗end )
{
f o r ( i n t ∗ p t r = b e g i n ; p t r != end ; p t r++)
{
∗ ptr = ∗ ptr ∗ 2;
}
}
void pri nt ( i n t ( ∗ ) [ 3 ] , i n t ) ;
i n t main ( )
{
i n t t a b l e [ 3 ] [ 3 ] = {{1 , 2 , 3} , {4 , 5 , 6} , {7 , 8 , 9 } } ;
// к i л ь к i с т ь рядкiв або п i д м а с и в i в
i n t rowsCount = s i z e o f ( t a b l e ) / s i z e o f ( t a b l e [ 0 ] ) ;
p r i n t ( t a b l e , rowsCount ) ;
return 0;
}
v o i d p r i n t ( i n t (∗ numbers ) [ 3 ] , i n t rowsCount )
{
// к i л ь к i с т ь с т о в п ц i в або елементiв в кожному п i д м а с и в i
i n t columnsCount = s i z e o f (∗ numbers )/ s i z e o f (∗ numbers [ 0 ] ) ;
f o r ( i n t i =0; i < rowsCount ; i ++)
{
f o r ( i n t j = 0 ; j < columnsCount ; j ++)
{
s t d : : cout << numbers [ i ] [ j ] << "\ t " ;
}
s t d : : cout << s t d : : e n d l ;
}
}
Видiлення пам’ятi
Оператор new створює новий об’єкт типу int в динамiчнiй пам’ятi i повертає
покажчик на нього. Значення такого об’єкту невизначено.
Також можна iнiцiалiзувати об’єкт при створеннi:
i n t ∗p1 = new i n t ( ) ; // значення по замовчуваннi − 0
s t d : : cout << "p1 : " << ∗p1 << s t d : : e n d l ; // 0
i n t ∗p2 = new i n t ( 1 2 ) ;
s t d : : cout << "p2 : " << ∗p2 << s t d : : e n d l ; // 12
Звiльнення пам’ятi
{
i n t ∗ p t r = new i n t ( v a l u e ) ;
return ptr ;
}
void usePtr ( )
{
i n t ∗p1 = c r e a t e P t r ( 1 0 ) ;
s t d : : cout << ∗p1 << s t d : : e n d l ; // 10
d e l e t e p1 ;
}
i n t main ( )
{
usePtr ( ) ;
return 0;
}
// помилковi с ц е н а р i ї
s t d : : cout << ∗p1 << s t d : : e n d l ;
d e l e t e p1 ;
i n t main ( )
{
i n t ∗p1 = new i n t ( 1 2 ) ;
i n t ∗p2 = p1 ;
d e l e t e p1 ;
// адреса в p1 i p2 недопустимi
p1 = new i n t ( 1 1 ) ;
// p1 вказує на новий об ’ єкт
s t d : : cout << ∗p1 << s t d : : e n d l ; // 11
d e l e t e p1 ;
return 0;
}
Тут пiсля видалення об’єкту, на який указує p1, цьому покажчику передає-
ться адреса iншого об’єкту в динамiчнiй пам’ятi. Вiдповiдно ми також може-
мо використовувати покажчик p1. В той же час адреса в покажчику p2 як i
ранiше буде недiйсною.
масив).
чи то
f l o a t ∗a=( f l o a t ∗) с a l l o c ( 3 ∗ 5 , s i z e o f ( f l o a t ) ) ;
чи то
free (a );
Цей код створює двi рiзнi функцiї. Жодна з них не є видима поза файлом, у
якому її визначено.
На мiсцi HEADCOM може бути який завгодно iдентифiкатор. Цей вираз го-
ворить про те, що якщо HEADCOM ще не було визначено, то весь текст
звiдси i до директиви #endif просто вставлятиметься до файла реалiзацiї.
В iншому разi (якщо HEADCOM вже було визначено ранiш, в чому можна
впевнитися за допомогою директиви #define HEADCOM) наступний за #if
текст не буде долучено до початкового коду. Оскiльки змiнну HEADCOM не
було визначено до того як ця директива зустрiлася вперше, але одразу ж пi-
сля #if!defined() вона стала визначеною, увесь текст, розмiщений помiж #if
i #endif, буде долучено один раз, але це буде перший i останнiй раз. Напри-
клад:
#i f ! d e f i n e d (HEADCOM) // Якщо змiнну HEADCOM ще не визначено ,
#d e f i n e HEADCOM // визначити ї ї ,
i n t X; // визначити змiнну Х,
i n t f u n c ( i n t a , i n t b ) // визначити функцiю f u n c ( ) .
{ r e t u r n a+b ; }
#e n d i f // Директива , яка закриває умову .
Для написання коду створимо файл TstLib.h зробимо там потрiбнi оголо-
шення й заголовки функцiй. Використаємо директиву #define, щоб задати
константi k значення 8.
#i f n d e f TstLibH
#d e f i n e TstLibH
// Альтернативний варiант задання константи : #d e f i n e k 8
c o n s t i n t k=8;
// Оголошення типiв matrix ( ’ ’ матриця ’ ’ ) i v e c t o r ( ’ ’ вектор ’ ’ )
t y p e d e f double matrix [ k ] [ k ] , v e c t o r [ k ] ;
// Оголошення прототипiв функцiй
v o i d elem_matrix ( matrix c ) ;
v o i d elem_Vect ( matrix c , v e c t o r v ) ;
double G( matrix c ) ;
#e n d i f
145
Запис в потiк
#include <iostream>
int main()
{
std::cout << "Hello" << std::endl;
return 0;
}
Читання даних
#include <iostream>
int main()
{
int age;
double weight;
std::cout << "Input age: ";
std::cin >> age;
std::cout << "Input weight: ";
std::cin >> weight;
std::cout << "Your age: "
<< age << "\t your weight: " << weight << std::endl;
return 0;
}
Проте такий спосiб не дуже пiдходить для читання рядкiв з консолi особливо
коли прочитуваний рядок мiстить пробiльнi символи. В цьому випадку краще
використовувати вбудовану функцiю getline(), яка як параметр приймає потiк
istream i змiнну типу string, в яку треба рахувати данi:
#include <iostream>
#include <string>
int main()
{
std::string name;
std::cout << "Input name: ";
getline(std::cin, name);
//std::cin >> name;
std::cout << "Your name: " << name <<std::endl;
return 0;
}
Консольне виведення даної програми:
150
Виведення помилок
#include <iostream>
int main()
{
std::cerr << "Error occured" << std::endl;
return 0;
}
#include <iostream>
int main()
{
int age;
double weight;
std::wcout << "Input age: ";
std::wcin >> age;
std::wcout << "Input weight: ";
std::wcin >> weight;
if (age <= 0 || weight <= 0)
std::wcerr << "Invalid data" << std::endl;
else
std::wcout << "Your age:
" << age << "\t your weight: " << weight << std::endl;
return 0;
}
151
Для роботи з даними типу wchar_t для цих потокiв визначенi двiйники:
• wifstream
• wofstream
• wfstream
Вiдкриття файлу
• open(шлях)
• open(шлях, режим)
std::ofstream out2;
out2.open("D:\\hello2.txt", std::ios::app);
// вiдкривається файл для дозапису
std::ofstream out3;
out2.open("D:\\hello3.txt", std::ios::out | std::ios::trunc);
// установка дккiлькох режимiв
std::fstream fs;
// потiк для читання-запису
fs.open("D:\\hello5.txt");
// вiдкриваємо файл для читання-запису
fstream(шлях)
fstream(шлях, режим)
std::ofstream out("D:\\hello.txt");
std::ifstream in("D:\\hello.txt");
std::fstream fs("D:\\hello.txt", std::ios::app);
Закриття файлу
#include <iostream>
#include <fstream>
int main()
{
std::ofstream out; // потiк для запису
out.open("D:\\hello.txt"); // вiдкриваємо файл для запису
out.close(); // закриваємо файл
return 0;
}
Запис у файл
#include <iostream>
#include <fstream>
int main()
{
std::ofstream out; // потiк для запису
out.open("D:\\hello.txt"); // вiдкриваємо файл для запису
if (out.is_open())
{
out << "Hello World!" << std::endl;
}
Даний спосiб перезаписує файл наново. Якщо треба дозаписати текст в кiнець
файлу, то для вiдкриття файлу потрiбно використовувати режим ios::app:
Читання з файлу
Якщо треба рахувати весь рядок цiлком або навiть всi рядки з файлу, то
краще використовувати вбудовану функцiю getline(), яка приймає потiк для
читання i змiнну, в яку треба рахувати текст:
Також для читання даних з файлу для об’єктiв ifstream i fstream може засто-
совуватися оператор » (також як i при читаннi з консолi):
120 57.7
1030 57.4
980 58.5
560 57.2
Оператор «
#include <iostream>
#include <string>
struct Person
{
std::string name;
int age;
};
std::ostream& operator << (std::ostream &os, const Person &p)
{
return os << p.name << " " << p.age;
}
int main()
{
Person tom;
tom.name = "Tom";
tom.age = 31;
std::cout << tom << std::endl;
return 0;
}
Том 31
157
Оператор »
#include <iostream>
#include <string>
struct Person
{
std::string name;
int age;
};
std::istream& operator >> (std::istream& in, Person& p)
{
in >> p.name >> p.age;
return in;
}
int main()
{
Person bob;
std::cout << "Input name and age: ";
std::cin >> bob;
std::cout << "Name:
" << bob.name << "\t Age: " << bob.age << std::endl;
return 0;
}
Проте що якщо ми введемо для вiку замiсть числа рядок? В цьому випадку
змiнна age набуде невизначене значення. Iснують рiзнi варiанти, як обробляти
158
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
class Person
{
public:
std::string name;
int age;
Person(std::string n, int a): name(n),age(a) { }
Person(){ }
};
std::ostream& operator << (std::ostream &os, const Person &p)
{
return os << p.name << " " << p.age;
}
std::istream& operator >> (std::istream& in, Person& p)
{
in >> p.name >> p.age;
159
if (!in)
{
p = Person();
}
return in;
}
int main()
{
// початковi данi - вектор об’єктiв Person
std::vector<Person> people =
{
Person("Tom", 23),
Person("Bob", 25),
Person("Alice", 22),
Person("Kate", 31)
};
// запис даних у файл
std::ofstream out("D:\\users.txt");
if (out.is_open())
{
for (int i = 0; i < people.size(); i++)
{
out << people[i] << std::endl;
}
}
out.close();
// вектор для считування даних
std::vector<Person> users;
// зчитування ранiше записаних даних iз файлу
std::ifstream in("D:\\users.txt");
if (in.is_open())
{
Person p;
while (in >> p)
{
users.push_back(p);
}
}
in.close();
// виведення зчитаних даних на консоль
std::cout << "All users:" << std::endl;
for (int i = 0; i < users.size(); i++)
160
{
std::cout << users[i] << std::endl;
}
return 0;
}
All users:
Tom 23
Bob 25
Alice 22
Kate 31
• Якi базовi типи визначає заголовний файл iostream в для роботи з пото-
ками мови програмування С/С++?
• Яких значень може набувати об’єкт типу ostream?
• Для чого призначенi об’єкти cout, cin, сеrr в мовi програмування
С/С++?
• Який оператор використовується для запису даних в потiк ostream?
• Який оператор використовується для читання даних з потоку та якi його
основнi властивостi?
• В якмх випадках доцiльно використовувати вбудовану функцiю getli-
ne()?
• Який оператор використовується для виведення повiдомлення про по-
милку на консоль?
• Який заголовний файл використовується для роботи з файлами в стан-
дартнiй бiблiотецi С/С++?
• Якi базовi типи для читання i запису файлiв визначаються в стандартнiй
бiблiотецi С/С++?
161
Рекомедована лiтература
Обов’язкова лiтература
Додаткова лiтература