← Повернутися до лекцій

Лекція 9: Символьні масиви (C-style strings) та функції роботи з ними

У C++ є два способи працювати з текстом:

  1. std::string — сучасний, зручний об'єкт (ми вже трохи торкалися його раніше).
  2. C-style strings (С-рядки) — прості масиви символів (char). Саме так працювали з текстом у старій мові C.

Сьогодні ми заглибимося в "підкапотну" частину — масиви char.

1. Що таке рядок у пам'яті?

Для комп'ютера текст — це просто послідовність символів, що лежать один за одним у пам'яті.

Питання: як комп'ютер знає, де закінчується слово "Hello" і починається інший "сміття" з пам'яті?

Відповідь: Null-terminator (\0). Кожен C-style рядок обов'язково закінчується спеціальним символом, код якого дорівнює 0. У коді це записується як '\0'.

Приклад: Слово "Hi" у пам'яті займає 3 байти, а не 2: ['H'] ['i'] ['\0'].

2. Оголошення та ініціалізація

Оскільки це масив, синтаксис вам знайомий. Але важливо пам'ятати про місце для \0!

char word[6] = "Hello"; // 5 літер + 1 нуль-термінатор = 6 комірок

Якщо написати char word[5] = "Hello";, це буде помилка — не вистачить місця для термінатора!

Краще дозволити компілятору самому порахувати розмір:

char greeting[] = "Hello World"; // Розмір автоматично буде 12

3. Проблема введення (cin)

Недолік звичайного cin: він читає текст лише до першого пробілу.

#include <iostream>
using namespace std;

int main() {
    char name[50];
    cout << "Введіть ім'я та прізвище: ";
    cin >> name; // Якщо ввести "Taras Shevchenko"
    cout << name; // Виведе тільки "Taras"
    
    return 0;
}

Рішення: Функція cin.getline(). Вона приймає два параметри: куди записати (масив символів) та максимальний розмір.

#include <iostream>
using namespace std;

int main() {
    char fullName[100];
    cout << "Введіть повне ім'я: ";
    cin.getline(fullName, 100); // Прочитає весь рядок із пробілами
    cout << "Привіт, " << fullName << endl;
    
    return 0;
}

4. Бібліотека <cstring> (або <string.h>)

Масиви char — це не об'єкти, тому прямі операції неможливі:

  • str1 = str2 — не працює!
  • str1 == str2 — не працює!
  • str3 = str1 + str2 — не працює!

Для цих операцій існують спеціальні функції. Підключіть бібліотеку: #include <cstring>

strlen(str) — Довжина рядка

Повертає довжину рядка (кількість символів без \0).

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char msg[] = "Hi";
    cout << strlen(msg); // Виведе 2
    
    return 0;
}

strcpy(dest, source) — Копіювання рядка

Копіює вміст одного рядка в інший.

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char original[] = "Apple";
    char copy[20];
    strcpy(copy, original); // copy тепер "Apple"
    // Увага! у 'copy' має бути достатньо місця!
    
    return 0;
}

strcat(dest, source) — Конкатенація (склеювання)

Додає (приклеює) другий рядок в кінець першого.

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char text[50] = "Hello, ";
    char name[] = "User";
    strcat(text, name); // text стає "Hello, User"
    
    return 0;
}

strcmp(str1, str2) — Порівняння рядків

Порівнює два рядки по коду символів (алфавітний порядок).

  • Повертає 0, якщо рядки однакові.
  • Повертає < 0, якщо перший рядок йде раніше в алфавіті.
  • Повертає > 0, якщо перший рядок йде пізніше.
#include <iostream>
#include <cstring>
using namespace std;

int main() {
    char password[20];
    cin >> password;
    
    if (strcmp(password, "secret123") == 0) {
        cout << "Пароль вірний!";
    }
    
    return 0;
}

5. Приклад використання функцій

#include <iostream>
#include <cstring> // Обов'язково для strlen, strcpy, strcat, strcmp
using namespace std;

int main() {
    char str1[50] = "Super";
    char str2[] = "Mario";

    // 1. Об'єднання
    strcat(str1, " "); // Додали пробіл: "Super "
    strcat(str1, str2); // Додали Mario: "Super Mario"

    cout << "Результат: " << str1 << endl;
    cout << "Довжина: " << strlen(str1) << endl; // 11 символів

    // 2. Порівняння
    char login[20];
    cout << "Введіть логін: ";
    cin >> login;

    if (strcmp(login, "admin") == 0) {
        cout << "Вхід дозволено!" << endl;
    } else {
        cout << "Звичайний користувач." << endl;
    }

    return 0;
}

Практичні завдання до Лекції 9

Виконайте ці завдання в своєму середовищі розробки.

Завдання 1: Власний strlen

Напишіть програму, яка просить користувача ввести слово. Не використовуючи функцію strlen, порахуйте кількість символів у цьому слові.

Підказка: Використовуйте цикл while або for. Перебирайте символи str[i], доки не зустрінете нуль-термінатор '\0'.

Завдання 2: Детектор слів

Користувач вводить два слова. Програма має визначити:

  1. Яке слово довше.
  2. Чи однакові ці слова (ідентичні). Використовуйте функції з бібліотеки <cstring>.

Завдання 3: Заміна символів (Цензура)

Користувач вводить речення (використовуйте cin.getline). Програма має пройтися по всьому масиву символів. Якщо вона знаходить літеру 'а' (англійську), вона замінює її на '@'. Якщо знаходить 'о', замінює на '0' (нуль). Виведіть оброблене речення.

Приклад: "Hello world and all" → "Hell0 w0rld @nd @ll"