Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
glinskiymetodichka-s.doc
Скачиваний:
24
Добавлен:
15.08.2019
Размер:
2.7 Mб
Скачать

§ 13. Рядки

1. Рядки символів і дії з ними. На відміну від інших мов програмування у C++ не визначено спеціального типу для опрацювання рядків. Рядок символів розглядається як масив елементів типу char, який закінчується символом '\0' (нуль-символ) що є ознакою кінця рядка. Такі рядки називають ASCI І-рядками. Сталі типу рядок записують у лапках, на­приклад, "Львівська політехніка", "студенти", ' " — рядок, що містить один символ-пропуск. У сталих рядках нуль-сим-вол дописується автоматично.

Зауваження 1. Більшості компіляторів мови C++ автоматично додає нуль-символ у кінець рядка, тому зазначати його не обов'язково.

Масиви символів оголошують так:

char <назва рядка>[довжина рядка];

Під час оголошення символьного масиву необхідно до фактичної довжини рядка додати одиницю для нульового символу (але не у всіх компіляторах). Якщо масив символів оголошують й ініціалізують одночасно, то довжину можна не зазначати, компілятор визначить її. Оскільки рядки є маси-

вами символів, то назва рядка є вказівником на його перший елемент (на перший символ).

Приклад 1. Розглянемо оголошення та ініціалізацію ряд­ків

const char text1[] = "Ми вивчаємо програмування";

char slovo[] = "University";

char fraza1[11], fraza2[40];

Тут оголошено сталу texti, яка має значення "Ми вивчаємо програмування", символьні масиви: slovo (без зазначення роз­міру), frazai (може містити до 10 символів) та fraza2 (до 39 сим­волів).

Символьний масив slovo ще можна оголосити так:

char slovo[11] = "University"; або так

