C++

Вступ у програмування та алгоритми

Перше знайомство зі світом програмування: від історичних витоків до побудови алгоритмів. Дізнайтеся, що таке алгоритм (algorithm), які його властивості, типи та як описувати їх за допомогою блок-схем (flowcharts).

Навіщо вчити програмування?

Уявіть: ви відкриваєте сайт з вакансіями і бачите, що програмісти — одні з найбільш запитуваних і високооплачуваних спеціалістів. Але чому? Відповідь проста — попит на кваліфікованих програмістів значно перевищує пропозицію. Програмування — це не просто «знання слів якоюсь мовою». Це спосіб мислення, вміння розкладати складні задачі на прості кроки та давати комп'ютеру чіткі інструкції.

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

Що ви отримаєте після вивчення цього розділу:
  • Розуміння історії розвитку програмування та мов
  • Чітке визначення алгоритму та його властивостей
  • Вміння розрізняти типи алгоритмів
  • Навички побудови блок-схем

Коротка подорож в історію

Перш ніж писати код, варто знати, як ми дійшли до сучасних мов програмування. Ця подорож — від механічних пристроїв до C++ — допоможе зрозуміти, чому мови програмування влаштовані саме так.

Loading diagram...
timeline
    title Еволюція програмування
    section Механічна ера
        1804 : Жаккар — перфокарти для ткацького верстата
        1890 : Голлеріт — табулятор (майбутня IBM)
    section Теоретичні основи
        1936 : Тюрінг — «Машина Тюрінга»
        1941 : Цузе — комп'ютер Z3 (двійкова система)
    section Перші комп'ютери
        1945 : ENIAC — перший електронний комп'ютер
        1948 : «Марк-1» — перша програма в пам'яті
        1949 : EDSAC — поява «асемблера»
    section Мови високого рівня
        1957 : Фортран — перша «справжня» мова
        1963 : Бейсік
        1970 : Паскаль (Ніклаус Вірт)
        1972 : Мова Сі (Денніс Рітчі)
    section Сучасна ера
        1983 : C++ (Б'ярн Страуструп)
        1995 : Java (Sun Microsystems)
        2001 : C# (Microsoft)

Ключові віхи

🏭 1804 — Перфокарти

Жозеф Марі Жаккар створив «програмно-керований» ткацький верстат. Перфокарти визначали візерунок тканини — це був перший приклад програмного управління пристроєм.

🧮 1936 — Машина Тюрінга

Алан Тюрінг описав гіпотетичний пристрій, здатний вирішити будь-яку математичну задачу. Це — теоретичний прообраз сучасного комп'ютера.

⚡ 1945 — ENIAC

Перший повністю електронний комп'ютер. Для програмування потрібно було вручну встановлювати тисячі перемикачів та штекерів.

🔤 1949 — Асемблер

Моріс Вілкс запропонував мнемонічні позначення замість числових кодів. Слово «assembler» (збирач) з'явилося саме тоді.

🚀 1972 — Мова Сі

Денніс Рітчі створив мову Сі у Bell Labs. Саме ця мова стала фундаментом для C++, Java та C#.

➕ 1983 — C++

Б'ярн Страуструп розширив мову Сі, додавши класи та об'єктно-орієнтоване програмування. Назва «C++» означає «Сі плюс один крок уперед».
Зверніть увагу на шлях розвитку: Сі → C++ → Java → C#. Кожна наступна мова будувалася на досвіді попередньої, вирішуючи її обмеження. Тому, вивчаючи C++, ви закладаєте фундамент для розуміння багатьох сучасних мов.

Перше знайомство з алгоритмами

Що таке алгоритм?

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

Розглянемо простий приклад — приготування яєчні:

При виконанні цієї послідовності ми отримаємо гарячий сніданок. Але що станеться, якщо поміняти місцями кроки 2 і 3 — налити масло, а потім поставити пательню? Масло опиниться на плиті, а не на пательні!

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

Алгоритм (algorithm) — це чітка і строга послідовність дій, яка приводить до потрібного результату.

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

Властивості алгоритму

Щоб алгоритм був надійним і працював коректно, він повинен відповідати шести ключовим властивостям:

🎯 Результативність

Алгоритм завжди має приводити до результату. Якщо ви виконали всі кроки, але нічого не отримали — це поганий алгоритм.

✅ Коректність

Результат має бути правильним. Готовий сніданок, а не брудна плита. Якщо результат відрізняється від очікуваного — помилка в алгоритмі.

📏 Точність

Усі дії мають бути описані однозначно. «Смажити деякий час» — погано. «Смажити 5 хвилин» — добре. Двозначність неприпустима.

💡 Зрозумілість

Виконавець має розуміти всі інструкції. Рецепт іноземною мовою буде марним. У програмуванні ми «спілкуємося» з комп'ютером мовою C++.

🧩 Дискретність

Алгоритм складається з окремих кроків. Неможливо виконати все одночасно — спочатку одна дія, потім наступна.

♻️ Масовість

Алгоритм має підходити для цілого класу подібних задач. Рецепт яєчні працює з курячими, перепелиними чи страусиними яйцями — змінюється лише час приготування.
Loading diagram...
mindmap
  root((Алгоритм))
    Результативність
      Завжди є результат
    Коректність
      Правильний результат
    Точність
      Однозначні дії
    Зрозумілість
      Виконавець розуміє інструкції
    Дискретність
      Окремі послідовні кроки
    Масовість
      Підходить для класу задач
Порушення будь-якої з цих властивостей призводить до нестабільної системи. Програма, яка працює «через раз» або дає неправильні відповіді, зазвичай побудована на алгоритмі, де одна з властивостей була проігнорована.

Типи алгоритмів

Не всі задачі розв'язуються однаково. Залежно від структури дій, виділяють три основні типи алгоритмів:

1. Лінійний алгоритм

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

Аналогія: Рецепт з кулінарної книги — ви чітко знаєте, який продукт брати, у якій кількості і що з ним робити.

Loading diagram...
graph TD
    A([Початок]) --> B[Крок 1]
    B --> C[Крок 2]
    C --> D[Крок 3]
    D --> E([Кінець])

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#64748b,stroke:#334155,color:#ffffff
    style C fill:#64748b,stroke:#334155,color:#ffffff
    style D fill:#64748b,stroke:#334155,color:#ffffff
    style E fill:#3b82f6,stroke:#1d4ed8,color:#ffffff

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

RectangleArea.cpp
#include <iostream>

int main() {
    int length, width;
    std::cout << "Введіть довжину: ";
    std::cin >> length;
    std::cout << "Введіть ширину: ";
    std::cin >> width;

    int area = length * width;
    std::cout << "Площа прямокутника: " << area << std::endl;
    return 0;
}
Execution: RectangleArea
$ g++ RectangleArea.cpp -o area && ./area
Введіть довжину: 10
Введіть ширину: 5
Площа прямокутника: 50

2. Розгалужений алгоритм

Розгалужений алгоритм — виконується вибір одного з декількох можливих шляхів залежно від умови.

Аналогія: Ви лежите на дивані. Якщо дощ припинився — йдете гуляти, інакше — дивитесь телевізор. Залежно від погоди, ви можете піти лише одним шляхом.

Loading diagram...
graph TD
    A([Початок]) --> B{Умова?}
    B -- Так --> C[Дія 1]
    B -- Ні --> D[Дія 2]
    C --> E([Кінець])
    D --> E

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#f59e0b,stroke:#b45309,color:#ffffff
    style C fill:#64748b,stroke:#334155,color:#ffffff
    style D fill:#64748b,stroke:#334155,color:#ffffff
    style E fill:#3b82f6,stroke:#1d4ed8,color:#ffffff

Приклад: Світлофор — якщо зелений колір — продовжуємо рух, інакше — зупиняємо автомобіль.

TrafficLight.cpp
#include <iostream>
#include <string>

int main() {
    std::string color;
    std::cout << "Який колір світлофора? ";
    std::cin >> color;

    if (color == "green") {
        std::cout << "ПРОДОВЖУЙТЕ РУХ" << std::endl;
    } else {
        std::cout << "ЗУПИНІТЬСЯ!" << std::endl;
    }
    return 0;
}
Execution: TrafficLight
$ ./traffic_light
Який колір світлофора? red
ЗУПИНІТЬСЯ!

3. Циклічний алгоритм

Циклічний алгоритм — повтор одних і тих самих дій, поки виконується певна умова.

Аналогія: Садівник заповнює клумбу квітами. Для кожної квітки: викопати ямку → полити → посадити → засипати землею. І так доти, доки не засадить усю клумбу.

Loading diagram...
graph TD
    A([Початок]) --> B{Умова циклу?}
    B -- Так --> C[Дія]
    C --> B
    B -- Ні --> D([Кінець])

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#f59e0b,stroke:#b45309,color:#ffffff
    style C fill:#64748b,stroke:#334155,color:#ffffff
    style D fill:#3b82f6,stroke:#1d4ed8,color:#ffffff

Приклад: Друкувати «Привіт» 10 разів — повторювати дію, поки лічильник не досягне 10.

HelloLoop.cpp
#include <iostream>

int main() {
    for (int i = 1; i <= 10; i++) {
        std::cout << i << ". Привіт, kostyl.dev!" << std::endl;
    }
    return 0;
}
Execution: HelloLoop
$ ./hello_loop
1. Привіт, kostyl.dev!
2. Привіт, kostyl.dev!
3. Привіт, kostyl.dev!
4. Привіт, kostyl.dev!
5. Привіт, kostyl.dev!
6. Привіт, kostyl.dev!
7. Привіт, kostyl.dev!
8. Привіт, kostyl.dev!
9. Привіт, kostyl.dev!
10. Привіт, kostyl.dev!

Що бачить комп'ютер?

Коли ми запускаємо програму, комп'ютер не просто "виконує кроки". Він оперує пам'яттю та регістрами процесора. Вже на старті навчання важливо розуміти, як ваші змінні виглядають "під капотом".

Зазирнути в пам'ять

Використовуйте MemoryView для візуалізації HEX-даних.

Стежити за станом

DebuggerView допоможе побачити значення змінних у реальному часі.

Стан програми (Debugger)

Уявіть, що ми зупинили виконання алгоритму обчислення площі прямокутника на середині. Ось як би виглядав стан наших змінних у дебагері:

Locals: RectangleArea
Filter
NameTypeValue
lengthint10
widthint5
areaint50
Running
Process: 12842

Сирі дані (Memory)

А ось так число 50 (яке у шістнадцятковій системі виглядає як 0x32) може виглядати безпосередньо в комірці оперативної пам'яті:

RAM Preview
Hex Dump / ASCII
0x00A1FBB0
00000032000000000000000000000000
Offset: 8 bytes
Big Endian
Розуміння того, як дані лежать у пам'яті, допоможе вам у майбутньому опанувати вказівники (pointers) — одну з найпотужніших та найскладніших тем у C++.

::

Графічний опис алгоритму: блок-схеми

Навіщо потрібні блок-схеми?

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

Блок-схема (flowchart) — графічний спосіб опису алгоритму, що складається з функціональних блоків, з'єднаних стрілками.

Елементи блок-схем

ЕлементФормаПризначенняВходи / Виходи
Початок / КінецьОвал (скруглений прямокутник)Позначає початок або завершення алгоритмуПочаток — тільки вихід; Кінець — тільки вхід
ДіяПрямокутникОбчислення, присвоєння, виконання команди1 вхід, 1 вихід
УмоваРомбПеревірка умови (розгалуження)1 вхід, 2 виходи (Так / Ні)
Ввід / ВивідПаралелограмВведення або виведення даних1 вхід, 1 вихід
ЦиклШестикутникПочаток або кінець циклу1 вхід, 1 вихід
Правила побудови блок-схем:
  • Схема будується зверху вниз
  • Блок «Початок» розміщується тільки один раз на початку
  • Блок «Кінець» розміщується тільки один раз у кінці
  • Виходи блоку «Умова» обов'язково підписуються: Так / Ні, + / - або true / false

Приклад: Розгадування ребуса

Побудуємо блок-схему для простого алгоритму — розгадування ребуса, де з малюнка м'яча потрібно отримати слово «хом'як»:

Loading diagram...
graph TD
    A([Початок]) --> B[/"Визначаємо слово на малюнку — М'ЯЧ"/]
    B --> C["Відкидаємо останню літеру — Ч"]
    C --> D["Додаємо літери «ХО» та «К»"]
    D --> E[/"Відповідь — ХОМ'ЯК"/]
    E --> F([Кінець])

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#64748b,stroke:#334155,color:#ffffff
    style C fill:#64748b,stroke:#334155,color:#ffffff
    style D fill:#64748b,stroke:#334155,color:#ffffff
    style E fill:#64748b,stroke:#334155,color:#ffffff
    style F fill:#3b82f6,stroke:#1d4ed8,color:#ffffff

Це приклад лінійного алгоритму — всі дії виконуються послідовно.

Приклад: Вовк, Коза і Капуста

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

Loading diagram...
graph TD
    A([Початок]) --> B["Перевезти козу"]
    B --> C["Повернутися за вовком"]
    C --> D["Перевезти вовка та забрати козу"]
    D --> E["Перевезти капусту"]
    E --> F["Повернутися за козою"]
    F --> G["Перевезти козу"]
    G --> H([Кінець])

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#64748b,stroke:#334155,color:#ffffff
    style C fill:#64748b,stroke:#334155,color:#ffffff
    style D fill:#f59e0b,stroke:#b45309,color:#ffffff
    style E fill:#64748b,stroke:#334155,color:#ffffff
    style F fill:#64748b,stroke:#334155,color:#ffffff
    style G fill:#64748b,stroke:#334155,color:#ffffff
    style H fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
Зверніть увагу на крок «Перевезти вовка та забрати козу» (виділений жовтим). Це ключовий хід — без нього вовк з'їв би козу на протилежному березі. При побудові алгоритму кожен крок потрібно аналізувати з точки зору його впливу на весь алгоритм.

Приклад: Світлофор (розгалужений алгоритм)

Автомобіль рухається дорогою. Водій бачить світлофор. Потрібно визначити дії водія залежно від кольору:

Loading diagram...
graph TD
    A([Початок]) --> B[/"Запитуємо колір світлофора"/]
    B --> C{Це зелений колір?}
    C -- Так --> D["Продовжуємо рух"]
    C -- Ні --> E["Зупиняємо автомобіль"]
    D --> F([Кінець])
    E --> F

    style A fill:#3b82f6,stroke:#1d4ed8,color:#ffffff
    style B fill:#64748b,stroke:#334155,color:#ffffff
    style C fill:#f59e0b,stroke:#b45309,color:#ffffff
    style D fill:#22c55e,stroke:#15803d,color:#ffffff
    style E fill:#ef4444,stroke:#dc2626,color:#ffffff
    style F fill:#3b82f6,stroke:#1d4ed8,color:#ffffff

У цьому прикладі:

  • Вхідні дані — колір світлофора
  • Вихідні дані — одна з двох дій (продовження руху або зупинка)
  • Блок «Умова» (ромб) має два виходи — і саме тут алгоритм розгалужується

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

Рівень 1 — Базовий

Рівень 2 — Логічний

Рівень 3 — Творчий

Підсумок

📌 Алгоритм

Чітка послідовність дій для досягнення результату. Має 6 обов'язкових властивостей: результативність, коректність, точність, зрозумілість, дискретність, масовість.

📌 Три типи

Лінійний — крок за кроком. Розгалужений — вибір шляху за умовою. Циклічний — повтор дій.

📌 Блок-схема

Графічний спосіб описати алгоритм. Овал — початок/кінець, прямокутник — дія, ромб — умова, паралелограм — ввід/вивід.