Device . Put (char_var); , 4 страница
У мові Сі і ранніх версіях мови С++ рядки розглядалися як символьні масиви і вся робота з ними ґрунтувалася на використанні цих масивів. Розроблена бібліотека функцій <string.h> містить могутні засоби для роботи зі строковими масивами .
Для опису рядка використовуються звичайні засоби опису масивів, наприклад: char str [25];. Індексування такого масиву, як і будь-якого іншого, починається з нуля. Символьні послідовності, розділені тільки проміжками, розглядаються як один рядок, тобто запис:
" У той рік осіння
погода"
ідентична рядку " У той рік осіння погода".
Усі рядки, у тому числі й ідентичні, у програмі розглядаються як різні об'єкти. Адреса першого символу рядка може використовуватися по-різному:
¾ якщо рядок застосовується при ініціалізації масиву типу char, адреса його першого елемента стає синонімом імені масиву. Наприклад, ідентичними є наступні описи масиву:
char st [] = "Слово";
char st [6] = "Слово";
char st [6] = {'С' 'л' 'о' 'в' 'о' '\0'};
¾ якщо рядок використовується для ініціалізації покажчика типу char*, адреса першого символу рядка буде початковим значенням покажчика, наприклад:
char *pst = "Слово"; ,
тут описується змінна - покажчик pst , що одержує початкове значення, рівне адресі першого елемента (символ С);
¾ якщо рядок використовується у виразі (там, де дозволяється застосовувати покажчик), то компілятор підставляє у вираз рядка адресу його першого символу, наприклад:
char *pst;
pst = " Перший символ"; ,
тут pst ¾ одержує адресу букви "П", тобто при виконанні операції присвоювання в комірку пам'яті, відведену для покажчика pst, записується не масив символів, а тільки покажчик на його початок, тобто адреса першого символу рядка.
При описі символьного масиву, його ім'я ¾ не змінна, а покажчик-константа на початок рядка. Оскільки для константи не приділяється адреса в пам'яті, то її не можна використовувати в деяких операціях адресної арифметики, наприклад, не можна здійснювати операцію присвоювання вигляду:
char st [20];
st = " Петров"; // запис невірний, тому що не можна змінити значення st
Використання елементів масиву здійснюється через індекси або через покажчики. Для доступу до будь-якого символу рядка використовується індекс масиву char, наприклад, якщо описана змінна char str[3], то третім елементом масиву можна скористатися, записавши: str[3]або *(str+3).
При роботі з елементами масивів рядків, тобто двовимірним масивом, варто використовувати або індекси масиву, або індекси покажчиків, наприклад, якщо описаний список прізвищ
char spis [5] [15];,
то для використання символу масиву варто записати:
spis [i] [j]або*(spis [i] + j).
Аналогічно при оголошенні масивів покажчиків char *str [5](указує на 5 елементів, кожний з який указує на рядок), а доступ до символу рядка можна здійснити, записавши *(str [i]+j).
3.2.3 Введення-виведення символьних масивів
Рядки можна вводити різними способами, найбільш розповсюдженими з яких є:
¾ введення шляхом ініціалізації при оголошенні строкових масивів:
char st [5] = " Стіл";
char st [] = " Стіл";
char *pst = " Стіл";
у цьому випадку двовимірні масиви можна ініціалізувати одним з наступних засобів:
char str [5] [20] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,};
char str [ ] [20] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,};
char *pst [5] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,};
char *pst [ ] = {"Іванов И.И. ", "Сидоров С.С. ", . . . ,};
¾ введення за допомогою оператора cin >> , якщо в рядку немає проміжків, тому що символ проміжок є роздільником вводу даних, наприклад:
char st [5]; cin >> st;
char *pst; cin >> *pst
char str [5] [20]; cin >> str [i];
char *pst [5]; cin >> ( pst [i] );
¾ посимвольне уведення за допомогою функції get( ), наприклад get(st[i]);
¾ за допомогою функції cin.get (str [i], size, endl) ; ,
де size - кількість символів, що читаються;
¾ уведення за допомогою функції cin.getline ( str [i], sizeof ( str [i] ) ); ,
де sizeof( ) - функція визначення розміру рядка.
Виводити строкові дані можна використовуючи наступні записи:
cout << st;
printf ( “% s”,st ); // або ( sprintf)
puts ( st ); cout . write ( st , size );і ін.
Приклад 3.3Список рядків ( прізвища і ініціали ¾ Ф.И.О.) оголошений як масив покажчиків. Скласти програму , що реалізує введення масиву по рядках і посимвольне виведення цього масиву.
// P3_3.СРР—список рядків оголошений як масив покажчиків
#include <stdio.h>
Void main (void)
{
char *psp[ ] = { "Авдєєв А.А.'',
"Петров П.П.",
"Лисиця Л.Л. ",
NULL };
char **ptr =psp;
//Виведення масиву по рядках
while (*ptr)
puts (*ptr++);
ptr=psp;
//Виведення цього масиву посимвольне
while (*ptr)
{
while (**ptr)
{ putchar(**ptr); (*ptr)++; }
ptr++
}
}
Під час використання заголовного файлу stdio.h можна також застосувати, наприклад, такі функції:
для введення рядків для виведення рядків
puts(st) ;іprintf(%s, st);
Gets( st); cout.width(w);
scanf (“% s”,st) ; cout.precision (d);
Setw(w);
Setprecision(d);
3.2.4 Основні функції обробки символьних типів
У ранніх версіях С++ рядки розглядалися як символьні масиви і робота з ними ґрунтувалася на використанні цих масивів. Розроблена бібліотека функцій <string.h> містить могутні засоби для роботи зі строковими масивами. Згодом була розроблена стандартна бібліотека шаблонів Standard Template Library (STL) , що надає ще більш могутні засоби роботи з рядками, об'єднані в клас string. Цей клас включається як заголовний файл , тобто:
#include <string>// без літери h
Для обробки символьних типів даних бібліотека функцій <string.h> має велику кількість вбудованих функцій, що збільшують продуктивність праці програмістів і скорочують час на розробку програм. Ця бібліотека містить такі функції, як наприклад:
функції перевірки символів;
функції перетворення символів;
функції перевірки рядків;
функції маніпулювання рядками.
Усі ці функції приводяться у вигляді списків, згрупованих по їх розташуванню в заголовних файлах. Найчастіше приводяться прототипи функцій, що описують, яким образом використовувати функції в програмах.
Розглянемо прототипи, короткий опис дій і методику використання функцій, які частіше використовуються:
¾ Копіювання рядків
char strcpy (s, *st); ¾ копіює байти рядка st у рядок s, (включаючи "\0"; повертає s),наприклад:
char str [50];
strcpy (str, "Сьогодні гарна погода ");
char *strdup (const char *str); ¾ копіює рядок strі повертає
покажчикна рядок – копію, наприклад:
char *st1 = " Прийшла весна";
char *st2;
st2= strdup (st1); // Копіюється st1 у st2
char * strnсpy (char *st1,const char *st2, int n); ¾ копіює n символів з рядка st2у st1,рядок st1 повинний бути більше чи дорівнювати st2, інакше виникне помилка, наприклад:
char st1[]= "Паскаль ";
char st2[] = "Привіт з далека ";
strnсpy (st1,st2,3);// Тепер у st1¾ "Прикаль"
¾ Конкатенація слів
char *strcat (char *st1, const char *st2); ¾ поєднує st1і st2і повертає st1,наприклад:
char string [100];
strcpy (string, "Borland ");
strcat (string, " C++5"); ,
получаємо рядок string = "Borland C++ 5" ;
char *strncat (char *st1, const char * st2, int n);¾ додає до рядка st1 n символів рядка st2і повертає в st1, наприклад :
сhаr st1 [90] = "Привіт " ;
char st2 [50] = " Сашко і Маша";
Strncat (st1, st2, 5);
st1 ="Привіт Сашко ".
¾ Порівняння рядків
int strcmp ( char *st1, char *st2); - порівнює рядки st1 і st2і повертає цілу величину, рівну:
< 0 ¾ якщо st1 < st2;
= 0 ¾ якщо st1 = st2;
> 0 ¾ якщо st1 > st2; ,
наприклад:
char st1[] = "Слово " ;
char st2 [] = "слово";
Int k;
k = strcmp (st1, st2); // k < 0;
int stricmp (const char *st1, const char *st2); ¾ виконує порівняння рядків не зважаючи на регістр символів; повертає цілу величину як і в попередньому випадку (див. функцію strcmp()), наприклад:
char st1[] = "Слово " ;
char st2 [] = "слово";
Int k;
k = stricmp (st1, st2); k=0;
int strncmp (char *st1, char *st2, int n); ¾ виконує порівняння рядків c заданою кількістю символів n у st1 і st2 і повертає цілу величину:
< 0¾ якщо st1 < st2;
= 0 ¾ якщо st1 = st2;
> 0 ¾ якщо st1 > st2;
char *strnicmp (char *st1, char *st2, int n); ¾ виконує порівняння рядків c заданою кількістю символів n у st1і st2, не зважаючи на регістр і повертає цілу величину як і в попередньому випадку.
¾ Перетворення символів рядка
char *strlwr (char *st);¾ перетворить символи рядка st верхнього
регістра в символи нижнього регістра, інші символи не зачіпаються,
Наприклад:
char st [i] =" Привіт Маша';
strlwr (st); // тепер st = "привіт маша".
char *strupr (char *st); ¾ перетворить символи рядка st нижнього регістра в символи верхнього регістра, інші символи не зачіпаються;
char *strrev (char *st); ¾ записує символи в рядку st у зворотному порядку (реверсує рядок), наприклад:
char st [] =" Hello";
strrev (st); //теперst = "olleН ".
char *strchr (char *st , int c); ¾ визначає перше входження символу c у рядок st; повертає покажчик на символ у рядку st, що відповідає введеному зразку, наприклад:
сhаr st [90] = " Borland C++ 5 "
char *spt;
spt = strchr (st , '+');
// Тепер покажчик spt указує на підрядок "++5" рядка st.
char *strrchr (char *st, int c); ¾ знаходить останнє входження символу cу рядок st;якщо символ cу рядку не виявлений ¾ повертає 0, інакше повертає покажчик на останній символ у рядку st, що відповідає заданому зразку, наприклад:
char st [80] = "Borland C++5";
char *spt;
spt = strrchr (st , '+');
// Тепер покажчик spt указує на підрядок "+5" рядка st.
¾ Пошук підрядка в рядку
strspn (const char *st1, const char *st2 );¾ повертає кількість символів від початку рядка st1, що збігаються із символами рядка st2, де б вони не знаходилися в st2, наприклад:
char st1 [] = "Borland C++5";
char st2 [] = " narlBod ";
Int k;
k = strspn (st1, st2); // k=8
У цьому випадку зміннаkодержує значеннярівне8,тому що перші 8 символів рядка містилися в st1 (включаючи символ проміжок).
char *strstr (const char *st1,const char *st2); ¾ функція шукає в рядку st1 перше входження st2і повертає покажчик на перший символ, знайдений у st1 з підрядка st2; якщо рядок st2 не виявлена в st1 - функція повертає 0, наприклад:
char st1 [] = "Привіт друг, йдемо в кіно " ;
char st2 [] = "друг ';
char*spt;
spt = strstr (st1, st2);
Результат виконання:
spt = " друг, йдемо в кіно".
У разі потреби визначення останнього входження, треба спочатку реверсувати рядок за допомогою функції strrev.
char *strtok ( char *st, const char *dlm); - розбивка рядка на лексеми ( сегменти ), обмежені символами включеними до складу параметра dlm. Цей параметр може містити будь-яку кількість різних обмежників ¾ ознак границь лексем; після виділення лексеми в рядок stміститься символ '\0'.
Наступні виклики функції strtok() повинні бути. с першим аргументом NULL.Вони будуть повертати покажчик на інші , наявні в stлексеми. Щораз після завершення виділення лексем у її кінці замість розділового символу міститься символ '\0'. Після того, як у рядку не залишиться ні однієї лексеми, функція повертає NULL . Для збереження вихідного рядка її треба записати в резервну змінну. Цю функцію зручно використовувати для розбивки речення на слова або будь-які інші сегменти. Розглянемо приклад програми з використанням strtok():
Приклад 3.4 Увести речення, розбити його на слова з виведенням порядкового номера слова і підрахунком символів у кожнім слові:
//P3_4.CPP ¾ застосування функції strtok( ).
// визначення порядкового номера слова в реченні і
// підрахунок символів у кожнім слові
#include <string.h>
#include < iostream>
Using namespace std;
Void main (void)
{
char *tk, *spt =", .!";
char st[] = "Сашко, нехай завжди буде солнце!";
cout << st << endl;
int i = 1;
tk = strtok (st, spt);
while (tk!= NULL)
{
cout << i << " слово-" << tk << " містить " <<
strlen(tk) << "символів" << endl;
tk = strtok (NULL,spt);
i++;
}
}
Для видалення з рядка підрядка або символу з заданої позиції в мові С++ немає спеціальної функції, однак можна написати свою, наприклад:
void del (char *st, int k, int n);
{ int i;
for ( i = k; i < strlen(st)-n; i++)
st[i] = st [i +n ];
st [i] ='\0';// Запис '\0'у кінець нового рядка
}
де st ¾ вихідний рядок (покажчик на неї);
n ¾кількість символів у підрядку що видаляється ;
k ¾ позиція, з якої треба видалити підрядок.
Нижче наведений приклад, що ілюструє реалізацію цієї програми
Приклад 3.5 Скласти програму видалення підрядка в n символів з k - ой позиції в рядку.
//P3_5.CPP видалення підрядка
#include < iostream>
Using namespace std;
#include <string.h>
const int n = 50;
const int m = 5;
void del(char *st, int, int);
Void main()
{
char st [n], st1 [m];
cout << "Введіть рядок"<< endl;
Cin. getline(st,n);
cout << "Введіть підрядок"<< endl;
cin >> st1;
if(strstr (st,st1)!=NULL)
{