char slovo[] = {'U', 'n', y, v 'e', 'r',’ s',' i',' t', 'y', '\0'};

Тут потрібно вручну записати нуль-символ, інакше компі­лятор трактуватиме змінну slovo не як рядок, а як масив.

Рядки можна опрацьовувати посимвольно за допомогою вказівників або назви масиву, наприклад, так:

for (int n = 0; n < 11; n++) *(fraza1+n) = *(slovo+n); cout<<frazai;

Змінній fraza1 надається значення "University" і ця фраза виводиться на екран. Інакше це можна зробити так:

for (int n = 0; n < 11; n++)

fraza1[n] = slovo[n]; cout << fraza1;

Увести весь масив символів можна за допомогою команди

сіn >> <назва масиву>;

Якщо рядок даних містить символ пропуску, то команда сіп >> зчитає дані лише до першого пропуску. Щоб зчитати весь рядок до символу вводу, необхідно застосувати команду

cin.get(<Haзвa рядка>, максимальна довжина рядка>);

Наприклад, cin.get(fraza2, 40). Зчитати символ вводу можна так: cin.get(). Зчитати рядок разом із символом вводу можна одним із способів:

  1. cin.get(fraza2, 40); cin.get()

  2. cin.get(fraza2, 40).get()

  3. cin.getline(fraza2, 40).

Вивести значення рядка на екран можна за допомогою ко­манди

Cout << <назва рядка>;

Посимвольно вводити чи виводити елементи рядка можна за допомогою команд циклу for або while. Наприклад, for (int n = 0; n < 11; n++) сіn >> *(fraza1 + n);

В кінці рядка необхідно поставити нуль-символ, тобто *(fraza1 +n + 1) = '\0';

У бібліотеці conio.h визначені стандартні функції введення-виведення рядків. Наприклад, getc(), getchar() зчитують по одному символу рядка, введеного з клавіатури, putc() та putchar() виводять окремі символи рядка тощо. У бібліотеці stdio.h описані функції для введення gets() та виведення puts() усього рядка. Детальніше по ці та інші функції написано у довідниках.

2. Функції для опрацювання рядків. Для опрацювання масивів символів у мові C++ є стандартні функції, які опи­сані у модулі string.h. Розглянемо деякі з них.

strlen(<рядок>) - визначає фактичну кількість символів у рядку, застосовується у виразах;

strcat(r1, r2) - команда з'єднання рядків r1, r2 в один ря­док, результат присвоює змінній r1;

strncat(r1, r2, n) - до змінної r1 додає перших n символів рядка r2, команда;

strcpy(r1, r2) - копіює символи з рядка r2 в рядок r1, команда;

strncpy(r1, r2, n) - копіює перших п символів рядка r2 в рядок r1, команда;

strchr(r1, <символ>) - визначає перше входження деякого символу у рядок r1 так: повертає рядок, який почи­нається від першого входження заданого символу до кінця рядка r1, застосовується у виразах;

strrchr(r1, <символ>) - визначає останнє входження зада­ного символу у рядок, застосовується у виразах;

strspn(r1, r2) - визначає номер першого символу, який входить у рядок r1, але не входить у рядок r2, застосовується у виразах;

strstr(r1, r2) - визначає в рядку її підрядок, що починаєть­ся з першого входження рядка г2 у рядок її, засто­совується у виразах;

strtok(r1, r2) - визначає частину рядка її, яка закінчується перед періпим однаковим символом рядків її та г2;

strnset(r1, <символ>, п) - вставляє п разів заданий символ перед рядком її, застосовується у виразах;

strupr(r1) - перетворює усі малі літери рядка у великі;

strlwr(r1) - перетворює усі великі літери рядка у малі;

strrev(r1) - записує рядок у зворотному порядку.

Приклад 2. Розглянемо результати застосування функцій до таких змінних:

char Lviv[] = "Львівська політехніка",

Un [30] = "НУ ",

г1 [30] ="";

char *p; int n;

Застосування функцій

Результат

n = strlen(Lviv)

n = 21

strcat(Un, Lviv)

Un = "НУ Львівська політехніка"

strncat(Un, Lviv, 10)

її = "НУ Львівська"

strcpy(r1, Lviv)

г1 = "Львівська Політехніка"

strncpy(r1, Lviv, 10)

її = "Львівська"

p = strchr(Lviv, 'П')

р = "політехніка"

p = strrchr(Lviv, Ї)

р = "іка"

n = strspn(Lviv, "Львів")

п = 5

p = strstr(Lviv, "тех")

р = "техніка"

p = strtok(Lviv, "кс")

р = "Львів"

p = strnset(Lviv, 'x', 10)

р = "ххххххххххполітехніка"

p = struprf'l Love You")

р = "і love you"

p = strlwrfl Love You")

р = "І LOVE YOU"

p = strrevfTexHiKa")

р = "акінхет"

Зауваження 2. Функції перетворення літер strlwr і strupr діють лише для латинського алфавіту. Крім того, у деяких версіях мови C++ ці функції можуть записуватись інакше: _strlwr, _strupr.

У бібліотеці stdlib.h є стандартні функції перетворення типів даних. Зокрема, функція atoi(r1) перетворює рядок сим­волів її у дане цілого типу int, а функція Коа(<числове дане>, r1, <система числення>) - дане цілого типу int у рядок r1. Для пере­творення даних типу double у рядок символів визначена функ­ція gcvt(<Числовe дане>, <кількість знаків у числі>, r1), а обернену дію виконує функція strtod.

Приклад 3. Розглянемо результати дії цих функцій для оголошених нижче змінних.

int n;

doublet;

char r1[5], *p;

Застосування функції

Результат

n-atoi("12")

n = i2

itoa(12, г1, 10)

г1 = '12"

qcvt(-3.14, 4, г1)

г1 =-3.14

f = strtod("-3.1415", &p);

f = -3.1415

Рядки символів можна порівнювати між собою. Два ряд­ки порівнюють зліва направо посимвольно, причому 'А < В , В' < "С тощо. "Більшим уважається символ, який розміще­ний в алфавіті дальше (він має більший номер у таблиці кодів ASCII, див. далі). Для порівняння рядків у модулі string.h надані такі функції:

  • strcmp(r1, r2) - порівнює рядки символів її і г2 з ураху­ ванням регістра для латинського алфавіту;

  • stricmp(r1, г2) - порівнює рядки r1 і г2, не розрізняючи великих і малих літер латинського алфавіту.

Результатом виконання цих функцій є від'ємне число (якщо рядок її менший від рядка г2), 0 (якщо рядки однакові) або додатне число (рядок її більший за рядок г2). Приклад 4. Розглянемо результат дії функцій

Функція

Результат

n = strcmp("BecHa", "весна")

п = -32

n = strcmpC'eecHa", "Весна")

п = 32

n = strcmp("BecHa", "Весна")

п = 0

n = stricmp("BecHa", "весна")

п = -32

n = stricmpC'Vesna", "vesna")

n = 0

Задача 1 (про довжину фрази). Увести рядок символів та визначити його довжину.

Зробимо це двома способами:

1) за допомогою вказівника типу char і виділення дина­мічної пам'яті:

