SlideShare a Scribd company logo
1 of 36
Тема 12.3
Рядки в мові
програмування С++.
Робота з рядками.
Рядок як масив
літер.
Поняття рядка в мові програмування
Один з різновидів одновимірних масивів — масив символів, або рядок, —
посідає особливе місце у багатьох мовах програмування. Це не випадково, адже
алгоритми перетворення рядків застосовуються для вирішення широкого
спектру задач. Рядки, як різновиди даних, призначені для введення, обробки і
виведення символьної інформації.
Рядок у мові програмування – це скінчена послідовність символів, які
сприймаються і обробляються як єдине ціле. Рядки можуть представлятися у
вигляді масиву символів, але масив символів - не завжди рядок! Кожен рядок
характеризується загальною довжиною, яка визначається при оголошенні
та поточною довжиною - кількістю символів у конкретний момент виконання
програми. Тобто, довжина рядка може змінюватися в процесі роботи програми,
але не може перевищувати загальної довжини, зазначеної при оголошенні типу.
Деякі мови програмування накладають обмеження на максимальну довжину
рядка,але в більшості мов, зокрема, у С++, подібні обмеження відсутні - довжина
рядка може обмежуватись лише кількістю пам'яті на комп'ютері.
Рядковий тип (тип рядка) – це тип даних, значеннями якого є довільна
послідовність символів алфавіту. Кожна змінна такого типу може бути
представлена фіксованою кількістю байтів або мати довільну довжину. Слід
зазначити, що деякі мови програмування мають вбудований тип даних для
зберігання рядків; у інших - рядок представляється як символьний масив, який
завершується певним символом.
Зокрема, у мові С не визначено вбудованого рядкового типу даних, але поняття
“рядка”, як єдиної лінгвістичної конструкції, існує. Рядком в С вважається
символьний масив, який завершується символом кінця рядка '0' (NULL-
символом). Такий підхід до реалізації рядків дає програмісту більше "важелів"
керування порівняно з тими мовами, у яких використовується окремий рядковий
тип даних.
В сучасних IDE, що підтримують мову С++, доступною для роботи є так
звана стандартна бібліотека шаблонів STL (Standard Template Library), яка
містить універсальні шаблонні класи і функції, які реалізують функціональність
багатьох структур даних. Зокрема, в ній є клас string, що слугує для організації
роботи з рядками. Сам STL-рядок розглядається як контейнер для зберігання
символів. Для використання класу string необхідно підключити заголовний файл
<string>.
При розміщенні у пам'яті рядок, як різновид масиву, займає зв’язну область і
зберігається як безперервна послідовність символів.
Часто при компіляції програми для даних рядкового типу резервується ділянка
пам'яті, розмір якої дещо більший за загальну довжину рядка (зазвичай, на 1
байт).
Додатковий байт використовується для зберігання допоміжних даних, зокрема,
значення поточної довжини рядка (у Pascal) або символа кінця рядка (у С/С++).
Опис рядків
Синтаксис опису змінної-рядка залежить від способу подання рядка,
характерного для тієї чи іншої мови програмування. Якщо мова програмування
має вбудований рядковий тип даних, то змінна-рядок оголошується з
використанням відповідного ідентифікатора типу.
У С/С++ змінна-рядок, як масив символів, має наступний синтаксис
оголошення:
char ім’я[загальна_довжина].
Оголошений масив символів повинен мати такий розмір, щоб мати змогу
зберігати найдовший рядок, що оброблятиметься, та символ кінця рядка '0'.
Як і у випадку масиву, ім’я рядка у С/С++ є покажчиком на нього (на його
перший символ). Отже, рядок можна оголосити і як покажчик на тип char:
сhar *ім’я.
Наприклад,
char str[26]; // змінна-рядок
char *st. // покажчик на рядок
При зазначенні довжини рядка слід враховувати завершальний нуль-символ.
Наприклад, у вищенаведеному рядку str можна зберігати не 26, а лише 25
символів.
Рядок, як масив символів, у С/С++ може як оголошуватися, так і визначатися.
Ініціалізація рядка здійснюється під час його визначення за
допомогою рядкових літералів або як перелік окремих символів.
Наприклад,
char str1[]="ПРИВІТ"; // довжина рядка визначається автоматично
char str2[4]={‘а',‘b’,‘с',’0’}; // '0' заноситься явно
char *st = "Приклад  довгого рядка";
char *st 1= "";
Рядок, визначений останнім (""), вважається порожнім або нульовим. Він
складається тільки з '0' (ознаки завершення рядка).
При визначенні рядків за допомогою літералів, програмісту не потрібно
вручну додавати в кінець нуль-символ - компілятор робить це автоматично.
Отже, рядок "ПРИВІТ" в пам'яті розміщується так:
Не слід плутати символьну константу з рядком, що містить один символ:
'Х' - це окремий символ (символьна константа), що займає 1 байт пам'яті;
"Х" - це рядок (рядкова константа), що складається з одного символу (букви
Х) та символу кінця рядка '0' і займає 2 байти пам'яті.
STL-рядки (у С++) створюються і визначаються наступним чином:
string s1, s2; // створення рядків s1 і s2
string str1(“Hello”); // створення і ініціалізація рядка str1
string str2=“greetings”; // ще одне створення і ініціалізація рядка str2
Окрім рядка-змінної у програмах можна використовувати рядкові (текстові)
константи, які не можуть змінювати своє значення в процесі роботи
програми. Описуються вони використання ключового слова const. У С/С++
рядкову константу можна описати як через через ім’я, так і через покажчик
на її перший символ. Оскільки ім’я рядка є покажчиком на його перший
елемент, то наступні визначення будуть еквівалентними:
const char *str1="Рядок 1";
const char str2[]="Рядок 2";
Рядкові константи можна визначити і за допомогою директиви
препроцесора #define, наприклад,
#define str "Приклад рядка" // ' 0' заноситься автоматично
Для використання цієї рядкової константи достатньо вказати її ім’я (str) у
відповідному місці програми.
Введення-виведення рядків
Для введення-виведення рядків у мовах програмування, зазвичай,
використовуються вбудовані підпрограми. У мові С++ для введення-виведення
рядків у консолі можуть використовуватися декілька альтернативних варіантів:
•функції форматованого введення-виведення (scanf, printf);
•спеціалізовані функції введення-виведення рядків (gets, puts).
Мова С++ розширює ці можливості шляхом використання потоків введення-
виведення cin і cout.
Для використання спеціальних функцій та функцій форматованого введення-
виведення рядків слід підключити заголовний файл <stdio.h>; для використання
потокового введення-виведення - заголовний файл <iostream>.
Поточна довжина рядка, що вводиться, визначається автоматично. Зокрема,
при введенні рядка з клавіатури його довжина визначатиметься як кількість
символів, введених до натискання клавіші Enter, і символа кінця рядка (‘0’),
який автоматично заноситься після натиснення клавіші Enter.
Наприклад,
char s[14], st[19], str[16];
cin>>s;
cout<<s;
scanf("%s", st); // ім'я рядка – покажчик
printf("Pядок: %s", st);
puts(s); //автоматичний перехід на новий рядок
У С/С++ введення рядків за допомогою функцій форматованого і операцій
потокового введення-виведення має важливе обмеження: такі рядки вводяться
тільки до першого роздільного символу (символа пробілу, табуляції або нового
рядка), всі інші символи рядка - ігноруються. Тому ці засоби можна
застосовувати тільки для введення окремих слів.
Для введення ж рядків-речень можна використати спеціалізовану функцію
введення рядків gets. Формат її виклику є таким:
gets(рядок); // читання введеного з клавіатури рядка
При використанні функції gets, у випадку помилки введення, повертається
нульовий покажчик NULL (описаний у бібліотеці stdio.h). Тому для перевірки
правильності введення рядків доцільно ---використовувати цикл:
while (gets(s)!= NULL)
{ …
}
У С++ для введення рядків-речень можна також скористатися функцією getline,
вбудованою у потік введення cin. Функція getline має два параметри: перший
аргумент – рядок, який вводиться, другий – кількість символів.
Наприклад,
char s[36];
cout<<"Enter row: ";
cin.getline( s, 30); // читання введеного з клавіатури рядка
Обробка рядків
Рядки можуть оброблятися як цілісний об’єкт, а також поелементно
(посимвольно).
При посимвольній обробці доступ до конкретного символу рядка, як і до
елементів масиву символів, здійснюється за індексом або за покажчиком (у
С/С++). Можна вказати індекс рядка і поза його поточною довжиною. У цьому
випадку зчитані символи будуть випадковими. При цьому присвоювання поза
поточною довжиною не впливає на значення рядкової змінної.
При посимвольній обробці до окремого символа рядка можна застосовувати
ті ж операції, що і до змінної символьного типу.
Рядки, як цілісні об’єкти, можна присвоювати, порівнювати і обробляти
різноманітним чином, застосовуючи вбудовані засоби (підпрограми) обробки
рядків, які, зазвичай, містяться у стандартних бібліотеках відповідної системи
програмування. Тому для використання потрібної підпрограми відповідну
бібліотеку (заголовний файл – у С/С++) слід підключити до основної
програми.
У С/С++ функції обробки C-рядків визначені у заголовному файлі string.h.
Імена більшості із них починаються з префікса str.
Дії по обробці рядків різняться в залежності від мови програмування. Однак,
усі їх можна згрупувати наступним чином:
• ініціалізація рядка;
• визначення довжини рядка;
• копіювання рядка;
• об'єднання (конкатенація) рядків;
• порівняння рядків;
• аналіз символів рядка;
• пошук у рядку;
• перетворення рядка.
Ініціалізація рядків може здійснюватися при їх визначенні, а також шляхом
явного присвоювання. При цьому вираз рядкового типу (літерал), зазвичай,
можна присвоїти змінній-рядку. Однак, у мові С++ операція явного
присвоювання літерала рядковій змінній заборонена.
Тобто, якщо мають місце оголошення:
char str[26];
char *st;
то оператор присвоєння виду:
st = "адреса"
є допустимим, а оператор присвоєння:
str = "помилка"
викличе повідомлення про помилку.
Розглянемо наступний фрагмент програми:
char str1[10]= "row 1";
char *str2;
str2=str1;
str2[0]='R';
cout <<str1<<endl; // row 1
Слід зауважити, що у даному випадку неправильно вважати, що в str2
міститься копія str1. Насправді, цей покажчик вказує не на копію, а на той же
самий рядок (str1). При будь-якій зміні вмісту str2 змінюється рядок str1.
Визначення довжини рядка. Визначити поточну довжину рядка можна
тільки після його ініціалізації (у С/С++ - функція strlen). Параметром даних
функцій є рядок, значення довжини якого вони повертають. Прототип задання
функції strlen:
size_t strlen(char *str),
де: стандартний тип size_t визначено у заголовному файлі stddef.h як
беззнаковий цілий.
Наприклад,
char s[20];
cin >> s;
cout << “Length:" << strlen(s).
Слід зауважити, що значення довжини рядка, що повертає функція strlen, не
включає нуль-символ (“0”).
Відоме значення довжини рядка дозволяє обробляти символи рядка за
допомогою циклу for.
Копіювання рядка. Мови програмування підтримують різні варіанти
копіювання рядків. У С/С++ передбачено більше таких можливостей. Зокрема,
можна копіювати вміст одного рядка в інший повністю або частково (перші
символи). Протопити відповідних функцій наведені у табл. 1.
Таблиця 1. Перелік основних функцій копіювання рядків у С/С++
Прототип функції Опис
char* strcpy(char *str1, char *str2); Копіює вміст рядка str2 у рядок str1
char* strncpy(char *str1, char
*str2, size_t n);
Копіює n перших символів рядка
str2 у рядок str1
Необхідно пам'ятати, що масив, який використовують для зберігання рядка
str1, повинен бути достатньо великим, щоб в нього можна було помістити рядок
з масиву str2. Інакше масив str1 переповниться, тобто відбудеться вихід за його
межі, що може призвести до руйнування програми. Наприклад,
char s1[10], s2[ ] = “example", s3[ ]="row";
strcpy(s1, s2);
cout <<s1<<endl; // example
strcnpy(s1, s3, 2);
cout <<s1<<endl; // roample
Слід зазначити, що саме функція strcpy використовується для ініціалізації
рядка-змінної у С/С++.
Об'єднання рядків. Над рядковими змінними означена операція об'єднання
(конкатенації), яка дозволяє дописати один рядок в кінець іншого. Під час
об'єднання рядків поточна довжина рядка, до якого приєднується інший рядок,
збільшується на довжину рядка, що додається. Збільшення довжини
об'єднаного рядка здійснюється тільки у заданих під час оголошення межах.
У деяких мовах програмування об'єднання рядків здійснюється за
допомогою вбудованих операцій, у інших – за допомогою стандартних
функцій. Так у табл. 2 наведено основні функції об'єднання рядків,
передбачені у С/С++.
Таблиця 2. Перелік основних функцій об'єднання рядків у С/С++
Прототип функції Опис
char *strcat(char *str1, char
*str2);
Приєднує рядок str2 в кінець рядка str1
char *strncat(char *str1, char
*str2, size_t n);
Приєднує n перших символів рядка str2
в кінець рядка str1
Наприклад,
char s1[30] ="example", s2[ ] =" of concatenation", s3[ ] ="rows ";
strcat(s1, s2);
cout << s1 << endl; // example of concatenation
strcat(s1, s3, 4);
cout << s1 << endl; // example of concatenation row
Порівняння рядків. Порівняння рядків виконується як серія послідовних
порівнянь символів рядків, що мають однакові індекси, починаючи з першого.
Порівняння здійснюється до першого незбіжного символу, і той рядок
вважається більшим, у якому перший незбіжний символ має більше значення.
Наприклад,
"рядок1" < "рядок2" . Якщо рядки мають різну довжину, але в загальній
частині символи збігаються, то вважається, що коротший рядок менше більш
довгого. Наприклад, "курс" < "курси".
У деяких мовах програмування (наприклад, у Pascal) для порівняння рядків
означено операції порівняння “<“, “=“, “>“. У С/С++ різні варіанти порівняння
рядків реалізуються за допомогою стандартних функцій (табл. 3).
Таблиця 3. Перелік основних функцій порівняння рядків у С/С++
Прототип функції Опис
int strcmp(char *str1, char *str2); Порівнює рядки str1 і str2
int stricmp(char *str1, char *str2); Порівнює рядки str1 і str2 без урахування
регістра
int strncmp(char *str1, char *str2,
size_t n);
Порівнює перші n символів рядків str1 і str2
int strnicmp(char *str1, char *str2,
size_t n);
Порівнює перші n символів рядків str1 і str2
без урахування регістра
Дані функції повертають значення 0, якщо рядки однакові (з урахуванням
або без урахування регістра). Якщо рядок str1 лексикографічно (тобто
відповідно до алфавітного порядку) більший від рядка str2, то повертається
додатне число; якщо ж менший від рядка str2 - то повертається від’ємне число.
Наприклад,
int r;
char s1[20], s2[10]= "example";
cin >>s1; // example
r = strcmp(s1, s2);
cout <<r <<endl; // 0
cin >>s1; // row
r = strcmp(s1, s2);
cout <<r <<endl; // 13
cin >>s1; // concatenation
r = strcmp(s1, s2);
cout <<r <<endl; // -2
Оскільки значення 0, що повертається даними функціями у випадку
рівності порівнюваних рядків, відповідає логічному значенню false, то при
перевірці рівності рядків рекомендується використовувати логічну операцію
НЕ ("!"), щоб інвертувати умову (тобто змінити її на зворотню). Наприклад,
if (! strcmp(s1, s2))
cout << "Рядки однакові" << endl;
else
cout << "Рядки не однакові" << endl;
Прототип функції Опис
int islower( int ch); Перевіряє приналежність аргумента ch до рядкових
літер
int isalnum( int ch); Перевіряє приналежність аргумента ch до алфавітно-
цифрових символів
int isalpha( int ch); Перевіряє приналежність аргумента ch до літер
int isupper( int ch); Перевіряє приналежність аргумента ch до прописних
літер
int isdigit( int ch); Перевіряє приналежність аргумента ch до цифрових
символів
int ispunct( int ch); Перевіряє приналежність аргумента ch до
знаківпунктуації
int isspace( int ch); Перевіряє, чи є аргумент ch пробілом
Аналіз символів рядка. Іноді у програмах виникає необхідність у перевірці
приналежності симолів до певної класифікаційної групи: літера, цифра, знак
пунктуації тощо. Для цього у С/С++ передбачено ряд стандартних функцій
(табл. 4).
Таблиця 4. Перелік основних функцій С/С++ для аналізу символів
Якщо символ належить до відповідної класифікаційної групи, то відповідна
повертає ненульове значення, інакше – 0. Наприклад,
for (int i= 1; i<= strlen(s1); i++)
if (isdigit(s1[i])) cout<<"Element "<<s[ i]<<" -digit"<<endl;
Пошук у рядку. Часто у програмах доводиться виконувати пошук у рядках
окремих символів або підрядків. Деякі мови програмування мають незначні
можливості виконання такого пошуку, інші – значно більші. Так у С/С++
передбачені наступні можливості пошуку у рядках:
•пошук символів;
•пошук підрядків;
•пошук лексем.
Пошук окремих символів підтримується функціями, наведеними у табл. 5.
Таблиця 5. Перелік основних функцій С/С++ для пошуку символів у рядках
Прототип функції Опис
char *strchr(char *str, int
ch);
Шукає перше входження символа сh у рядок str
char *strrchr(char *str, int
ch);
Шукає останнє входження символа сh у рядок
str
char *strpbrk(char *str1,
char *str2);
Шукає першевходження будь-якого символу з
рядка str2 у рядок str1
Наприклад,
if (strchr(filename, '.'))
cout << "Ім'я вже містить розширення" << endl;
else strcat(filename, ".TXT");
Вираз strchr( filename , ' .' ) повертає покажчик на символ точки в рядку, що
адресується покажчиком filename. Якщо такий символ не знайдений, функція
strchr повертає NULL. Оскільки ненульові значення означають "істину", то
можна використовувати функцію strchr як таку, що повертає значення "істина"
/ "хибність".
Прототип функції Опис
char *strstr(char *str1, char
*str2);
Шукає перше входження підрядка str2 у рядок
str1
size_t strcspn(char *str1,
char *str2);
Визначає довжину початкового інтервалу рядка
str1, що не містить символів з рядка str2; тобто,
повертає індекс першого символу рядка str1, який
збігається з будь-яким із символів в рядку str2
size_t strspn(char *str1,
char *str2);
Визначає довжину початкового інтервалу рядка
str1, що містить символи з рядка str2
Окрім пошуку символів в рядку, можна також організувати пошук і підрядків
вказаного рядка. Для цього ц С/С++ служать функції, наведені у табл. 6.
Таблиця 6. Перелік основних функцій С/С++ для пошуку підрядків у рядках
Наприклад,
p = strstr(filename, ".txt");
if (p) cout << " Ім'я вже містить потрібне розширення" << endl;
else
{ p = strchr(filename, '.');
if (p) *p= NULL; //видалити будь-яке інше розширення
strcat(filename, ".txt");
}
Цей фрагмент програми створює ім'я файлу, яке обов'язково закінчується
розширенням .txt. Щоб визначити, чи є в імені файлу це розширення,
програма виконує оператор
p = strstr( filename, ".txt" ) ;
Подібно strchr, функція strstr повертає адресу підрядка або NULL, якщо
шуканий рядок не знайдений. Якщо заданий підрядок знайдений​​, покажчик p
стане рівним його адресі, в даному прикладі - адресі точки (".") в підрядку ".
txt".
Даний приклад також демонструє спосіб відсікання рядка в позиції заданого
символа або підрядка. Якщо при виклику функції strstr результат пошуку
першої точки в рядку filename не нульовий, то виконається оператор, який
запише замість точки нуль-символ:
*p = NULL ; //або *р=’0’
Тим самим буде приєднано новий кінець рядка в тому місці, де раніше
знаходилося розширення файлу. Тепер рядок готовий до додавання нового
розширення шляхом виклику функції strcat.
Перетворення рядків. Мови програмування підтримують різні варіанти
перетворення рядків. Так у Pascal можна видаляти заданий підрядок із рядка
або вставляти його у рядок, перетворювати малі літери у прописні, а також
перетворювати числові значення в рядкові і навпаки.
У С/С++ можливості перетворення рядків значно ширші. Перелік основних
із них наведений у табл. 7.
Таблиця 7. Перелік основних функції перетворення рядків у С/С++
Прототип функції Опис
char *strlwr(char *str); Приводить символи рядка до нижнього
регістра
char *strupr(char *str); Приводить символи рядка до верхнього
регістра
char *strset(char *str, int ch); Замінює всі символи рядка на символ сh
char *strnset(char *str, int ch,
size_t n);
Замінює перші n символів у рядку на
символ сh
char *strrev(char *str); Інвертує рядок
Наприклад,
strcpy(str, "this is a test");
strupr(str);
cout << str << endl; // THIS IS A TEST
strnset(str, “-“, 9);
cout << str << endl; // --------- TEST
strrev(str);
cout << str << endl; // TSET ---------
До функцій перетворення рядків також відносять функції, які дозволяють
здійснювати перетворення рядка у відповідне числове значення (наведені у
табл. 8).
Таблиця 8. Перелік основних функції перетворення рядків і чисел у С/С++
Прототип функції Опис
double atof(const char
*str);
Перетворює рядок str в число з плаваючою крапкою типу double;
якщо рядок str не є коректним текстовим поданням числа double,
то повертається NULL (заголовний файл - math.h)
double strtod ( const char
*str, char **endptr );
Перетворює рядок str в значення типу double; параметр endptr
встановлюється так, щоб вказувати на "невикористаний" залишок
початкового рядка, якщо такий існує (заголовний файл - stdlib.h)
int atoi(const char *str); Перетворює рядок str в число типуint (заголовний файл - stdlib.h)
long atol(const char *str);
Перетворює рядок str в число типуlong (заголовний файл -
stdlib.h)
Наприклад,
char str []= “10.4e-1”, *ptr;
double d = atof(str);
cout << d <<endl; // 1.04
double d = strtod(str, &ptr);
cout << d <<endl; // 1.04
int n = atoi(str);
cout << n <<endl; // 10
Після числа у рядку перетворення може слідувати будь-який символ, який
не може бути частиною допустимого числа з плаваючою крапкою - пробіли,
символи табуляції і порожнього рядка, розділові знаки (але не точки) і
символи, відмінні від літер "Е" або "е".
Це означає, що, якщо функція atof або функція strtod викликаються з
аргументом "10.4е-1 HELLO", то все рівно буде повернуто значення 1.04.
Різниця між цими функціями полягає у тому, що функція strtod має
параметр-покажчик (endptr), який встановлюється так, щоб вказувати на
"невикористаний" залишок початкового рядка, якщо такий існує.
Це означає, що для попередгього прикладу функція strtod поверне значення
1.04, а параметр-покажчик endptr буде вказувати на пробіл, який передує
слову "HELLO". Наприклад, наступна програма читає числа з плаваючою
точкою з текстового рядка:
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{ char *end, *start = "100.00 notebooks 200.00 pencils";
end = start;
while(*start)
{ printf("%f, ", strtod(start, &end));
printf("Rest of the line: %sn", end);
start = end;
while(!isdigit(*start) && *start) start++; // пропускає символи, що не
входять в числа
}
system("pause");
}
Ось що виводить ця програма:
Мови програмування також підтримують функції перетворення числових
значень в рядкові. Основні такі функції мови С/С++ наведені у табл. 9.
Таблиця 9. Перелік основних функції перетворення рядків і чисел у С/С++
Прототип функції Опис
char *itoa(int value, char *str, int
radix);
Перетворює значення цілого типу value в рядок str з
урахуванням зазначеної системи числення radix
char *gcvt(double value, int ndig,
char *buf);
Перетворює число з плаваючою
крапкою value типуdouble в рядок
довжиною ndig цифр, який адресується
аргументом buf. Спосіб подання вибирається
функцією (звичайний або експонентний).
char *ecvt(double value, int ndig,
int *dec, int *sign);
Перетворює число з плаваючою
точкою value типу doubleв символьний рядок
довжиною ndig цифр і повертає адресний покажчик
отриманого рядка. Якщо кількість цифр
в value перевищує ndig, остання значуща цифра
округлюється, якщо цифр менше, ніж ndig, - рядок
доповнюється нулями.Результуючий рядок не містить
символу десяткової точки - позиція десяткової точки
щодо початку рядка непрямим чином зберігається в
параметрі dec (від'ємне значення decозначає, що
десяткова точка розміщена лівіше першої цифри
на dec позицій, додатне – правіше першої цифри
на dec позицій).Аргумент sign вказує на ціле, що
визначає знак перетворюваного числа (якщо sign
дорівнює 0, то число додатне, інакше - від'ємне).
Наприклад,
char result[17];
int value=23677;
itoa(value, result, 10);
cout << "10:" << result << endl; // 23677
itoa(value, result, 16);
cout << "16:" << result << endl; // 5c7d
itoa(value, result, 2);
cout << "2:" << result << endl; // 101110001111101
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = =
int dec, sign;
char *buffer;
int precision=10;
buffer= ecvt(314.15926535, precision, &dec, &sign);
cout << buffer << endl; // рядок -"3141592654", dec=3, sign=0
// = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
= = = = = = = = = = = = = = =
char buffer[50];
int precision = 7;
gcvt (-3.1415e3, precision, buffer);
cout << buffer << endl; // -3141.5
Параметри-рядки
При вирішенні практичних задач часто потрібно використовувати рядок як
параметр функції. Крім того, функції можуть повертати покажчик на рядок в
якості результату.
Розглянемо реалізацію цих можливостей у мовах програмування.
Передача символьного рядка у функцію подібна до передачі будь-якого
масиву як параметру. У С/С++ таких способів декілька:
• як масиву символів, наприклад,
void showText1(char str []);
• за допомогою покажчика, наприклад,
void showText2(char *str);
• за посиланням, наприклад,
void showText3(char (&str)[150]).
При передачі рядка як масиву символів не треба вказувати розмірність
масиву (кількість символів у рядку).
За допомогою символу '0', який автоматично додається в кінець будь-якого
рядка, функція сама знайде останній елемент масиву.
При передачі рядка за посиланням необхідно вказувати точний розмір рядка
- без цього компілятор може видати помилку.
Приклад.
void showText1(char str[]) //функція приймає рядок як масив
{ cout << str << endl;
}
void showText2(char *str) //покажчик на адресу першого символа в
рядку
{ cout << str << endl;
}
void showText3(char (&str)[150]) // адреса рядка із 150-ти символів
{ cout << str << endl;
}
int main()
{ char str1[] = "str1 - pass as an array";
showText1(str1);
cout << endl;
char str2[] = "str2 - pass using the pointer";
showText2(str2);
cout << endl;
char str3[150] = "str3 - pass using the address line";
showText3(str3);
cout << endl;
system("pause");
}
Масиви рядків
Текст, що обробляється програмою, може розглядатися як масив рядків. У
такому використанні немає нічого незвичайного. Наприклад, при
програмуванні баз даних для з'ясування коректності команд, що вводяться
користувачем, вхідні дані порівнюються з вмістом масиву рядків, у якому
записано допустимі у цьому додатку команди. Для побудови масиву рядків
може використовуватися двовимірний символьний масив, у якому розмір
лівого індексу визначає кількість рядків, а розмір правого – максимальну
довжину кожного рядка. Наприклад, char strArray[20][80] – оголошення
масиву, призначеного для зберігання 20 рядків завдовжки 80 символів.
Отримати доступ до окремого рядка такого масиву достатньо просто:
достатньо вказати тільки лівий індекс. Наприклад, виклик функції gets для
запису третього рядка описаного вище масиву: gets(strArray[2]);
Щоб краще зрозуміти, як потрібно поводитися з масивами рядків,
розглянемо фрагмент програми, яка приймає рядки тексту, що вводяться з
клавіатури, і відображає їх на екрані після введення порожнього рядка.
int t, i;
char text[100][80];
for(t=0; t<100; t++)
{ cout << t << ": "; gets(text[t]);
if(!text[t][0]) break; // вихід з циклу за порожнім рядком
}
for(i=0; i<t; i++) // відображення рядків на екрані
cout << text[i] << endl;
Обробка stl-рядків
Як уже зазначалося, у С++ рядки можна розглядати як об’єкти шаблонного
класу string, описаного в стандартній бібліотеці шаблонів STL (Standard
Template Library). Тому такі рядки ще називають STL-рядками. Щоб
використовувати рядки класу string, треба підключити до програми заголовний
файл <string>:
#include <string>.
Обробка STL-рядків має певну специфіку. Зокрема, STL-рядкам можна
присвоювати значення, як і змінним будь-яких інших типів:
string name; // створення рядка name
name = “Row”; // присвоєння значення рядковій змінній name
Введення або виведення STL-рядків виконується застосуванням
перевантажених для рядків операцій потокового введення та виведення (”<<” і
”>>”). Наприклад,
string s;
cin >> s;
cout << s << endl;
Однак слід пам’ятати, що таким способом рядки вводяться тільки до першого
роздільного символу (пробілу, кінця рядка, символу табуляції). Для введення
рядка-речення слід скористатися функцією getline класу string:
string s; // створення рядка s
getline(cin, s); // читання введеного з клавіатури рядка
cout << s<<endl; // одержання довжини рядка
STL-рядки можна лексикографічно порівнювати між собою, користуючись
звичайними операціями порівняння (”= =”, ”>” і т.ін.):
if (str == “Hello”)
cout << str << endl;
Для string-об'єктів визначена також операція додавання (”+” ), тобто можна
написати s1 + s2 і результатом цієї операції буде конкатенація (об’єднання)
рядків: рядок s2 буде дописаний в кінець рядка s1. Наприклад,
string str(“Hello”);
string r = str + ‘ ’ + “world”; //конкатенація трьох рядків
r += ‘!’; //r = “Hello world!”
Основна функціональність STL-рядків реалізується через методи класу
string. Методом в ООП називають функцію, яка застосовується до об'єкта
вказаного класу, наприклад, рядка. При виклику метода його ім'я пишеться
після ідентифікатора об'єкта через крапку. Наприклад, у об'єкта типу string є
метод length, який повертає довжину рядка. Якщо str - це рядок, то метод
викликається так: str.length().
Даний клас дозволяє досить ефективно і легко вирішувати наступні задачі:
•створювати, присвоювати, копіювати і видаляти рядки;
•виконувати перетворення типів символьних змінних;
•порівнювати рядки;
•поєднувати рядки;
•визначати довжину рядка;
•знаходити і заміщати потрібний фрагмент у рядку.
Перелік деяких методів обробки string-рядків наведений у табл. 10
Таблиця 10. Перелік основних методів обробки STL-рядків
Назва Опис
empty перевіріє, чи є рядок порожнім (якщо рядок порожній,
повертає true)
erase видаляє символ або декілька символів з рядка
find шукає підрядок в рядку;
insert вставляє підрядоку рядок
length повертає довжину рядка
replace видаляє підрядок
substr виділяє підрядок рядка
swap обмінює вмісти двох рядків
Наприклад,
string str1(“Hello”);
string str2=“greetings”;
if (str1.empty()) cout << "String is empty" << "n";
else cout << "String isn't empty" << "n";
cout << str1.length(); //повертає 5 (довжину рядка str1)
cout << str2.find(“ее”); //повертає 2 (позицію самого
лівого входження “ее”)
string s(“Testing!”);
cout << s.substr(2, 5); // “sting”
cout << s[3]; // ‘t’
s.replace(2, 2,”eth”); // s == “Teething!”
s.erase(1, 4); // s == “Ting!”
s[1] = ‘a’; // s == “Tang!”
s.insert(1,”w”); // s == “Twang!”
Також існує багато варіацій цих методів (табл. 11).
Таблиця 11. Перелік варіацій деяких методів обробки STL-рядків
Прототип Опис
unsigned int find (string substr); шукає підрядок substr в рядку; повертає індекс, з якого
починається перше входження підрядка в рядок
unsigned int findC(string substr,
unsigned int from);
шукає підрядок substr в рядку, починаючи з позиції from
unsigned int find_first_of (string
substr);
шукає перше входження будь-якого символа
ізsubstrврядку
unsigned int find_first_not_of(string
substr);
шукаєперший символ врядку, який не входить в substr
unsigned int find_ last _of (string
substr);
шукає останнє входження будь-якого символа
із substrврядку
unsigned int find_last_not_of(string
substr);
шукаєостанній символ врядку, який не входить в substr
unsigned int rfind(string substr); шукає останнє входження підрядка substr в рядок;
повертає індекс, з якого починається останнє входження
підрядка в рядок
unsigned int rfindC(string substr,
unsigned int from);
шукає останній підрядок substr в рядку, індекс початку
якого менше from
string substr(unsigned int n); або виділяє підрядок, що містить перші n символів рядка
string substr(unsigned int k, unsigned
int n);
виділяє підрядок, що містить перші n символів рядка,
починаючи з k-го
Наприклад,
string str(“Hello, World!”);
cout << str.rfind(‘o’); //виконує пошук з кінця (повертає 8)
int index = str.find_first_of(", !"); // пошук першого пробілу, знаку оклику або
коми
Для позначення того, що шукана послідовність символів не знайдена, багато
методів (наприклад, find) повертають спеціальну константу npos, яка означає
«не знайдено» або «всі символи, що залишилися». Наприклад,
string str(“Hello”);
cout << str.find(“x”) // повертає string::npos
Для того, щоб використовувати все розмаїття методів обробки STL-рядків,
під рукою повинна бути відповідна документація. Microsoft пропонує досить
докладну документацію, як частину MSDN для своєї реалізації STL.
Хоча значна частина функціональності роботи з рядками реалізована в
бібліотеці <string.h> (функції strcmp, strcat, strcpy, strlen та ін.), але
використання string-об'єктів часто буває зручнішим.
Для роботи з рядками передбачений шаблонний клас basic_string з якого
визначається клас string:
typedef basic_string <char> string;
Клас string відрізняється від vector<char> функціями для маніпулювання
рядками й політикою роботи з пам'яттю. Для визначення довжини рядка,
використовується string: length(), а не vector::size().
Розглянемо приклад роботи з рядками.
string sl = "слово";
string s1 = sl.substr(0, 3), // "сло"
s2 = sl.substr(1, 3), // "лов"
s3 = sl.substr(0, s.length()-1), //"слов"
s4 = sl.substr(1), // "лово"
s = "Завтра - термін здачі лабораторної !";
// пошук першого пробілу
int ind1 = s.find_first_of(' ');
// пошук першого пробілу, знаків ! або -
int ind2 = s.find_first_of(" -!");
Також рядки можна додавати за допомогою оperator+, порівнювати за
допомогою операторів порівняння. Таким чином, vector<string> можна
впорядковувати стандартними методами. Рядки порівнюються в
лексикографічному порядку
•string- представляет из себя коллекцию, хранящую символы char в формате
ASCII. Для того, чтобы использовать данную коллекцию, вам необходимо
включить #include <string>.
•wstring- это коллекция для хранения двухбайтных символов wchar_t,
которые используются для представления всего набора символов в формате
Unicode. Для того, чтобы использовать данную коллекцию, вам необходимо
включить #include <xstring>.
int string_length(char []);
void main(void)
{ char title[] = " Learning to program in C++";
char lesson[] = "Сharacter strings";
cout << " String " << title << " contains " <<
string_length(title) << " characters" << endl;
cout << " String " << lesson << " contains " <<
string_length(lesson) << " characters" << endl;
}
int string_length(char string[])
{ int i;
for (i = 0; string[і] != '0'; i++);
return i;
}
24

