МІНІСТЕРСТВО ОСВІТИ ТА НАУКИ УКРАЇНИ
НАЦІОНАЛЬНИЙ УНІВЕРСИТЕТ “ЛЬВІВСЬКА ПОЛІТЕХНІКА”
Кафедра САПР
СИМВОЛЬНІ МАСИВИ. РЯДКОВИЙ ТИП У МОВІ PASCAL
ЗВІТ
до лабораторної роботи № 6 з курсу:
“Алгоритмізація та програмування”
1. МЕТА РОБОТИ
Мета роботи – ознайомитись з окремим видом масивів – строками, або рядками символів.
2. ТЕОРЕТИЧНІ ВІДОМОСТІ
Під час розв’язування різних задач на ЕОМ виникає необхідність використання рядків, або рядків символів. У задачах лексичного і синтаксичного аналізу, а також при обробці текстової інформації, основним об’єктом обробки є рядки. Для позначення у програмі наперед визначеної послідовності символів служить рядок – константа. Рядок-константа – це послідовність символів між двома одинарними апострофами, наприклад:
’Львівська політехніка’
’Введи X,Y’
Якщо в середині рядка-константи є апостроф, то він подвоюється:
’Вимкни комп’’ютер’
’Опиши об’’єкт’
Символ ’ (апостроф) у мові Паскаль використовується як обмежувач рядків-констант. Тому транслятор не переплутає тип константи, якщо вона стоїть між апострофами.
Наприклад:
25 – ціла константа,
‘25’ – рядок-константа.
Кожна з цих констант наведена у пам’яті машини по-різному:
25 –0000000000011001 – у двійковій системі
’25’ – 0011001000110101,
де 00110010 – код цифри 2 та 00110101 – код цифри 5 в системі ASCII.
Відповідно і операції над цими двома константами можуть виконуватись різні: число 25 може брати участь в арифметичних операціях, а рядкова константа ’25’ у таких операціях використовуватись не може.
2.1. СИМВОЛЬНІ МАСИВИ
У більшості випадків конкретна послідовність символів не є наперед відомою, а формується у процесі виконання програми. Тому в мові Паскаль використовуються крім рядкових констант і рядкові змінні – одномірні масиви, елементами яких є символи:
VAR ST:ARRAY [1..50] OF CHAR;
Ми описали рядкову змінну ST, яка є рядком з п’ятдесяти символів. Типом індекса такого масиву повинен бути інтервальний цілий тип.
Мова Паскаль має додаткові засоби для роботи з такими масивами.
В авторській версії мови Паскаль рядкові змінні подано у вигляді упаковного масиву, елементи якого максимально ефективно займають пам’ять машини за рахунок упакування декількох компонентів в одне поле пам’яті.
Опис упакованого масиву:
VAR TS = PACKED ARRAY[1..50] OF CHAR;
Упакований масив використовується у програмі так само, як і неупакований, але програми з такими масивами виконуються дещо повільніше, оскільки необхідний додатковий час на вибір компонентів з масиву.
Для зменшення часу можна використати процедури PACK I UNPACK для упакування та розпакування масивів. Упаковані масиви (строки) мають ті ж властивості, що і звичайні масиви, але є і деякі відмінності:
1. Рядковій змінній можна присвоїти значення рядкової константи. При цьому слід пам’ятати, що довжини рядквої константи і змінної повинні бути однакові:
VAR ST1:PACKED ARRAY[1..22]OF CHAR;
BEGIN
ST1: = ’Львівська/Політехніка/’;
де / – символ пропуску (пробілу).
Пропуск є значущим символом, і тому рядки можна доповнювати відповідною кількістю пропусків.
2. Над рядковими змінними і рядковими константами можуть виконуватись операції порівняння: >, >=, <, <=, =, < >.
Порівняння проводиться посимвольно, тому довжина рядків символів, що порівнюються, повинна бути однакова.
Наприклад, порівняти: ’АВС’ > ’ABL’
Така операція дасть результат FALSE, оскільки буква С стоїть раніше ніж буква L, тобто C<L.
3. Над рядковими масивами може виконуватись операція конкатенації + (приєднання) при виведенні:
S1 = ’Львівська’;
S2 = ’Політехніка’;
WRITELN(S1 + ’/’ + S2);
У результаті виконання оператора WRITELN на екрані висвітиться:
Львівська Політехніка
4. До рядків символів може застосуватись стандартна функція EOLN, яка дає значення TRUE, якщо зчитано останній символ вхідного рядка і значення FALSE, якщо кінця рядка не досягнуто.
Приклад: У реченні довжиною не більше 80 символів обчислити число входжень слів FOR.
Блок-схему алгоритму наведено на рис. 1.
Блок 3 – введення першої і другої букви символьного рядка.
Блок 4 – початок циклу. Введення третьої букви.
Блок 5 – перевірка, чи знайдено сло-во FOR.
Блок 8 – перевірка, чи досягнуто кінця рядка.
Програма має такий вигляд:
PROGRAM KFOR (INPUT, OUTPUT);
VAR ST:PACKAD ARRAY[1..3] OF CHAR;
K: INTEGER;
BEGIN
K:= 0;
WRITELN (’Введи речення’);
READ(ST[1], ST[2]);
REPEAT
READ(ST[3]);
IF ST = ’FOR’ THEN K:= K+1;
ST[1]: = ST[2];
ST[2]: = ST[3]
UNTIL EOLN;
WRITELN(’Кількість слів FOR’=, K)
END.
2.2. РЯДКОВИЙ ТИП У МОВІ ТУРБО-ПАСКАЛЬ
Рядковий тип є одним із розширень мови Паскаль, реалізованих у середовищі Turbo Pascal. Рядковий тип випливає з поняття символьних масивів, але в рядковому типі може змінюватись довжина рядка.
Рядковий тип визначає множину символьних ланцюжків довільної довжини (від нуля до заданого числа). Для опису рядкового типу використовується службове слово STRING, слідом за яким вказується максимальна довжина рядка.
Структура опису типу:
TYPE <ім’я типу>=STRING[<довжина рядка>];
Синтаксична діаграма:
Рис. 2. Синтаксиксична діаграма рядкового типу
Приклад:
TYPE ST = STRING[80];
VAP TX : ST;
Зміна ТХ є рядком символів довжиною від нуля до 80 символів.
Описати зміну рядкового типу можна і в розділі опису змінних:
VAR TX : STRING[80];
S : STRING;
Максимальна довжина рядка може бути задана цілим числом або іменованою константою цілого типу, а може і не вказуватись. Якщо довжина не вказана, то максимальною довжиною є число 255.
Отже, найважливішою відмінністю рядка від символьного маcиву є те, що рядки можуть змінювати свою довжину.
Наприклад:
S: = ’Львівська/Політехніка’;
S: = ’Національний/університет/’ + S;
У результаті виконання цих двох операторів присвоєння змінна S буде мати значення:
’Національний/університет/Львівська/Політехніка’
де / – символ пропуску (пробілу).
Хоч на перший погляд пам’ять під змінну рядкового типу виділяється динамічно, проте це не так. Точніше, пам’ять виділяється так, як і для масивів на етапі трансляції програми за максимальною довжиною. Якщо максимальна довжина рядка 80 символів, то виділяється 81 байт. При цьому в 80-ти байтах записується рядок символів, а в нульовому байті довжина цього рядка:
Нехай описана зміна:
VAR ST : STRING[80];
BEGIN
SТ: = ’ABCD’,
У нульовий байт запишеться довжина рядка ST – 4, а у перший, другий, третій і четвертий байти символи A,B,C,D. Решта 76 байтів будуть вільними.
Над змінними рядкового типу можуть виконуватися операції.
1) конкотенації ( + ). Наприклад: ST = ST + ‘LM’
У результаті виконання цієї операції рядок ST вже буде містити 6 символів: ‘ABCDLM’.
2) порівняння: >, > =, <, < =, =, < >.
При виконанні операцій порівняння діють такі правила:
Коротший рядок завжди менший від довшого;
Якщо довжина рядків однакова, то відбувається поелементне порівняння цих рядкiв з урахуванням лексикографічної впорядкованості значень стандартного символьного типу CHAR.
Значення рядкової змінної може бути присвоєно оператором присвоєння або прочитано з файла чи з клавіатури. При цьому слід пам’ятати, що якщо рядковій змінній присвоюється значення довше ніж максимальна довжина, рядок обрубується до максимальної довжини:
VAR ST : STRING[15];
BEGIN
ST: = ’Державний/університет’
WRITELN(ST);
У результаті виконання такого фрагмента програми виведеться:
Державний уніве
Є два способи роботи із рядками символів:
Представити рядок у вигляді символьного масиву.
Працювати з рядком як з єдиним цілим за допомогою функцій і процедур.
2.2.1. РОБОТА З СИМВОЛЬНИМ РЯДКОМ, ПРЕДСТАВЛЕНИМ МАСИВОМ СИМВОЛІВ
(стандарт мови Паскаль)
На змінну рядкового типу переносяться всі властивості і правила роботи з символьними масивами.
Введення і виведення рядка здійснюється поелементно в циклі за допомогою процедур READ і WRITE
Доступ до окремого елемента рядка здійснюється з використанням індекса, тобто ST[1], ST[I].
Приклад: у символьному рядку довжиною 80 символів визначити кількість входжень слів IN, вважаючи, що всі слова розділені пропусками. При вирішенні цього завдання доцільно передбачити три ситуації:
Слово IN стоїть на початку рядка; тобто ’IN/’;
Cлово IN стоїть в середині рядка, тобто ’/IN/’;
Cлово IN в кінці рядка, тобто ’/IN’.
Блок-схема алгоритма представлена на рис. 3.
Блоки 2, 3 – введення рядка символів довжиною 80.
Блок 4 – обнулення лічильника К.
Блоки 5, 6 – перевірка чи слово IN стоїть на початку рядка.
Блоки 7, 8 – перевірка, чи слово IN стоїть в кінці рядка.
Блок 9 – відкриття циклу.
Блок 10 – перевірка, чи слово IN стоїть в середині рядка.
Блок 11 – збільшення лічильника на 1.
Блок 12 – виведення результату К.
Текст програми:
PROGRAM SIMMAS(INPUT,OUTPUT);
VAR ST : ARRAY[1..80] OF CHAR;
I,K : INTEGER;
BEGIN
FOR I: = 1 TO 80 DO
READ(ST[I]);
K: =0;
IF (ST[1]=’I’) AND (ST[2]=’N’) AND (ST[3]=’/’)THEN K:=K+1;
IF (ST[78]=’/’) AND (ST[79]=’I’) AND (ST[80]=’N’)THEN K:=K+1;
FOR I:=1 TO 76 DO
IF(ST[I]=’/’)AND(ST[I+1]=’I’)AND(ST[I+2]=’N’)AND(ST[I+3]=’/’)
THEN K:=K+1;
WRITELN(’Кількість слів IN=’, K)
END.
2.2.2. РОБОТА З СИМВОЛЬНИМИ РЯДКАМИ ЯК З ЄДИНИМ ЦІЛИМ (середовище Turbo Pascal)
Введення і виведення змінної рядкового типу здійснюється за допомогою процедур READLN та WRITELN без вказування індексу елемента.
READLN(ST);
WRITELN(ST);
Над змінними рядкового типу визначені такі стандартні функції:
LENGTH(<рядок>) – визначає довжину рядка, тобто кількість символів у цьому рядку.
CONCAT(S1, S2,…,SN) – з’єднує рядки S1, S2, …SN в один рядок.
COPY(S, IND, K) – дає підрядок, виділений із рядка S, довжиною К, починаючи з індекса IND;
POS(SP, S) – дає номер позиції, з якої починається підрядок SP в рядку S.
Стандартні процедури:
DELETE(S, IND, K) – вилучає К символів із рядка S, починаючи з позиції IND.
INSERT(S1, S , IND) – вставляє S1 в рядок S, починаючи з позиції IND.
З використанням стандартних функцій і процедур до змінної рядкового типу ST програма для розв’язання попереднього прикладу буде мати такий вигляд:
PROGRAM STROK;
VAR ST:STRING[80];
S1, S2:STRING[3];
S3:STRING[4];
I, K:INTEGER;
BEGIN
READLN(ST);
K:=0;
S1:=COPY(ST, 1, 3);
S2:=COPY(ST, 78, 3);
IF(S1=’IN/’)THEN K:=K+1;
IF(S2=’/IN’)THEN K:=K+1;
FOR I:=1 TO 76 DO
BEGIN
S3:=COPY(ST, i, 4);
IF S3=’/IN/’ THEN K:=K+1;
END;
WRITELN(’Кількість слів IN=’, K)
END.
ЛАБОРАТОРНЕ ЗАВДАННЯ
Програма №1, Варіант №17
Блок-схема:
/
Код програми:
program words_array;
uses crt;
var
s:array [1..70] of char;
i, k:integer;
begin
writeln('Введiть рядок');
for i:=1 to 70 do
read(s[i]);
k:=0;
for i:=1 to 65 do
if (s[i] = ' ') and (s[i+5] = ' ') then
k:=k+1;
writeln('Кiлькiсть слiв з 4 букв=', k);
end.
Результати обчислень:
/
Програма №2, Варіант №17
Блок-схема:
/
Код програми:
program words_string;
uses crt;
var
s:string[70];
i, k:integer;
begin
writeln('Введiть рядок');
readln(s);
k:=0;
for i:=1 to 65 do
if (copy(s, i, 1) = ' ') and (copy(s, i+5, 1) = ' ') then
k:=k+1;
writeln('Кiлькiсть слiв з 4 букв=', k);
end.
Результати обчислень:
/
У двох випадках з однаковими вхідними даними програми показали правильний результат. Але якщо представляти рядок у вигляді масиву символів, програма має більш громіздкий код і при вводі рядка з 70 символів потребує введення всіх 70 символів. До символьних масивів також неможливо застосовувати стандартні, призначені для типу STRING, функції та арифметичні операції.
ВИСНОВОК
В ході виконання цієї лабораторної роботи я ознайомився з окремим видом масивів – строками, або рядками символів.