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)

{