More Related Content

What's hot

Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.
Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.
Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.Василь Тереховський
 
Довідкові матеріали до НМТ з математики
Довідкові матеріали до НМТ з математики Довідкові матеріали до НМТ з математики
Довідкові матеріали до НМТ з математики Oleksii Voronkin
 
4 клас алгоритм з розгалуженням урок 20
4 клас алгоритм з розгалуженням урок 204 клас алгоритм з розгалуженням урок 20
4 клас алгоритм з розгалуженням урок 20Жанна Коваль
 
Пошук максимального елемента в масиві
Пошук максимального елемента в масивіПошук максимального елемента в масиві
Пошук максимального елемента в масивіЗоя Муляр
 
ознака паралельності прямої і площини
ознака паралельності прямої і площиниознака паралельності прямої і площини
ознака паралельності прямої і площиниanyaanya1
 
Вивчаємо мову програмування Lazarus
Вивчаємо мову програмування LazarusВивчаємо мову програмування Lazarus
Вивчаємо мову програмування LazarusЮлія Артюх
 
Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».
Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».
Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».VsimPPT
 
8 Алгоритми з розгалуженнями для опрацювання величин
8 Алгоритми з розгалуженнями для опрацювання величин8 Алгоритми з розгалуженнями для опрацювання величин
8 Алгоритми з розгалуженнями для опрацювання величинСергій Каляфіцький
 