#include <iostream.h> // Довжина рядка символів

void main()

{

char *s; // Оголошуємо вказівник на рядок

s = new char[50]; // Виділяємо пам'ять для введення рядка

сіn >> s;

int d = 0;

while (*s++) d++;

cout << d;

}

2) визначивши різницю адрес першого й останнього сим­волів:

#include <iostream.h> // Довжина рядка символів

void main()

{

char *s, *p; // Оголошуємо вказівники

s = new char[50]; // Виділяємо пам'ять для введення рядка

сіп >> s;

р = s; // Вказівник р вказує на перший символ рядка

// Вказівник s тепер вказуватиме while (*s++); // на останній символ рядка

int d;

// Визначаємо довжину рядка як різницю адрес d = s - р+ 1; cout<< d; }

Задача 2 (про пошук слова у фразі). Нехай задано рядок "Скоро будуть канікули". Визначити довжину рядка. Вивести на екран друге слово цього рядка.

#include <iostream.h> // Пошук другого слова за допомогою функцій

#include <string.h>

void main()

{

char r1[] = "Скоро будуть канікули";

char *p;

cout << r1 << "\n";

cout << "Довжина рядка r1 = " << strlen(r1) << “\n”";

// Встановлюємо вказівник р на перший пропуск р = strchr(r1,''); // у рядку г1

// З рядка р вилучаємо всі символи після його strtok(p, ""); // першого пропуску

cout << р;

}

Подамо ще один спосіб розв'язання задачі 2, в якому ря­док розглядається як масив символів і функції для роботи з рядками не використовуються.

#include <iostream.h> // Рядок як масив символів

#include <conio.h>

#include <string.h>

void main()

{

clrscr();

char r1[] = "Скоро будуть канікули";

char *p;

int n1, n2, k, m;

m = 0;

k = strlen(r1);

cout << "Довжина рядка r1 = " << k << "\n";

for (int i= 0; і < k; І++) // Переглядаємо всі символи рядка

if (r1 [і] == '') // Шукаємо пропуск

{

m++; // Визначаємо номери першого

if (m == 1) n1 = і; // та другого

if (m == 2) n2 = і; // пропусків

}

// Виводимо слово між двома пропусками

for (і = п1 + 1; і < п2 -1; і++) cout << r1 [і];

getch();

}

Задача 3 (про столиці). Введіть п'ять назв столиць євро­пейських країн. Упорядкуйте їх за алфавітом. Виведіть упо­рядкований масив на екран.

// Столиці країн

#include <iostream.h>

#include <string.h>

#include <conio.h>

#define N 5

void main()

{ // Оголошуємо N вказівників на рядки

char p[N][16]; // довжиною до 15 символів

char m[16];

for (int і = 0; і < N; i++)

сіn >> *(p +i); // Вводимо рядок і

for (і = 0; і < N - 1; і++)

{

for (intj = 0; j < N - і; j++)

{

if (strcmp(p[j], p[j+1]) > 0) // Порівнюємо рядки

{ Hi, у разі потреби, міняємо

strcpy(m, p[j]); // їх місцями

strcpy(p[j], p[j+1]);

strcpy(pO+1], m);

}

}

}

for (i = 0; і < N; І++) cout << p[i] << "\n";

}

3. Криптографічні задачі. Текстові функції застосовують­ся для розв'язування задач кодування даних з метою збере­ження секретності інформації. Існує наука - криптографія, де вивчаються і створюються різні алгоритми кодування ін­формації. Основні задачі криптографії - це шифрування текс­ту, передача його на відстань і дешифрування. Це використо­вується у банківських справах, у воєнних цілях, у діяльності різних фірм, під час пересилання інформації в локальних чи глобальних мережах тощо.

