3 Робота з рядками
3.1 Мета роботи
Отримати практичні навички програмування на С++ задач, де використовується символьна інформація.
3.2 Методичні вказівки до організації самостійної роботи студентів
У мові С++ є кілька можливостей роботи з символьними даними. Класична робота зводиться до використання масива символів. Для того, щоб скористуватися стандартними функціями С++ для роботи з рядками, треба їх файли підключити в директиві #include <string.h>. Основні функції з цього пакету наведено нижче.
— char*strcat (char*_dest, const char*_src); — функція реалізує сціплення рядка dest з рядком src. Функція вертає покажчик на початок отриманого рядка (dest). Проміжний символ‘\0’ рядка dest гаситься.
— char*strncat (char*_dest, const char*_src, size_t_maxlen); — функція приєднує maxlen символів з рядка, на який вказує src, до рядка, на який вказує dest. Рядок dest повинен містити не менше maxlen вільних байтів. Якщо maxlen більше рядка src, виконується проста конкатенація.
— char*strchr (const char*_, int_c); — функція вертає покажчик на позицію першого входження символу “c” в рядок, на який вказує s. В рядок s включається і символ ‘\0’.
— int strcmp (const char*_s1, const char*_s2); — функція виконує порівняння двох рядків, на початок яких вказують s1 і s2. Функція вертає значення: менш нуля, якщо s1<s2; рівне нулю, якщо s1==s2; більше нуля, якщо s1>s2.
— int strnсmp (const char*_s1, const char*_s2, size_t_maxlen); — функція, що аналогічна функції strcmp () і відрізняється тим, що виконується порівняння перших maxlen байтів.
— int stricmp (const char *_s1, const char *_s2); — функція виконує порівняння двох рядків, на що вказують s1 і s2. Перед порівнянням символи перетворюються в малі. Функція вертає значення: більше нуля, якщо s1>s2; рівно нулю, якщо s1==s2; менш нуля, якщо s1<s2.
— int strlen (const char*_s); — функція вертає довжину рядка в байтах, на який вказує s. Нуль-терминатор не враховується.
— char*stpcpy (char *_dest, const char *_src); —функція копіює рядок, на котрий вказує src, в інше місце в пам'яті, на що вказує est. Функція вертає покажчик на кінець рядка, що скопіювався в dest.
— char*strncpy (char*_dest, const char*_src, size_t_maxlen); — функція копіює maxlen байт з рядка, на який вказує src, в інше місце в пам'яті, на що вказує dest. Нуль-термінатор теж копіюється. Якщо maxlen менш довжини рядка src, до рядка src не приєднується символ“\0”. І якщо більше, то рядок src переноситься повністю, а символи, що залишалися, заповнюються символом “\0”. Функція вертає покажчик dest.
— char *strlwr (char *_s); —функція перетворює всі символи рядка, на початок якого вказує s, в малі літери. Функція повертає покажчик на початок цього рядка.
— char *strups (char *_s); —функція перетворює всі символи рядка, на початок якої вказує s, в великі літери. Функція вертає покажчик на отриманий рядок.
— char *strset (char *_s, int_ch); — функція заповнює рядок, на початок якого вказує s, символом ch. Функція вертає покажчик на отриманий рядок.
— char *strtok (char *_s1, char *_s2); — функція вертає наступну лексему із s1, яка відділена любим символом з набора s2.
Функції для роботи з рядками
Заголовковий файл <string.h>
strlen(s) |
кількість елементів у рядку |
застосовується у виразах |
strcat(s1,s2) |
з'єднання рядків |
результат присвоює змінній s1 |
strncat(s1,s2,n) |
до змінної s1 додає перших n символів рядка s2 |
команда |
strcmp(s1,s2) |
Порівнює рядки. Повертає 0, якщо рядки рівні, число мене від нуля, якщо s1<s2 і число більше від нуля, якщо s1>s2 |
застосовується у виразах |
strcpy(s1,s2) |
копіює символи з рядка s2 в рядок s1 |
команда |
strncpy(s1,s2,n) |
копіює перших n символів рядка s2 в рядок s1 |
команда |
strchr(s1,’a’) |
визначає перше входження символу у рядок s1 так: повертає рядок, який починається від першого входження заданого символу до кінця рядка s1 |
застосовується у виразах |
strrchr(s1,’a’) |
визначає останнє входження символу у рядок s1 |
застосовується у виразах |
strspn(s1,s2) |
Визначає номер першого символу, який входить у рядок s1, але не входить у рядок s2 |
застосовується у виразах |
strtok(s1,s2) |
визначає частину рядка s1, яка закінчується перед першим однаковим символом рядків s1 та s2 |
застосовується у виразах |
strset(s1,’a’, n) |
вставляє n разів заданий символ перед рядком s1 |
застосовується у виразах |
strupr(s1) |
перетворює усі малі літери рядка у великі |
команда |
strlwr(s1) |
перетворює усі великі літери рядка у малі |
команда |
strrev(s1) |
записує рядок у зворотному порядку |
команда |
Приклади
char lviv[]=“Львівська політехніка”; un[30]=“НУ ”; r1[30]=“”; char *p; int n;
Застосування функцій |
Результат |
n=strlen(lviv); |
n=21 |
strcat(un, lviv); |
un=”НУ Львівська політехніка” |
strcat(un, lviv, 10); |
un=”НУ Львівська” |
strcpy(r1, lviv); |
r1=”Львівська політехніка” |
strcpy(r1, lviv, 10); |
r1=”Львівська” |
p=strchr(lviv, ‘п’); |
p=”політехніка” |
p=strchr(lviv, ‘i’); |
p=”іка” |
n=strspn(lviv, ”Львів”); |
n=5 |
p=strstr(lviv, ‘тех’); |
p=”техніка” |
p=strtok(lviv, ‘сь’); |
p=”Львів” |
p=strnset(lviv, ‘x’, 10); |
p=”xxxxxxxxxx техніка” |
p=srtupr(‘I love you’); |
p=’I LOVE YOU’ |
p=srtlwr(‘I Love You’); |
P=’i love you’ |
p= strrev(‘техніка’) |
p=’акінхет’ |
Приклад 3.1
Підрахувати кількість слів у рядку, враховуючи те, що пробілів, а також інших розділових знаків між словами може бути скількі завгодно.
1-ий варіант вирішення поставленої задачі
#include <iostream>
#include <conio.h>
#include <string.h>
int main()
{
char s[]=" Repetitio est , mater studiorum !";
int i=0, col=0;
char spes[]=" ;!,.?\t";
int strLen = strlen(s);
while (i<strLen)
{
if ( !strchr(spes, s[i]) )
{
col++;
while (!strchr(spes, s[i]) && i<strLen)
i++;
}
else
{
while (strchr(spes, s[i]) && i<strLen)
i++;
}
}
std::cout<<"\nKilkist sliv="<<col<<'\n';
getch();//задержка экрана
return 0;
}
2-ий варіант вирішення поставленої задачі з використанням функції strtok
#include <iostream>
#include <conio.h>
#include <string.h>
int main()
{
int col=0;
char str[] = "Repetitio est mater studiorum. Help.";
char seps[] = " ;,\t\n";//знаки препинания
std::cout<<str<<std::endl;
char *token = strtok(str, seps);//поиск первого слова
while( token != NULL )
{
col++;
token = strtok(NULL, seps );//поиск следующего слова
}
std::cout<<"\nKilkist sliv="<<col<<std::endl;
getch();//задержка экрана
return 0;
}
Приклад 3.2
Знайти в тексті всі слова, що починаються та закінчуються буквою a, та скопіювати їх в нову рядок через пробіл. Під новий рядок необхідно виділити рівно стільки пам’яті, скільки необхідно для запису знайдений слів.
Розв’язок. Поставлено задачу вирішимо у два етапи: спочатку підрахуємо кількість необхідної пам’яті, а за тим запишемо у новий рядок необхідні слова.
#include <iostream>
#include <conio.h>
#include <string.h>
int main()
{
char str[] = "test word 1: asdda. Test word 2: asdfg, word 3: Awea";
char strCopy[sizeof(str)];
strcpy(strCopy,str);//створюємо копію рядка
char seps[] = " :?!;,.\t\n";//знаки препинания
std::cout<<str<<std::endl;
char *token = strtok(str, seps);//пошук першого слова
int lenResult=0;
int countWord=0; //кількість слів
//Підрахуємо кількість необхідної пам'яты для рядка-результата
while( token != NULL )
{
int last = strlen(token)-1;
if (
(token[0] == 'a' || token[0] == 'A')
&& (token[last] == 'a' || token[last] == 'A')
)
{
lenResult+= strlen(token)+1;
++countWord;
}
token = strtok(NULL, seps );//пошук наступного слова
}
char* resString = new char [lenResult];
resString[0]='\0'; //створюєму пустий рядок
strcpy(str,strCopy);//відновлюємо рядок
token = strtok(str, seps);//пошук першого слова
int curentNumberWord=0;
while( token != NULL )
{
int last = strlen(token)-1;
if (
(token[0] == 'a' || token[0] == 'A')
&& (token[last] == 'a' || token[last] == 'A')
)
{
strcat(resString,token);
++curentNumberWord;
if (countWord!=curentNumberWord)//Якщо не останнє слово
{
strcat(resString," ");
}
}
token = strtok(NULL, seps );//пошук наступного слова
}
std::cout<<"\nResult:\n"<<resString<<std::endl;
delete[]resString;
getch();//задержка экрана
return 0;
}