Урок 35. Логічні вирази. Змінні логічного типу.
Урок 35. Логічні вирази.  Змінні  логічного  типу.Урок 35. Логічні вирази.  Змінні  логічного  типу.
Урок 35. Логічні вирази. Змінні логічного типу.Василь Тереховський
 
Робота з файлами в C++
Робота з файлами в C++Робота з файлами в C++
Робота з файлами в C++Alexander Kuzmenko
 
інформатика 1 урок
інформатика 1 урокінформатика 1 урок
інформатика 1 урокssuserd09fbf
 
Презентація Бази даних Урок 1.pptx
Презентація Бази даних Урок 1.pptxПрезентація Бази даних Урок 1.pptx
Презентація Бази даних Урок 1.pptxssuserceb60a
 
Вартова служба
Вартова службаВартова служба
Вартова службаsh75inf
 
3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.
3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.
3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.Сокальська ЗШ І-ІІІ ступенів №2
 
Створення таблиць в текстових документах
Створення таблиць в текстових документахСтворення таблиць в текстових документах
Створення таблиць в текстових документахAlena Danilets
 

What's hot (20)

Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.
Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.
Урок 65. Вибір теми проекту. Його планування. Добір ресурсів.
 
презентація поняття події
презентація   поняття подіїпрезентація   поняття події
презентація поняття події
 
