
- •Лекція 1
- •Зауваження до програми
- •Правила ініціалізації масивів
- •Лекція 2
- •Конкатенація рядкових літералів
- •Використання рядків у масивах
- •Зауваження до програми
- •Ризики, пов'язані з введенням рядків
- •Читання введення по рядках
- •Введення, орієнтоване на рядки за допомогою getline()
- •Введення, орієнтоване на рядки за допомогою get()
- •Змішування рядкового та числового вводу
- •Клас string
- •Лекція 3
- •Використання структур в програмах
- •Зауваження до програми
- •Чи може структура містити член типу string?
- •Інші властивості структур
- •Масиви структур
- •Лекція 4
- •Перерахування
- •Встановлення значень нумераторам
- •Діапазони значень нумераторів
- •Лекція 5
- •Оголошення та ініціалізація вказівників
- •Небезпека пов’язана з вказівниками
Лекція 2
Рядки
Рядок - це серія символів, збережена в розташованих послідовно байтах пам'яті. У C++ доступні два способи роботи з рядками. Перший, успадкований від С і часто званий рядками в стилі С. Альтернативний спосіб, заснований на бібліотечному класі string.
Ідея серії символів, що зберігаються в послідовних байтах, припускає зберігання рядка в масиві char, де кожен елемент міститься в окремому елементі масиву. Рядки надають зручний спосіб зберігання текстової інформації, такої як повідомлення для користувача або його відповіді. Рядки в стилі С володіють спеціальною характеристикою: останнім у кожній такій рядку є нульовий символ. Цей символ, записується як «\0», є символом з ASCII-кодом 0, який служить міткою кінця рядка. Наприклад, розглянемо два наступних оголошення:
Обидві ці змінні є масивами char, але тільки другий з них є рядком. Нульовий символ грає фундаментальну роль в рядках стилю С. Наприклад, в C++ є безліч функцій для обробки рядків, включаючи ті, що використовуються cout. Всі вони обробляють рядки символ за символом доти, поки не зустрінеться нульовий символ. Якщо ви просите об'єкт cout відобразити такий рядок, як cat з попереднього прикладу, він виводить перших сім символів, виявляє нульовий символ і на цьому зупиняється. Однак якщо ви раптом вирішите вивести в cout масив dog з попереднього прикладу, який не є рядком, то cout надрукує вісім символів з цього масиву і продовжуватиме рухатися по пам'яті, байт за байтом, інтерпретуючи кожен з них як символ, що підлягає висновку, поки не зустріне нульовий символ. Оскільки нульові символи, які, по суті, являють собою байти, що містять нулі, зустрічаються в пам'яті досить часто, помилка зазвичай виявляється швидко, але в будь-якому випадку ви не повинні трактувати нерядкові символьні масиви як рядки.
Приклад ініціалізації масиву cat виглядає досить громіздким і виснажливим - безліч лапок і необхідність пам'ятати про нульовий символі. Існує більш простий спосіб ініціалізації масиву за допомогою рядка. Для цього просто використовуйте рядок в подвійних лапках, який називається «рядковою константою» або «рядковим літералом»:
Рядки в подвійних лапках завжди неявно включають обмежуючий нульовий символ, тому вказувати його не потрібно (Мал. 2.). До того ж різноманітні засоби введення C++, призначені для читання рядка з клавіатурного введення в масив char, автоматично додають завершальний нульовий символ. (Якщо при компіляції програми з лістингу 1 виникне необхідність у використанні ключового слова static для ініціалізації масиву, це також знадобиться зробити з показаними вище масивами char.)
Мал. 2. Ініціалізація масива рядком
Звичайно, ви повинні забезпечити достатній розмір масиву, щоб в нього помістилися всі символи рядка, включаючи нульовий. Ініціалізація символьного масиву рядковою константою - це один з тих випадків, коли безпечніше доручити компілятору підрахунок кількості елементів в масиві. Якщо зробити масив більше рядка, ніяких проблем не виникне - тільки непродуктивна витрата простору. Причина в тому, що функції, які працюють з рядками, керуються позицією нульового символу, а не розміром масиву. У C++ не накладається ніяких обмежень на довжину рядка.
Зверніть увагу, що рядкова константа (в подвійних лапках) не взаємозамінна з символьної константою (в одинарних лапках). Символьна константа, така як 'S' - скорочене позначення для коду символу. В системі ASCII константа 'S' - це просто інший спосіб запису коду 83. Тому наступний оператор привласнює значення 83 змінній shirt_size:
З іншого боку, "S" не є символьної константою; це рядок, що складається з двох символів - S і \0. Гірше того, "S" в дійсності представляє адреса пам'яті, по якому розміщується рядок. Це означає, що оператор
означає спробу привласнити адресу пам'яті змінній shirt_size:
Оскільки адреса пам'яті - це окремий тип в C++, компілятор не пропустить подібну нісенітницю.