Древнєримський імператор Цезар кодував свої секретні вказівки так: кожна літера тексту замінювалась на четверту після неї літеру з алфавіту. Такий шифр називається в крип­тографії шифром зі сталим зміщенням (тут 4), або шифром з одним ключем.

Задача 4 (про шифр Цезаря). Скласти програму для ко­дування деякого тексту до 50 символів шифром Цезаря, замі­нивши кожну літеру на &-ту (наприклад, четверту) після неї літеру з алфавіту. Під алфавітом розуміти таблицю кодів ASCII.

// Програма Код Цезаря

#include <iostream.h>

#include <string.h>

void main()

{

char a[50];

cout<< "Введіть текстЛп";

cin.get(a, 50);

for (int k, n = 0; n < strlen(a); n++)

{

k = *(a+n) + 4; *(a + n) = k;

}

cout<< a;

}

Задача 5 (про заміну слів). Скласти програму, яка скрізь у заданому тексті mytext замінить деяке слово іншим словом такої ж довжини (wordl на word2).

#include <iostream.h> // Програма Заміна слів

#include <string.h>

void main()

{

char wordl[5], word2[5], mytext[50];

char *p;

cout << "Введіть текст\n"; cin.get(mytext, 50);

cout << "Введіть шукане словo \n"; сіn >> wordl;

cout << "Введіть інше слово\n"; сіn >> word2;

int k = strlen(word1);

// Встановлюємо вказівник р на початок р = mytext; // рядка mytext

for (int і = 0; і < strlen(mytext) - k; І++) // Опрацьовуємо посимвольно { // рядок р

// Знаходимо перше входження wordl р = strstr(p, wordl); // у рядку р

// Якщо такого входження немає, то if (p == NULL) break; // виходимо з циклу

// У рядку р замінюємо wordl на word2

for (int j =0; j < k; j++) *(p + j) = *(word2 + j);

}

cout << mytext;

}

Вправи

  1. Складіть програму розв'язування задачі 1, використавши статич­ний масив та функцію srtlen.

  2. Уведіть фразу з кількох слів і виведіть її так, щоб усі слова були зображені в зворотному порядку, зберігши порядок слів, двома способа­ми: а) з використанням функцій з бібліотеки string.h; б) без використан­ня функцій з бібліотеки string.h. Наприклад, фразу "заняття з програ­мування" треба вивести так: "яттяназ з яннавумаргорп" (модифікуйте для цього програму Рядок як масив символів).

  3. Розв'яжіть задачу про столиці країн без застосування функцій з модуля string.h.

  4. Модифікуйте програму Код Цезаря, щоб можна було зашифрувати текст, уведений у декілька рядків.

  5. Складіть програму розшифровування тексту, закодованого кодом Цезаря.

  6. Складіть програму кодування тексту так: перший символ замінити на k-й, що розміщений в алфавіті після нього (тобто замінити з кроком зміщення k), кожний наступний символ замінювати з кроком зміщення на m одиниць більшим, ніж попереднє зміщення. Алфавіт (таблицю кодів чи її фрагмент) розглядати циклічно. Наприклад, обмежимося алфавітом 0, 1, 2, 3, 4, 5, 6, 7, 8, 9. Для k = 2, m = 1 чисельність військового гарнізону 12290 вояків буде зашифрована числом 35646. Такий шифр називається шифром зі змінним зміщенням (або шифром з двома ключами).

  7. Запишіть програму Заміна слів без використання функцій з бібліо­теки string, h.

8. Закодуйте фразу так: вилучіть з неї пропуски та коми, інші символи продублюйте. Вивести результат.

9. Масив зі 100 рядків і 10 стовпців заповніть цілими числами, що вводяться з клавіатури. Якщо чергове число менше від 0, заповнення такого рядка припиніть. Після чисел у кожному рядку запишіть ще од­не число - кількість чисел у ньому. Виведіть масив.

10. Розв'яжіть задачі № 16, 17 і 18 з розділу "Задачі" вашого варіанта дврма способами:

а) з використанням функцій з бібліотеки string.h;

б) без використання функцій з бібліотеки string.h.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]