Довідкові матеріали до НМТ з математики
Довідкові матеріали до НМТ з математики Довідкові матеріали до НМТ з математики
Довідкові матеріали до НМТ з математики
 
4 клас алгоритм з розгалуженням урок 20
4 клас алгоритм з розгалуженням урок 204 клас алгоритм з розгалуженням урок 20
4 клас алгоритм з розгалуженням урок 20
 
Пошук максимального елемента в масиві
Пошук максимального елемента в масивіПошук максимального елемента в масиві
Пошук максимального елемента в масиві
 
6 клас урок 17
6 клас урок 176 клас урок 17
6 клас урок 17
 
ознака паралельності прямої і площини
ознака паралельності прямої і площиниознака паралельності прямої і площини
ознака паралельності прямої і площини
 
Вивчаємо мову програмування Lazarus
Вивчаємо мову програмування LazarusВивчаємо мову програмування Lazarus
Вивчаємо мову програмування Lazarus
 
Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».
Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».
Урок 22 для 3 класу - . Використання логічних висловлювань з «не», «і», «або».
 
8 Алгоритми з розгалуженнями для опрацювання величин
8 Алгоритми з розгалуженнями для опрацювання величин8 Алгоритми з розгалуженнями для опрацювання величин
8 Алгоритми з розгалуженнями для опрацювання величин
 
функції
функціїфункції
функції
 
середовище Lazarus
середовище Lazarusсередовище Lazarus
середовище Lazarus
 
6 клас урок 6
6 клас урок 66 клас урок 6
6 клас урок 6
 
Урок 35. Логічні вирази. Змінні логічного типу.
Урок 35. Логічні вирази.  Змінні  логічного  типу.Урок 35. Логічні вирази.  Змінні  логічного  типу.
Урок 35. Логічні вирази. Змінні логічного типу.
 
Робота з файлами в C++
Робота з файлами в C++Робота з файлами в C++
Робота з файлами в C++
 
інформатика 1 урок
інформатика 1 урокінформатика 1 урок
інформатика 1 урок
 
Презентація Бази даних Урок 1.pptx
Презентація Бази даних Урок 1.pptxПрезентація Бази даних Урок 1.pptx
Презентація Бази даних Урок 1.pptx
 
