Урок №82. Рядки C-style

  Юрій  | 

  Оновл. 7 Лип 2020  | 

 513

В уроці №60 ми визначили термін «рядок» як набір послідовних символів (наприклад, Hello, world!). Рядки — це основний спосіб роботи з текстом в C++, а std::string спрощує цю взаємодію.

Сучасний C++ підтримує два різних типи рядків:

   std::string (як частина Стандартної бібліотеки мови С++);

   рядки C-style (успадковані від мови Cі).

std::string реалізований за допомогою рядків C-style.

Рядки C-style

Рядок C-style — це простий масив символів, який використовує нуль-термінатор. Нуль-термінатор — це спеціальний символ (ASCII-код якого дорівнює 0), який використовується для позначення кінця рядку.

Для визначення рядку C-style необхідно просто оголосити масив типу char і ініціалізувати його літералом (наприклад, string):

Хоча string має лише 6 букв, мова C++ автоматично додає нуль-термінатор в кінець рядку (нам не потрібно додавати його вручну). Відповідно, довжина масиву mystring дорівнює 7!

Як приклад розглянемо наступну програму, яка виводить довжину рядка, а потім ASCII-коди всіх символів літералу string:

Результат виконання програми:

string has 7 characters.
115 116 114 105 110 103 0

Нуль в кінці є ASCII-кодом нуль-термінатора, який був доданий в кінець рядка.

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

Зверніть увагу, що рядки C-style слідують всім тим же правилам, що і масиви. Це означає, що ви можете ініціалізувати рядок при створенні, але після цього не зможете присвоювати йому значення за допомогою оператора присвоювання:

Це те ж саме, якби ми зробили наступне:

Оскільки рядки C-style є масивами, то ви можете використовувати оператор [] для зміни окремих символів в рядку:

Результат виконання програми:

spring

При виведенні рядка C-style, std::cout виводить символи до тих пір, поки не зустріне нуль-термінатор. Якби ви випадково перезаписали нуль-термінатор в кінці рядка (наприклад, присвоївши що-небудь для mystring[6]), то ви б не тільки отримали всі символи рядка, але std::cout також вивів би все, що знаходиться в сусідніх комірках пам’яті до тих пір, поки йому не попався би 0!

Зверніть увагу, що це нормально, якщо довжина масиву більше рядка, якого він зберігає:

В цьому випадку рядок Max виведеться на екран, а std::cout зупиниться на нуль-термінаторі. Решта символів в масиві будуть проігноровані.

Рядки C-style і std::cin

Є багато випадків, коли ми не знаємо заздалегідь, наскільки довгим буде наш рядок. Наприклад, розглянемо проблему написання програми, де ми просимо користувача ввести своє ім’я. Наскільки довгим воно буде? Це невідомо доти, доки користувач його не введе!

У такому випадку ми можемо оголосити масив розміром більше, ніж нам потрібно:

У вищенаведеній програмі ми оголосили масив з 255 символів, припускаючи, що користувач не введе ім’я більше 255 символів. Хоча це і поширена практика, але вона не дуже ефективна, так як користувачу нічого не заважає ввести ім’я більше 255 символів (випадково або навмисно).

Набагато краще зробити наступне:

Виклик cin.getline() буде приймати до 254 символів в масив name (залишаючи місце для нуль-термінатора!). Будь-які зайві символи будуть проігноровані. Таким чином, ми можемо гарантувати, що масив не буде переповнений!

Керування рядками C-style

C++ надає безліч функцій для керування рядками C-style, які підключаються за допомогою заголовкового файлу cstring. Ось декілька найбільш корисних функцій:

Функція strcpy_s() — копіює вміст одного рядка в інший. Найчастіше це використовується для присвоювання значень рядку:

Тим не менше, використання strcpy_s() може легко викликати переповнення масиву, якщо не бути обережним! У наступній програмі, довжина масиву dest менше довжини рядка, який ми копіюємо, тому в результаті ми отримаємо переповнення масиву:

Функція strlen() — повертає довжину рядка C-style (не враховуючи нуль-термінатор):

Результат виконання програми:

My name is Max
Max has 3 letters.
Max has 15 characters in the array.

Зверніть увагу на різницю між strlen() і sizeof. Функція strlen() виводить кількість символів ДО нуль-термінатора, тоді як оператор sizeof повертає розмір цілого масиву, незалежно від того, що в ньому знаходиться.

Ось ще кілька корисних функцій керування рядками C-style:

   функція strcat() – додає один рядок до іншого (небезпечно);

   функція strncat() – додає один рядок до іншого (з перевіркою розміру місця призначення);

   функція strcmp() – порівнює два рядки (повертає 0, якщо вони рівні);

   функція strncmp() – порівнює два рядки до певної кількості символів (повертає 0, якщо вони рівні).

Наприклад:

Чи варто використовувати рядки C-style?

Знати про рядки C-style варто, так як вони використовуються не так вже й рідко, але використовувати їх без вагомої на те причини — не рекомендується. Замість рядків C-style використовуйте std::string (підключаючи заголовок string), так як він простіший, безпечніший і гнучкіший.

Правило: Використовуйте std::string замість рядків C-style.

Оцінити статтю:

1 Зірка2 Зірки3 Зірки4 Зірки5 Зірок (4 оцінок, середня: 5,00 з 5)
Loading...

Залишити відповідь

Ваш E-mail не буде опублікований. Обов'язкові поля відмічені *