Лабораторна робота №8 Робота з даними рядкового типу. Оголошення та використання процедур і функцій. МЕТА РОБОТИ Навчитися використовувати у програмах данi рядкового типу та пiдпрограми (процедури і функції). ПОРЯДОК ВИКОНАННЯ РОБОТИ 1. При підготовці до лабораторної роботи, згідно із індивідуальним завданням, розробити алгоритм та програму на мові Pascal, в яких використовуються данi рядкового типу. Основні обчислення реалізувати з допомогою підпрограми-функції чи підпрограми-процедури. Зрозуміти апарат передачі даних між формальними-фактичними параметрами, для цього формальні і фактичні параметри позначити різними змінними. 3. Виконати ввід, виконання та відлагодження програми. 4. Проаналізувати отримані результати та оформити звіт по роботі. IНДИВIДУАЛЬНI ЗАВДАННЯ 1. Не використовуючи стандартних процедур та функцiй, напишiть фрагмент програми для витирання iз рядка пiдрядка заданої довжини, починаючи iз заданої позицiї; 2. Заданий рядок, що складається iз слiв, роздiлених пропусками, знайти кiлькість однакових слiв у рядку; 3. Пiдрахувати кiлькість заданих однакових символiв, що входять у заданий рядок. 4. Витерти iз заданого рядка всi пропуски. 5. Заданий масив рядкiв символiв. Впорядкувати його по зростанню кодiв символiв. 6. Заданий масив рядкiв символiв, знайти кiлькість рядкiв, що починаються з заданого символа s. 7. Для заданих оголошень type word_ = packed array [1..5] of char; str = array [1..60] of word_; var C: str; надрукувати слово iз списку С, яке по алфавiту передує всiм iншим словам цього списку. 8. Iз клавiатури вводиться послiдовнiсть малих латинських букв. Якщо це правильний запис значення типу color: type color=(red, blue, green, yellow, black, white); var x:color; то присвоїти його змiннiй х, iнакше повiдомити про помилку. 9. Пiдрахувати кiлькiсть голосних букв та кiлькість кожної iз голосних букв, що входять у рядок символiв, який вводиться iз клавiатури. 10. Задана послiдовнiсь, що складається вiд 1 до 100 слiв, мiж якими знаходиться не менше 1-го пропуску. Кожне слово мiстить вiд 1 до 10 символiв. Надрукувати всi слова в лексикографiчному порядку. 11. Задана змiнна рядкового типу m:string[100]. Замiнити групу однакових символiв на один символ цiєї групи. 12. Задана послiдовнiсть символiв. Роздрукувати цю послiдовнiсть подвоївши всi одинарнi пропуски; 13. Задана послiдовнiсть символiв, що зображає запис виразу на мовi Паскаль. Перевiрити, чи в даному виразi правильно розставленi круглi дужки. 14. Задана послiдовнiсть символiв. Перевiрити, чи ця послiдовнiсть правильно зображає запис цiлого числа зi знаком. 15. Задана послiдовнiсть символiв. Перевiрити, чи ця послiдовнiсть правильно зображає iдентифiкатор Паскаля. МЕТОДИЧНI ВКАЗIВКИ. Рядковий тип. Рядковий тип у Паскалі використовується для обробки текстів. Для його оголошення використовується ключове слово string: var ім'я_змінної: string[N]; де ім'я_змінної - правильний ідентифікатор, а N - ціле число або нетипована константа цілого типу зі значенням в діапазоні від 1 до 255. Якщо N не вказано, то довжина рядка приймається рівною 255 символів. Оголошення стрінга подібне на оголошення одномірного масиву символів var ім'я_змінної: array[0..N] of char; Такий масив символів називається рядком фіксованої довжини. На відміну від нього, рядок типу string може містити різну кількість символів в межах від 0 до N. Приклади оголошень стрінгів: type st=string[10]; var s:st; t:string[25]; r:string; Доступ до окремих символів стрінгу здійснюється так як до елементів одномірнрго масиву, наприклад: s[5]. В пам'яті під рядок символів відводиться N+1 байт, причому нульовий байт містить динамічну довжину рядка. Якщо стрінгу присвоюється значення, кількість символів якого менша N, то реальна довжина рядка запамятовується в нульовому байті. Якщо кількість символів більша від N, то рядок відсікається зправа до визначеної довжини. Наприклад: var str1,str2:string[12]; Begin str1:=''; {пустий рядок} str2:='Рядок'; str3:='Програмування на Турбо-Паскалі'; {..............} End. В результаті виконаних присвоєнь отримаємо: ORD(str1[0])=0; ORD(str2[0])=5; ORD(str3[0])=30; Над стрінгами допускається виконання операції конкатенації , яка позначається символом '+'. На відміну від рядків фіксованої довжини результат конкатенації рядків можна присвоїти іншому стрінгу. Операція конкатенації допускається над стрінгом та іншим стрінгом, рядком символів фіксованої довжини або окремим символом. Наприклад: var s1,s2,s3:string; s1:='Turbo'; s2:='Pascal'; s3:=s1+' '+s2; Для стрингів, рядків символів та окремих символів допускаються наступні операці відношення: =,<>,<,>,<=,>= . Операції відношення виконуються посимвольно зліва направо. При виконанні операцій відношення порівнюються ASCII-коди символів. Відповідність по довжині операндів не обов'язкова. Порівняння здійснюється до вичерпання довжини коротшого рядка. Результатом порівняння двох рядків є значення константи булівського типу true або false. Приклад: var s:string; a:array[1..5] of char; c:char; Begin s:='123456789'; a:='12abc'; c:=s[2]; writeln('a'>'A'); {true} writeln(s>a); {false} writeln(c>a); {true} End. Ввід стрингів здійснюється по їх імені за допомогою процедури Read, а вивід за допомогою процедури Write. Ввід рядка здійснюється до натискання клавіші Enter або до вичерпання його оголошеної довжини. Ввід рядка за допомогою процедури Read залишає у буфері вводу два символи #13#10, які виникають при натисканні клавіші Enter. Тому при наступному вводі рядків символів, наприклад, у циклі, буде прочитаний пустий рядок. Символи #13#10 будуть прочитані токаж наступною процедурою вводу символів, що приведе до неправильного вводу даних. Тому для вводу рядків та символів краще користуватися процедурою Readln, яка не залишає у буфері вводу вказаних символів. При вводі рядків у циклі необхідно обов'язково використовувати процедуру Readln. Наступна програма здійснює у циклі ввід рядків символів та записує їх у зворотньому порядку. const n=5; var s:string; c:char; i,j,m:byte; Begin for i:=1 to n do begin readln(s); m:=length(s); for j:=1 to m div 2 do begin c:=s[j]; s[j]:=s[m-j+1]; s[m-j+1]:=c end; writeln(s) end End.
Для роботи з рядками використовується ряд бібліотечних процедур та функцій. Бібліотечні процедури та функці для роботи з рядками символів 1. Визначення довжини рядка. Function Length(s:string):integer; Повертає біжучу довжину рядка в діапазоні від 0 до 255, визначену у нульовому байті рядка: Length(s)=ORD(s[0]). Приклад: var s:string[80]; begin s:='12345'; writeln(Length(s),' ',SizeOf(s)); {5 81} end. 2. Конкатенація рядків. Function Concat(s1 [,s2,...,sn]):string; Здійснює об'єднання рядків s1, s2, ... ,sn. Якщо сумарна довжина рядка буде більшою від 255 або від довжини рядка, розміщеного в лівій частині оператора присвоєння, то результуючий рядок відсікається зправа. var s1:string; s2:string[5]; begin s1:=Concat('123','456789'); writeln(s1); {'123456789'} s2:=Concat('123','456789'); writeln(s2); {'12345'} end.
3. Копіювання рядків. Function Copy(s:string; index:integer; count:integer):string; Повертає підрядок з count символів, починаючи з позиції index рядка s. Якщо index>length(s), то повертає пустий рядок. Якщо count>length(s)-index+1, то повертає length(s)-index+1 символ. Приклад: var s1:string; s2:string[5]; begin s1:='123456789'; s2:=Copy(s,3,5); writeln(s2); {'34567'} end. 4. Визначення входження одного рядка в інший. Function Pos(substr:string; s:string):byte; Повертає номер позиції першого входження підрядка substr в рядок s. Якщо substr не входить в s, то повертає 0. Приклад: var n:byte; begin n:=Pos('34','12345'); writeln(n); {3} end. 5. Вставка одного рядка в інший. Procedure Insert(substr:string; var s:string; index:integer); Вставляє підрядок substr в рядок s, починаючи з символа з номером index. Довжина результуючого рядка приводиться до оголошеної довжини рядка s шляхом відкидання символів зправа. Приклад: var s:string; begin s:='12345'; Insert('abc',s,3); writeln(s); {'12abc345'} end. 6. Витирання підрядка з рядка. Procedure Delete(var s:string; index:integer; count:integer); Витирає count символів з рядка s, починаючи з номера index. Якщо index=0, або count=0, або index>length(s), то рядок не міняється. Якщо count>length(s)-index+1, то витираються символи до кінця рядка. Приклад: var s:string; begin s:='12abc345'; Delete(s,3,3); writeln(s); {'12345'} end. 7. Перетворення числа у рядок. Procedure Str(x [:w [:d]]; var s:string); Перетворює дійсне або ціле число x у рядок символів s. Значення w та d можуть бути константами, змінними або виразами типу integer і відповідно позначають загальну кількість символів та кількість символів після десяткової крапки (тільки для дійсного типу). Якщо w<=sizeof(s), то рядок буде складатися з w символів заокругленого числа. Якщо w>sizeof(s), то рядок буде містити sizeof(s) символів заокругленого числа. Якщо w>0, то рядок вирівнюється по правій стороні, якщо w<0, то по лівій стороні. Для дійсних чисел, якщо d=0, а w<8, то приймається w=8 і рядок представляє запис числа з плаваючою крапкою. Приклад: var s1:string; s2:string[5]; s3:string[3]; begin Str(Pi:6:2,s1); {' 3.14'} Str(Pi:6:2,s2); {' 3.14'} Str(Pi:6:2,s3); {'3.1'} Str(Pi:-6:2,s1);{'3.14 '} Str(Pi:-6:2,s2);{'3.14 '} Str(Pi:-6:2,s3);{'3.1'} Str(Pi:10,s1); {' 3.142E+00'} Str(Pi:6,s1); {' 3.1E+00'} end. 8. Перетворення рядка символів у число. Procedure Val(s:string; var x; ErrCode:integer); Перетворює рядок із цифр в значення цілого або дійсного числа x. В рядку s не повинно бути ведучих пропусків. Тип x повинен відповідати вмісту рядка s. При перетворенні в ціле бажано оголосити x як longint. Параметр ErrCode=0, якщо перетворення пройшло успішно, інакше містить номер позиції , де знайдений помилковий символ. Приклад: var s:string; n:longint; r:real; ErrCode:integer; begin s:='12345'; Val(s,n,ErrCode); writeln(n); {12345} s:='3.14'; Val(s,r,ErrCode); writeln(r:5:2); {3.14} end. 9. Заповнення змінно значенням байта. Procedure FillChar(var x; count:word; ch:value); Записуї значення ch в count байтів змінно x. Змінна x може бути довільного типу, а значення ch - порядкового типу. var s:string[20]; begin FillChar(s,sizeof(s),'*'); s[0]:=Chr(20); End. Функцiя. Функцiї використовуються для опису пiдпрограми, в результатi виконання якої значення результату одержує одна змiнна. Ця змiнна - iм'я функцi . Тому в заголовку функцiї через двокрапку описується тип функцiї . В тiлi функцiї має бути оператор, який присвоює iменi функцiї значення результату. Звертання до функцiї проходить аналогiчно звертанню до стандартних функцiй типу SQR, SIN. Звертання до функцiї проходить в виразi. Для цього в виразi записується iм'я функцiї , далi за ним в круглих дужках перелiчуються фактичнi параметри, тобто параметри, якi необхiдні для обчислення значення функцi . Для кожного параметра, що входить в список формальних параметрiв (у заголовку функцiї ) при звертаннi до функцiї має бути вказаний фактичний параметр. Порядок, кiлькiсть, тип формальних параметрiв мають вiдповiдати порядку, кiлькостi, типу фактичних параметрiв. Приклад. Program Fn;{ програма для обчислення деякої функцiї} var F,X,A,B,H,K,P: real; function CH (T:real):real;{ опис функцiї} begin CH:=(exp(T)+exp(-T))/2 { обчислення значення функцiї} end; begin Read(A,B,H,K,P); Writeln('H=',H,'K=',K,'P=',P); X:=H; while X<=K do begin F:=A+B*CH(X); Writeln(X:5:1,' ',F:10:3); X:=X+P end end. Процедури. Якщо по алгоритму необхідно виводити бiльше нiж одне значення результату, то, як правило, використовуються пiдпрограми-процедури. Чим вiдрiзняються процедури вiд функцiй: -спосiб виклику процедури вiдрiзняється вiд виклику функцiї, так як виклик проводиться за допомогою спецiального оператора виклику процедури; -в заголовку процедури вiдсутнi опис типу її iменi, так як iм'я процедури нiяк не зв'язане з результатом; -для передачi результатiв процедури використовуються формальнi параметри в заголовку процедури, описанi за допомогою слова var. В описах програм-процедур i функцiй вiдрiзняються два типи параметрiв - параметри-змiннi i параметри-значення. Слово var перед iдентифiкатором в заголовку пiдпрограми означає параметр-змiнну, так як в процедурах iм'я процедури не використовується для передачi результату, для цього використовуються формальнi параметри-змiннi. Формальнi параметри-змiннi передають свої значення вiдповiдним фактичним параметрам при поверненнi з процедури у викликаючу програму. Приклад. Написати програму для обчислення значення чергового члена ряду Фiббоначчi. Послiдовнiсть чисел ряду Фiббоначчi має вигляд: 1,1,2,3,5,8,13,... program R; var I,N,X,Y: integer; procedure Fibo (var First,Second: integer); { опис процедури} var Fi: integer; begin Fi:=First; Second:=First+Fi end; begin X:=1; Y:=1; Readln(N); { вводиться кiлькiсть членiв ряду} Writeln('Числа Фiббоначчi':35); Write(X:1,',',Y:1); {вивiд результату} for I:=1 to N-2 do begin fibo(X,Y); {виклик процедури} Write(',',Y:1) {виведення результатiв} end; end.