Вартова служба
Вартова службаВартова служба
Вартова служба
 
3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.
3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.
3 клас урок 13 що таке веб сторінки,веб-сайти та як їх переглядати.
 
Створення таблиць в текстових документах
Створення таблиць в текстових документахСтворення таблиць в текстових документах
Створення таблиць в текстових документах
 

Similar to рядки (20)

2
22
2
 
2
22
2
 
2
22
2
 
тема 7
тема 7тема 7
тема 7
 
8 11
8 118 11
8 11
 
Ponyattya pascal
Ponyattya pascalPonyattya pascal
Ponyattya pascal
 
рядки в C ++
рядки в C ++рядки в C ++
рядки в C ++
 
5971 789623
5971 7896235971 789623
5971 789623
 
інформатика алгор та прогр по підручнику верлань 2 стор на 1 листку
інформатика алгор та прогр по підручнику верлань 2 стор на 1 листкуінформатика алгор та прогр по підручнику верлань 2 стор на 1 листку
інформатика алгор та прогр по підручнику верлань 2 стор на 1 листку
 
Основи програмування
Основи програмуванняОснови програмування
Основи програмування
 
Inf tema 1_urok_18_6-klas
Inf tema 1_urok_18_6-klasInf tema 1_urok_18_6-klas
Inf tema 1_urok_18_6-klas
 
8 11
8 118 11
8 11
 
Основи алгоритмізації та програмування. Лекція 1
Основи алгоритмізації та програмування. Лекція 1Основи алгоритмізації та програмування. Лекція 1
Основи алгоритмізації та програмування. Лекція 1
 
Inf tema 1_urok_18_6-klas
Inf tema 1_urok_18_6-klasInf tema 1_urok_18_6-klas
Inf tema 1_urok_18_6-klas
 
мова паскаль 42
мова паскаль 42мова паскаль 42
мова паскаль 42
 
4 18
4 184 18
4 18
 
Лекція #05. Технологія css
Лекція #05. Технологія cssЛекція #05. Технологія css
Лекція #05. Технологія css
 
Функція plot() в R
Функція plot() в RФункція plot() в R
Функція plot() в R
 
1
11
1
 
Html
HtmlHtml
Html
 

More from cit-cit

лекція 5
лекція 5лекція 5
лекція 5cit-cit
 
лаборатор. 10
лаборатор. 10лаборатор. 10
лаборатор. 10cit-cit
 
лекція 19
лекція 19лекція 19
лекція 19cit-cit
 
лекція 18
лекція 18лекція 18
лекція 18cit-cit
 
лекція 17
лекція 17лекція 17
лекція 17cit-cit
 
лекція 16
лекція 16лекція 16
лекція 16cit-cit
 
лекція 12
лекція 12лекція 12
лекція 12cit-cit
 
лекція 11
лекція 11лекція 11
лекція 11cit-cit
 
лекція 10
лекція 10лекція 10
лекція 10cit-cit
 
лаборатор. 15
лаборатор. 15лаборатор. 15
лаборатор. 15cit-cit
 
лаборатор. 14
лаборатор. 14лаборатор. 14
лаборатор. 14cit-cit
 
лаборатор. 13
лаборатор. 13лаборатор. 13
лаборатор. 13cit-cit
 
лаборатор. 12
лаборатор. 12лаборатор. 12
лаборатор. 12cit-cit
 
лаборатор. 11
лаборатор. 11лаборатор. 11
лаборатор. 11cit-cit
 
лаборатор. 9
лаборатор. 9лаборатор. 9
лаборатор. 9cit-cit
 
лаборатор. 8
лаборатор. 8лаборатор. 8
лаборатор. 8cit-cit
 
лаборатор. 7
лаборатор. 7лаборатор. 7
лаборатор. 7cit-cit
 
лекція 15 (pdf.io)
лекція 15 (pdf.io)лекція 15 (pdf.io)
лекція 15 (pdf.io)cit-cit
 
лекція 14 (pdf.io)
лекція 14 (pdf.io)лекція 14 (pdf.io)
лекція 14 (pdf.io)cit-cit
 
лекція 13 (pdf.io)
лекція 13 (pdf.io)лекція 13 (pdf.io)
лекція 13 (pdf.io)cit-cit
 

More from cit-cit (20)

лекція 5
лекція 5лекція 5
лекція 5
 
лаборатор. 10
лаборатор. 10лаборатор. 10
лаборатор. 10
 
лекція 19
лекція 19лекція 19
лекція 19
 
лекція 18
лекція 18лекція 18
лекція 18
 
лекція 17
лекція 17лекція 17
лекція 17
 
лекція 16
лекція 16лекція 16
лекція 16
 
лекція 12
лекція 12лекція 12
лекція 12
 
лекція 11
лекція 11лекція 11
лекція 11
 
лекція 10
лекція 10лекція 10
лекція 10
 
лаборатор. 15
лаборатор. 15лаборатор. 15
лаборатор. 15
 
лаборатор. 14
лаборатор. 14лаборатор. 14
лаборатор. 14
 
лаборатор. 13
лаборатор. 13лаборатор. 13
лаборатор. 13
 
лаборатор. 12
лаборатор. 12лаборатор. 12
лаборатор. 12
 
лаборатор. 11
лаборатор. 11лаборатор. 11
лаборатор. 11
 
лаборатор. 9
лаборатор. 9лаборатор. 9
лаборатор. 9
 
лаборатор. 8
лаборатор. 8лаборатор. 8
лаборатор. 8
 
лаборатор. 7
лаборатор. 7лаборатор. 7
лаборатор. 7
 
лекція 15 (pdf.io)
лекція 15 (pdf.io)лекція 15 (pdf.io)
лекція 15 (pdf.io)
 
лекція 14 (pdf.io)
лекція 14 (pdf.io)лекція 14 (pdf.io)
лекція 14 (pdf.io)
 
лекція 13 (pdf.io)
лекція 13 (pdf.io)лекція 13 (pdf.io)
лекція 13 (pdf.io)
 

рядки

  • 1. Тема 12.3 Рядки в мові програмування С++. Робота з рядками. Рядок як масив літер.
  • 2. Поняття рядка в мові програмування Один з різновидів одновимірних масивів — масив символів, або рядок, — посідає особливе місце у багатьох мовах програмування. Це не випадково, адже алгоритми перетворення рядків застосовуються для вирішення широкого спектру задач. Рядки, як різновиди даних, призначені для введення, обробки і виведення символьної інформації. Рядок у мові програмування – це скінчена послідовність символів, які сприймаються і обробляються як єдине ціле. Рядки можуть представлятися у вигляді масиву символів, але масив символів - не завжди рядок! Кожен рядок характеризується загальною довжиною, яка визначається при оголошенні та поточною довжиною - кількістю символів у конкретний момент виконання програми. Тобто, довжина рядка може змінюватися в процесі роботи програми, але не може перевищувати загальної довжини, зазначеної при оголошенні типу. Деякі мови програмування накладають обмеження на максимальну довжину рядка,але в більшості мов, зокрема, у С++, подібні обмеження відсутні - довжина рядка може обмежуватись лише кількістю пам'яті на комп'ютері. Рядковий тип (тип рядка) – це тип даних, значеннями якого є довільна послідовність символів алфавіту. Кожна змінна такого типу може бути представлена фіксованою кількістю байтів або мати довільну довжину. Слід зазначити, що деякі мови програмування мають вбудований тип даних для зберігання рядків; у інших - рядок представляється як символьний масив, який завершується певним символом.
  • 3. Зокрема, у мові С не визначено вбудованого рядкового типу даних, але поняття “рядка”, як єдиної лінгвістичної конструкції, існує. Рядком в С вважається символьний масив, який завершується символом кінця рядка '0' (NULL- символом). Такий підхід до реалізації рядків дає програмісту більше "важелів" керування порівняно з тими мовами, у яких використовується окремий рядковий тип даних. В сучасних IDE, що підтримують мову С++, доступною для роботи є так звана стандартна бібліотека шаблонів STL (Standard Template Library), яка містить універсальні шаблонні класи і функції, які реалізують функціональність багатьох структур даних. Зокрема, в ній є клас string, що слугує для організації роботи з рядками. Сам STL-рядок розглядається як контейнер для зберігання символів. Для використання класу string необхідно підключити заголовний файл <string>. При розміщенні у пам'яті рядок, як різновид масиву, займає зв’язну область і зберігається як безперервна послідовність символів. Часто при компіляції програми для даних рядкового типу резервується ділянка пам'яті, розмір якої дещо більший за загальну довжину рядка (зазвичай, на 1 байт). Додатковий байт використовується для зберігання допоміжних даних, зокрема, значення поточної довжини рядка (у Pascal) або символа кінця рядка (у С/С++).
  • 4. Опис рядків Синтаксис опису змінної-рядка залежить від способу подання рядка, характерного для тієї чи іншої мови програмування. Якщо мова програмування має вбудований рядковий тип даних, то змінна-рядок оголошується з використанням відповідного ідентифікатора типу. У С/С++ змінна-рядок, як масив символів, має наступний синтаксис оголошення: char ім’я[загальна_довжина]. Оголошений масив символів повинен мати такий розмір, щоб мати змогу зберігати найдовший рядок, що оброблятиметься, та символ кінця рядка '0'. Як і у випадку масиву, ім’я рядка у С/С++ є покажчиком на нього (на його перший символ). Отже, рядок можна оголосити і як покажчик на тип char: сhar *ім’я. Наприклад, char str[26]; // змінна-рядок char *st. // покажчик на рядок При зазначенні довжини рядка слід враховувати завершальний нуль-символ. Наприклад, у вищенаведеному рядку str можна зберігати не 26, а лише 25 символів. Рядок, як масив символів, у С/С++ може як оголошуватися, так і визначатися. Ініціалізація рядка здійснюється під час його визначення за допомогою рядкових літералів або як перелік окремих символів. Наприклад,
  • 5. char str1[]="ПРИВІТ"; // довжина рядка визначається автоматично char str2[4]={‘а',‘b’,‘с',’0’}; // '0' заноситься явно char *st = "Приклад довгого рядка"; char *st 1= ""; Рядок, визначений останнім (""), вважається порожнім або нульовим. Він складається тільки з '0' (ознаки завершення рядка). При визначенні рядків за допомогою літералів, програмісту не потрібно вручну додавати в кінець нуль-символ - компілятор робить це автоматично. Отже, рядок "ПРИВІТ" в пам'яті розміщується так: Не слід плутати символьну константу з рядком, що містить один символ: 'Х' - це окремий символ (символьна константа), що займає 1 байт пам'яті; "Х" - це рядок (рядкова константа), що складається з одного символу (букви Х) та символу кінця рядка '0' і займає 2 байти пам'яті. STL-рядки (у С++) створюються і визначаються наступним чином: string s1, s2; // створення рядків s1 і s2 string str1(“Hello”); // створення і ініціалізація рядка str1 string str2=“greetings”; // ще одне створення і ініціалізація рядка str2
  • 6. Окрім рядка-змінної у програмах можна використовувати рядкові (текстові) константи, які не можуть змінювати своє значення в процесі роботи програми. Описуються вони використання ключового слова const. У С/С++ рядкову константу можна описати як через через ім’я, так і через покажчик на її перший символ. Оскільки ім’я рядка є покажчиком на його перший елемент, то наступні визначення будуть еквівалентними: const char *str1="Рядок 1"; const char str2[]="Рядок 2"; Рядкові константи можна визначити і за допомогою директиви препроцесора #define, наприклад, #define str "Приклад рядка" // ' 0' заноситься автоматично Для використання цієї рядкової константи достатньо вказати її ім’я (str) у відповідному місці програми.
  • 7. Введення-виведення рядків Для введення-виведення рядків у мовах програмування, зазвичай, використовуються вбудовані підпрограми. У мові С++ для введення-виведення рядків у консолі можуть використовуватися декілька альтернативних варіантів: •функції форматованого введення-виведення (scanf, printf); •спеціалізовані функції введення-виведення рядків (gets, puts). Мова С++ розширює ці можливості шляхом використання потоків введення- виведення cin і cout. Для використання спеціальних функцій та функцій форматованого введення- виведення рядків слід підключити заголовний файл <stdio.h>; для використання потокового введення-виведення - заголовний файл <iostream>. Поточна довжина рядка, що вводиться, визначається автоматично. Зокрема, при введенні рядка з клавіатури його довжина визначатиметься як кількість символів, введених до натискання клавіші Enter, і символа кінця рядка (‘0’), який автоматично заноситься після натиснення клавіші Enter. Наприклад, char s[14], st[19], str[16]; cin>>s; cout<<s; scanf("%s", st); // ім'я рядка – покажчик printf("Pядок: %s", st); puts(s); //автоматичний перехід на новий рядок
  • 8. У С/С++ введення рядків за допомогою функцій форматованого і операцій потокового введення-виведення має важливе обмеження: такі рядки вводяться тільки до першого роздільного символу (символа пробілу, табуляції або нового рядка), всі інші символи рядка - ігноруються. Тому ці засоби можна застосовувати тільки для введення окремих слів. Для введення ж рядків-речень можна використати спеціалізовану функцію введення рядків gets. Формат її виклику є таким: gets(рядок); // читання введеного з клавіатури рядка При використанні функції gets, у випадку помилки введення, повертається нульовий покажчик NULL (описаний у бібліотеці stdio.h). Тому для перевірки правильності введення рядків доцільно ---використовувати цикл: while (gets(s)!= NULL) { … } У С++ для введення рядків-речень можна також скористатися функцією getline, вбудованою у потік введення cin. Функція getline має два параметри: перший аргумент – рядок, який вводиться, другий – кількість символів. Наприклад, char s[36]; cout<<"Enter row: "; cin.getline( s, 30); // читання введеного з клавіатури рядка
  • 9. Обробка рядків Рядки можуть оброблятися як цілісний об’єкт, а також поелементно (посимвольно). При посимвольній обробці доступ до конкретного символу рядка, як і до елементів масиву символів, здійснюється за індексом або за покажчиком (у С/С++). Можна вказати індекс рядка і поза його поточною довжиною. У цьому випадку зчитані символи будуть випадковими. При цьому присвоювання поза поточною довжиною не впливає на значення рядкової змінної. При посимвольній обробці до окремого символа рядка можна застосовувати ті ж операції, що і до змінної символьного типу. Рядки, як цілісні об’єкти, можна присвоювати, порівнювати і обробляти різноманітним чином, застосовуючи вбудовані засоби (підпрограми) обробки рядків, які, зазвичай, містяться у стандартних бібліотеках відповідної системи програмування. Тому для використання потрібної підпрограми відповідну бібліотеку (заголовний файл – у С/С++) слід підключити до основної програми. У С/С++ функції обробки C-рядків визначені у заголовному файлі string.h. Імена більшості із них починаються з префікса str.
  • 10. Дії по обробці рядків різняться в залежності від мови програмування. Однак, усі їх можна згрупувати наступним чином: • ініціалізація рядка; • визначення довжини рядка; • копіювання рядка; • об'єднання (конкатенація) рядків; • порівняння рядків; • аналіз символів рядка; • пошук у рядку; • перетворення рядка. Ініціалізація рядків може здійснюватися при їх визначенні, а також шляхом явного присвоювання. При цьому вираз рядкового типу (літерал), зазвичай, можна присвоїти змінній-рядку. Однак, у мові С++ операція явного присвоювання літерала рядковій змінній заборонена. Тобто, якщо мають місце оголошення: char str[26]; char *st; то оператор присвоєння виду: st = "адреса" є допустимим, а оператор присвоєння: str = "помилка" викличе повідомлення про помилку.
  • 11. Розглянемо наступний фрагмент програми: char str1[10]= "row 1"; char *str2; str2=str1; str2[0]='R'; cout <<str1<<endl; // row 1 Слід зауважити, що у даному випадку неправильно вважати, що в str2 міститься копія str1. Насправді, цей покажчик вказує не на копію, а на той же самий рядок (str1). При будь-якій зміні вмісту str2 змінюється рядок str1. Визначення довжини рядка. Визначити поточну довжину рядка можна тільки після його ініціалізації (у С/С++ - функція strlen). Параметром даних функцій є рядок, значення довжини якого вони повертають. Прототип задання функції strlen: size_t strlen(char *str), де: стандартний тип size_t визначено у заголовному файлі stddef.h як беззнаковий цілий. Наприклад, char s[20]; cin >> s; cout << “Length:" << strlen(s). Слід зауважити, що значення довжини рядка, що повертає функція strlen, не включає нуль-символ (“0”). Відоме значення довжини рядка дозволяє обробляти символи рядка за допомогою циклу for.
  • 12. Копіювання рядка. Мови програмування підтримують різні варіанти копіювання рядків. У С/С++ передбачено більше таких можливостей. Зокрема, можна копіювати вміст одного рядка в інший повністю або частково (перші символи). Протопити відповідних функцій наведені у табл. 1. Таблиця 1. Перелік основних функцій копіювання рядків у С/С++ Прототип функції Опис char* strcpy(char *str1, char *str2); Копіює вміст рядка str2 у рядок str1 char* strncpy(char *str1, char *str2, size_t n); Копіює n перших символів рядка str2 у рядок str1 Необхідно пам'ятати, що масив, який використовують для зберігання рядка str1, повинен бути достатньо великим, щоб в нього можна було помістити рядок з масиву str2. Інакше масив str1 переповниться, тобто відбудеться вихід за його межі, що може призвести до руйнування програми. Наприклад, char s1[10], s2[ ] = “example", s3[ ]="row"; strcpy(s1, s2); cout <<s1<<endl; // example strcnpy(s1, s3, 2); cout <<s1<<endl; // roample Слід зазначити, що саме функція strcpy використовується для ініціалізації рядка-змінної у С/С++.
  • 13. Об'єднання рядків. Над рядковими змінними означена операція об'єднання (конкатенації), яка дозволяє дописати один рядок в кінець іншого. Під час об'єднання рядків поточна довжина рядка, до якого приєднується інший рядок, збільшується на довжину рядка, що додається. Збільшення довжини об'єднаного рядка здійснюється тільки у заданих під час оголошення межах. У деяких мовах програмування об'єднання рядків здійснюється за допомогою вбудованих операцій, у інших – за допомогою стандартних функцій. Так у табл. 2 наведено основні функції об'єднання рядків, передбачені у С/С++. Таблиця 2. Перелік основних функцій об'єднання рядків у С/С++ Прототип функції Опис char *strcat(char *str1, char *str2); Приєднує рядок str2 в кінець рядка str1 char *strncat(char *str1, char *str2, size_t n); Приєднує n перших символів рядка str2 в кінець рядка str1 Наприклад, char s1[30] ="example", s2[ ] =" of concatenation", s3[ ] ="rows "; strcat(s1, s2); cout << s1 << endl; // example of concatenation strcat(s1, s3, 4); cout << s1 << endl; // example of concatenation row
  • 14. Порівняння рядків. Порівняння рядків виконується як серія послідовних порівнянь символів рядків, що мають однакові індекси, починаючи з першого. Порівняння здійснюється до першого незбіжного символу, і той рядок вважається більшим, у якому перший незбіжний символ має більше значення. Наприклад, "рядок1" < "рядок2" . Якщо рядки мають різну довжину, але в загальній частині символи збігаються, то вважається, що коротший рядок менше більш довгого. Наприклад, "курс" < "курси". У деяких мовах програмування (наприклад, у Pascal) для порівняння рядків означено операції порівняння “<“, “=“, “>“. У С/С++ різні варіанти порівняння рядків реалізуються за допомогою стандартних функцій (табл. 3). Таблиця 3. Перелік основних функцій порівняння рядків у С/С++ Прототип функції Опис int strcmp(char *str1, char *str2); Порівнює рядки str1 і str2 int stricmp(char *str1, char *str2); Порівнює рядки str1 і str2 без урахування регістра int strncmp(char *str1, char *str2, size_t n); Порівнює перші n символів рядків str1 і str2 int strnicmp(char *str1, char *str2, size_t n); Порівнює перші n символів рядків str1 і str2 без урахування регістра
  • 15. Дані функції повертають значення 0, якщо рядки однакові (з урахуванням або без урахування регістра). Якщо рядок str1 лексикографічно (тобто відповідно до алфавітного порядку) більший від рядка str2, то повертається додатне число; якщо ж менший від рядка str2 - то повертається від’ємне число. Наприклад, int r; char s1[20], s2[10]= "example"; cin >>s1; // example r = strcmp(s1, s2); cout <<r <<endl; // 0 cin >>s1; // row r = strcmp(s1, s2); cout <<r <<endl; // 13 cin >>s1; // concatenation r = strcmp(s1, s2); cout <<r <<endl; // -2 Оскільки значення 0, що повертається даними функціями у випадку рівності порівнюваних рядків, відповідає логічному значенню false, то при перевірці рівності рядків рекомендується використовувати логічну операцію НЕ ("!"), щоб інвертувати умову (тобто змінити її на зворотню). Наприклад, if (! strcmp(s1, s2)) cout << "Рядки однакові" << endl; else cout << "Рядки не однакові" << endl;
  • 16. Прототип функції Опис int islower( int ch); Перевіряє приналежність аргумента ch до рядкових літер int isalnum( int ch); Перевіряє приналежність аргумента ch до алфавітно- цифрових символів int isalpha( int ch); Перевіряє приналежність аргумента ch до літер int isupper( int ch); Перевіряє приналежність аргумента ch до прописних літер int isdigit( int ch); Перевіряє приналежність аргумента ch до цифрових символів int ispunct( int ch); Перевіряє приналежність аргумента ch до знаківпунктуації int isspace( int ch); Перевіряє, чи є аргумент ch пробілом Аналіз символів рядка. Іноді у програмах виникає необхідність у перевірці приналежності симолів до певної класифікаційної групи: літера, цифра, знак пунктуації тощо. Для цього у С/С++ передбачено ряд стандартних функцій (табл. 4). Таблиця 4. Перелік основних функцій С/С++ для аналізу символів
  • 17. Якщо символ належить до відповідної класифікаційної групи, то відповідна повертає ненульове значення, інакше – 0. Наприклад, for (int i= 1; i<= strlen(s1); i++) if (isdigit(s1[i])) cout<<"Element "<<s[ i]<<" -digit"<<endl; Пошук у рядку. Часто у програмах доводиться виконувати пошук у рядках окремих символів або підрядків. Деякі мови програмування мають незначні можливості виконання такого пошуку, інші – значно більші. Так у С/С++ передбачені наступні можливості пошуку у рядках: •пошук символів; •пошук підрядків; •пошук лексем. Пошук окремих символів підтримується функціями, наведеними у табл. 5. Таблиця 5. Перелік основних функцій С/С++ для пошуку символів у рядках Прототип функції Опис char *strchr(char *str, int ch); Шукає перше входження символа сh у рядок str char *strrchr(char *str, int ch); Шукає останнє входження символа сh у рядок str char *strpbrk(char *str1, char *str2); Шукає першевходження будь-якого символу з рядка str2 у рядок str1
  • 18. Наприклад, if (strchr(filename, '.')) cout << "Ім'я вже містить розширення" << endl; else strcat(filename, ".TXT"); Вираз strchr( filename , ' .' ) повертає покажчик на символ точки в рядку, що адресується покажчиком filename. Якщо такий символ не знайдений, функція strchr повертає NULL. Оскільки ненульові значення означають "істину", то можна використовувати функцію strchr як таку, що повертає значення "істина" / "хибність". Прототип функції Опис char *strstr(char *str1, char *str2); Шукає перше входження підрядка str2 у рядок str1 size_t strcspn(char *str1, char *str2); Визначає довжину початкового інтервалу рядка str1, що не містить символів з рядка str2; тобто, повертає індекс першого символу рядка str1, який збігається з будь-яким із символів в рядку str2 size_t strspn(char *str1, char *str2); Визначає довжину початкового інтервалу рядка str1, що містить символи з рядка str2 Окрім пошуку символів в рядку, можна також організувати пошук і підрядків вказаного рядка. Для цього ц С/С++ служать функції, наведені у табл. 6. Таблиця 6. Перелік основних функцій С/С++ для пошуку підрядків у рядках
  • 19. Наприклад, p = strstr(filename, ".txt"); if (p) cout << " Ім'я вже містить потрібне розширення" << endl; else { p = strchr(filename, '.'); if (p) *p= NULL; //видалити будь-яке інше розширення strcat(filename, ".txt"); } Цей фрагмент програми створює ім'я файлу, яке обов'язково закінчується розширенням .txt. Щоб визначити, чи є в імені файлу це розширення, програма виконує оператор p = strstr( filename, ".txt" ) ; Подібно strchr, функція strstr повертає адресу підрядка або NULL, якщо шуканий рядок не знайдений. Якщо заданий підрядок знайдений​​, покажчик p стане рівним його адресі, в даному прикладі - адресі точки (".") в підрядку ". txt". Даний приклад також демонструє спосіб відсікання рядка в позиції заданого символа або підрядка. Якщо при виклику функції strstr результат пошуку першої точки в рядку filename не нульовий, то виконається оператор, який запише замість точки нуль-символ: *p = NULL ; //або *р=’0’ Тим самим буде приєднано новий кінець рядка в тому місці, де раніше знаходилося розширення файлу. Тепер рядок готовий до додавання нового розширення шляхом виклику функції strcat.
  • 20. Перетворення рядків. Мови програмування підтримують різні варіанти перетворення рядків. Так у Pascal можна видаляти заданий підрядок із рядка або вставляти його у рядок, перетворювати малі літери у прописні, а також перетворювати числові значення в рядкові і навпаки. У С/С++ можливості перетворення рядків значно ширші. Перелік основних із них наведений у табл. 7. Таблиця 7. Перелік основних функції перетворення рядків у С/С++ Прототип функції Опис char *strlwr(char *str); Приводить символи рядка до нижнього регістра char *strupr(char *str); Приводить символи рядка до верхнього регістра char *strset(char *str, int ch); Замінює всі символи рядка на символ сh char *strnset(char *str, int ch, size_t n); Замінює перші n символів у рядку на символ сh char *strrev(char *str); Інвертує рядок
  • 21. Наприклад, strcpy(str, "this is a test"); strupr(str); cout << str << endl; // THIS IS A TEST strnset(str, “-“, 9); cout << str << endl; // --------- TEST strrev(str); cout << str << endl; // TSET --------- До функцій перетворення рядків також відносять функції, які дозволяють здійснювати перетворення рядка у відповідне числове значення (наведені у табл. 8). Таблиця 8. Перелік основних функції перетворення рядків і чисел у С/С++ Прототип функції Опис double atof(const char *str); Перетворює рядок str в число з плаваючою крапкою типу double; якщо рядок str не є коректним текстовим поданням числа double, то повертається NULL (заголовний файл - math.h) double strtod ( const char *str, char **endptr ); Перетворює рядок str в значення типу double; параметр endptr встановлюється так, щоб вказувати на "невикористаний" залишок початкового рядка, якщо такий існує (заголовний файл - stdlib.h) int atoi(const char *str); Перетворює рядок str в число типуint (заголовний файл - stdlib.h) long atol(const char *str); Перетворює рядок str в число типуlong (заголовний файл - stdlib.h)
  • 22. Наприклад, char str []= “10.4e-1”, *ptr; double d = atof(str); cout << d <<endl; // 1.04 double d = strtod(str, &ptr); cout << d <<endl; // 1.04 int n = atoi(str); cout << n <<endl; // 10 Після числа у рядку перетворення може слідувати будь-який символ, який не може бути частиною допустимого числа з плаваючою крапкою - пробіли, символи табуляції і порожнього рядка, розділові знаки (але не точки) і символи, відмінні від літер "Е" або "е". Це означає, що, якщо функція atof або функція strtod викликаються з аргументом "10.4е-1 HELLO", то все рівно буде повернуто значення 1.04. Різниця між цими функціями полягає у тому, що функція strtod має параметр-покажчик (endptr), який встановлюється так, щоб вказувати на "невикористаний" залишок початкового рядка, якщо такий існує. Це означає, що для попередгього прикладу функція strtod поверне значення 1.04, а параметр-покажчик endptr буде вказувати на пробіл, який передує слову "HELLO". Наприклад, наступна програма читає числа з плаваючою точкою з текстового рядка:
  • 23. #include <stdlib.h> #include <ctype.h> #include <stdio.h> int main(void) { char *end, *start = "100.00 notebooks 200.00 pencils"; end = start; while(*start) { printf("%f, ", strtod(start, &end)); printf("Rest of the line: %sn", end); start = end; while(!isdigit(*start) && *start) start++; // пропускає символи, що не входять в числа } system("pause"); } Ось що виводить ця програма:
  • 24. Мови програмування також підтримують функції перетворення числових значень в рядкові. Основні такі функції мови С/С++ наведені у табл. 9. Таблиця 9. Перелік основних функції перетворення рядків і чисел у С/С++ Прототип функції Опис char *itoa(int value, char *str, int radix); Перетворює значення цілого типу value в рядок str з урахуванням зазначеної системи числення radix char *gcvt(double value, int ndig, char *buf); Перетворює число з плаваючою крапкою value типуdouble в рядок довжиною ndig цифр, який адресується аргументом buf. Спосіб подання вибирається функцією (звичайний або експонентний). char *ecvt(double value, int ndig, int *dec, int *sign); Перетворює число з плаваючою точкою value типу doubleв символьний рядок довжиною ndig цифр і повертає адресний покажчик отриманого рядка. Якщо кількість цифр в value перевищує ndig, остання значуща цифра округлюється, якщо цифр менше, ніж ndig, - рядок доповнюється нулями.Результуючий рядок не містить символу десяткової точки - позиція десяткової точки щодо початку рядка непрямим чином зберігається в параметрі dec (від'ємне значення decозначає, що десяткова точка розміщена лівіше першої цифри на dec позицій, додатне – правіше першої цифри на dec позицій).Аргумент sign вказує на ціле, що визначає знак перетворюваного числа (якщо sign дорівнює 0, то число додатне, інакше - від'ємне).
  • 25. Наприклад, char result[17]; int value=23677; itoa(value, result, 10); cout << "10:" << result << endl; // 23677 itoa(value, result, 16); cout << "16:" << result << endl; // 5c7d itoa(value, result, 2); cout << "2:" << result << endl; // 101110001111101 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = int dec, sign; char *buffer; int precision=10; buffer= ecvt(314.15926535, precision, &dec, &sign); cout << buffer << endl; // рядок -"3141592654", dec=3, sign=0 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = char buffer[50]; int precision = 7; gcvt (-3.1415e3, precision, buffer); cout << buffer << endl; // -3141.5
  • 26. Параметри-рядки При вирішенні практичних задач часто потрібно використовувати рядок як параметр функції. Крім того, функції можуть повертати покажчик на рядок в якості результату. Розглянемо реалізацію цих можливостей у мовах програмування. Передача символьного рядка у функцію подібна до передачі будь-якого масиву як параметру. У С/С++ таких способів декілька: • як масиву символів, наприклад, void showText1(char str []); • за допомогою покажчика, наприклад, void showText2(char *str); • за посиланням, наприклад, void showText3(char (&str)[150]). При передачі рядка як масиву символів не треба вказувати розмірність масиву (кількість символів у рядку). За допомогою символу '0', який автоматично додається в кінець будь-якого рядка, функція сама знайде останній елемент масиву. При передачі рядка за посиланням необхідно вказувати точний розмір рядка - без цього компілятор може видати помилку.
  • 27. Приклад. void showText1(char str[]) //функція приймає рядок як масив { cout << str << endl; } void showText2(char *str) //покажчик на адресу першого символа в рядку { cout << str << endl; } void showText3(char (&str)[150]) // адреса рядка із 150-ти символів { cout << str << endl; } int main() { char str1[] = "str1 - pass as an array"; showText1(str1); cout << endl; char str2[] = "str2 - pass using the pointer"; showText2(str2); cout << endl; char str3[150] = "str3 - pass using the address line"; showText3(str3); cout << endl; system("pause"); }
  • 28. Масиви рядків Текст, що обробляється програмою, може розглядатися як масив рядків. У такому використанні немає нічого незвичайного. Наприклад, при програмуванні баз даних для з'ясування коректності команд, що вводяться користувачем, вхідні дані порівнюються з вмістом масиву рядків, у якому записано допустимі у цьому додатку команди. Для побудови масиву рядків може використовуватися двовимірний символьний масив, у якому розмір лівого індексу визначає кількість рядків, а розмір правого – максимальну довжину кожного рядка. Наприклад, char strArray[20][80] – оголошення масиву, призначеного для зберігання 20 рядків завдовжки 80 символів. Отримати доступ до окремого рядка такого масиву достатньо просто: достатньо вказати тільки лівий індекс. Наприклад, виклик функції gets для запису третього рядка описаного вище масиву: gets(strArray[2]); Щоб краще зрозуміти, як потрібно поводитися з масивами рядків, розглянемо фрагмент програми, яка приймає рядки тексту, що вводяться з клавіатури, і відображає їх на екрані після введення порожнього рядка. int t, i; char text[100][80]; for(t=0; t<100; t++) { cout << t << ": "; gets(text[t]); if(!text[t][0]) break; // вихід з циклу за порожнім рядком } for(i=0; i<t; i++) // відображення рядків на екрані cout << text[i] << endl;
  • 29. Обробка stl-рядків Як уже зазначалося, у С++ рядки можна розглядати як об’єкти шаблонного класу string, описаного в стандартній бібліотеці шаблонів STL (Standard Template Library). Тому такі рядки ще називають STL-рядками. Щоб використовувати рядки класу string, треба підключити до програми заголовний файл <string>: #include <string>. Обробка STL-рядків має певну специфіку. Зокрема, STL-рядкам можна присвоювати значення, як і змінним будь-яких інших типів: string name; // створення рядка name name = “Row”; // присвоєння значення рядковій змінній name Введення або виведення STL-рядків виконується застосуванням перевантажених для рядків операцій потокового введення та виведення (”<<” і ”>>”). Наприклад, string s; cin >> s; cout << s << endl; Однак слід пам’ятати, що таким способом рядки вводяться тільки до першого роздільного символу (пробілу, кінця рядка, символу табуляції). Для введення рядка-речення слід скористатися функцією getline класу string: string s; // створення рядка s getline(cin, s); // читання введеного з клавіатури рядка cout << s<<endl; // одержання довжини рядка
  • 30. STL-рядки можна лексикографічно порівнювати між собою, користуючись звичайними операціями порівняння (”= =”, ”>” і т.ін.): if (str == “Hello”) cout << str << endl; Для string-об'єктів визначена також операція додавання (”+” ), тобто можна написати s1 + s2 і результатом цієї операції буде конкатенація (об’єднання) рядків: рядок s2 буде дописаний в кінець рядка s1. Наприклад, string str(“Hello”); string r = str + ‘ ’ + “world”; //конкатенація трьох рядків r += ‘!’; //r = “Hello world!” Основна функціональність STL-рядків реалізується через методи класу string. Методом в ООП називають функцію, яка застосовується до об'єкта вказаного класу, наприклад, рядка. При виклику метода його ім'я пишеться після ідентифікатора об'єкта через крапку. Наприклад, у об'єкта типу string є метод length, який повертає довжину рядка. Якщо str - це рядок, то метод викликається так: str.length(). Даний клас дозволяє досить ефективно і легко вирішувати наступні задачі: •створювати, присвоювати, копіювати і видаляти рядки; •виконувати перетворення типів символьних змінних; •порівнювати рядки; •поєднувати рядки; •визначати довжину рядка; •знаходити і заміщати потрібний фрагмент у рядку. Перелік деяких методів обробки string-рядків наведений у табл. 10
  • 31. Таблиця 10. Перелік основних методів обробки STL-рядків Назва Опис empty перевіріє, чи є рядок порожнім (якщо рядок порожній, повертає true) erase видаляє символ або декілька символів з рядка find шукає підрядок в рядку; insert вставляє підрядоку рядок length повертає довжину рядка replace видаляє підрядок substr виділяє підрядок рядка swap обмінює вмісти двох рядків
  • 32. Наприклад, string str1(“Hello”); string str2=“greetings”; if (str1.empty()) cout << "String is empty" << "n"; else cout << "String isn't empty" << "n"; cout << str1.length(); //повертає 5 (довжину рядка str1) cout << str2.find(“ее”); //повертає 2 (позицію самого лівого входження “ее”) string s(“Testing!”); cout << s.substr(2, 5); // “sting” cout << s[3]; // ‘t’ s.replace(2, 2,”eth”); // s == “Teething!” s.erase(1, 4); // s == “Ting!” s[1] = ‘a’; // s == “Tang!” s.insert(1,”w”); // s == “Twang!” Також існує багато варіацій цих методів (табл. 11).
  • 33. Таблиця 11. Перелік варіацій деяких методів обробки STL-рядків Прототип Опис unsigned int find (string substr); шукає підрядок substr в рядку; повертає індекс, з якого починається перше входження підрядка в рядок unsigned int findC(string substr, unsigned int from); шукає підрядок substr в рядку, починаючи з позиції from unsigned int find_first_of (string substr); шукає перше входження будь-якого символа ізsubstrврядку unsigned int find_first_not_of(string substr); шукаєперший символ врядку, який не входить в substr unsigned int find_ last _of (string substr); шукає останнє входження будь-якого символа із substrврядку unsigned int find_last_not_of(string substr); шукаєостанній символ врядку, який не входить в substr unsigned int rfind(string substr); шукає останнє входження підрядка substr в рядок; повертає індекс, з якого починається останнє входження підрядка в рядок unsigned int rfindC(string substr, unsigned int from); шукає останній підрядок substr в рядку, індекс початку якого менше from string substr(unsigned int n); або виділяє підрядок, що містить перші n символів рядка string substr(unsigned int k, unsigned int n); виділяє підрядок, що містить перші n символів рядка, починаючи з k-го
  • 34. Наприклад, string str(“Hello, World!”); cout << str.rfind(‘o’); //виконує пошук з кінця (повертає 8) int index = str.find_first_of(", !"); // пошук першого пробілу, знаку оклику або коми Для позначення того, що шукана послідовність символів не знайдена, багато методів (наприклад, find) повертають спеціальну константу npos, яка означає «не знайдено» або «всі символи, що залишилися». Наприклад, string str(“Hello”); cout << str.find(“x”) // повертає string::npos Для того, щоб використовувати все розмаїття методів обробки STL-рядків, під рукою повинна бути відповідна документація. Microsoft пропонує досить докладну документацію, як частину MSDN для своєї реалізації STL. Хоча значна частина функціональності роботи з рядками реалізована в бібліотеці <string.h> (функції strcmp, strcat, strcpy, strlen та ін.), але використання string-об'єктів часто буває зручнішим. Для роботи з рядками передбачений шаблонний клас basic_string з якого визначається клас string: typedef basic_string <char> string; Клас string відрізняється від vector<char> функціями для маніпулювання рядками й політикою роботи з пам'яттю. Для визначення довжини рядка, використовується string: length(), а не vector::size().
  • 35. Розглянемо приклад роботи з рядками. string sl = "слово"; string s1 = sl.substr(0, 3), // "сло" s2 = sl.substr(1, 3), // "лов" s3 = sl.substr(0, s.length()-1), //"слов" s4 = sl.substr(1), // "лово" s = "Завтра - термін здачі лабораторної !"; // пошук першого пробілу int ind1 = s.find_first_of(' '); // пошук першого пробілу, знаків ! або - int ind2 = s.find_first_of(" -!"); Також рядки можна додавати за допомогою оperator+, порівнювати за допомогою операторів порівняння. Таким чином, vector<string> можна впорядковувати стандартними методами. Рядки порівнюються в лексикографічному порядку •string- представляет из себя коллекцию, хранящую символы char в формате ASCII. Для того, чтобы использовать данную коллекцию, вам необходимо включить #include <string>. •wstring- это коллекция для хранения двухбайтных символов wchar_t, которые используются для представления всего набора символов в формате Unicode. Для того, чтобы использовать данную коллекцию, вам необходимо включить #include <xstring>.
  • 36. int string_length(char []); void main(void) { char title[] = " Learning to program in C++"; char lesson[] = "Сharacter strings"; cout << " String " << title << " contains " << string_length(title) << " characters" << endl; cout << " String " << lesson << " contains " << string_length(lesson) << " characters" << endl; } int string_length(char string[]) { int i; for (i = 0; string[і] != '0'; i++); return i; } 24