бесплатные рефераты

Алгоритмический язык Паскаль

Фактическим же параметром, соответствующим формальному параметру-переменной, является всегда переменная. На время выполнения процедуры эти параметры отождествляются, им соответствует одна и та же область памяти. Вполне понятно, что в этой ситуации изменения формального параметра влекут адекватные изменения фактического параметра, и после завершения процедуры его значение может отличаться от его первоначального значения.

Именно поэтому, объявив в процедуре параметр-результат как параметр-значение, этот результат так и останется в формальном параметре-переменной без его передачи в соответствующий фактический параметр.

5.2 Функции пользователя. Рекурсивные функции

Функция как объект языка Паскаль является другой версией реализации технологии построения программ с использованием структуры группирования. Можно также сказать, что функция есть частный вид определенного типа процедур, а именно, процедур с одним параметром - переменной.

Функция отличается от процедуры только тем, что всегда возвращает в точку вызова одно скалярное значение. При этом функция, как процедура, может содержать параметры-значения или быть без оных. Общая форма записи заголовка функции:

FUNCTION имя (список параметров: тип): тип;

или

FUNCTION имя: тип;

Тип результата есть тип значения функции. Список параметров такой же, что и для процедуры, только здесь все параметры-аргументы. Имя переменной, которая хранит значение функции, совпадает с именем функции.

Итак, заголовок функции отличается от заголовка процедуры не только сменой слова PROCEDURE на FUNCTION, но и удалением из списка параметров параметра-результата с присвоением его типа имени функции:

PROCEDURE <имя процедуры>(аргументы; VAR параметр-результат: тип);

| |

FUNCTION <имя функции> (аргументы): тип;

Другой особенностью описания функции является наличие в нем хотя бы одного оператора присваивания, в левой части которого стоит имя определяемой функции, а в правой - выражение для вычисления результата функции. Очевидно, что тип этого выражения должен совпадать с указанным в заголовке типом функции.

Вызов функции также отличается от вызова процедуры. Если вызов процедуры осуществляется с помощью специального оператора вызова (оператора процедуры), функция вызывается только с помощью некоторого выражения. Для того чтобы осуществить обращение к функции, необходимо использовать ее имя со списком фактических параметров в каком-либо выражении, тип которого совпадает с типом значения функции. Само же выражение, внутри которого вызывается функция, может быть правой частью оператора присваивания, частью логического выражения и пр.

Известно, что Паскаль имеет набор стандартных функций. Однако этот набор ограничен. Пользователь может по желанию расширить список функций, создав свои функции - функции пользователя. Так, например, в Паскале есть SQR(X) = X2, а вот функции F(X)= Xn, где n принадлежит множеству целых чисел Z, нет. Используя определенное ранее понятие функции, можно создать для этого универсальную функцию, которая давала бы степени произвольного вещественного числа с любым целым показателем.

Определим вещественную функцию POWER, которая должна иметь два параметра-аргумента - для показателя и для основания степени:

function POWER (FACTOR:real;EXPONENT:integer):real;

var COUNT: integer; TFACTOR: real;

begin

¦ if EXPONENT = 0 then POWER:= 1

¦ else begin

¦ ¦ TFACTOR:= FACTOR;

¦ ¦ for COUNT:= 2 to ABS(EXPONENT) do

¦ ¦ TFACTOR:= TFACTOR*FACTOR;

¦ ¦ if EXPONENT<0 then POWER:= 1/TFACTOR

¦ ¦ else POWER:= TFACTOR

¦ end

end;

Теперь можно эту функцию вызывать следующим образом:

а) РI:=POWER(3.14,1);

б) WRITELN("PI=",POWER(3.14,1):5:2);

в) IF X > 2*POWER(6.2,3) THEN WRITE('ДА');

г) A:= POWER(X,2) + POWER(X,3) + POWER(X,4).

К функциям можно обращаться тремя способами: из тела основной программы, из тела другой функции, из тела самой функции, т.е. функция, может вызывать саму себя. Функции называются рекурсивными, если в описании функции происходит вызов самой себя, а процесс обращения - рекурсией. Продемонстрируем использование рекурсии на примере вычисления значения факториала произвольного натурального числа N.

В математике известно рекурсивное определение факториала:

n! = 1, при n = 0;

n! = (n-1)!n, при n > 0.

Это рекурсивное определение можно реализовать с помощью соответствующей рекурсивной функции:

function FACTORIAL(VALUE:integer):integer;

begin

iF VALUE=0 then FACTORIAL:=1

else FACTORIAL:= VALUE*FACTORIAL(VALUE-1)

end;

Теперь можно обращаться к этой функции в теле основной программы, как показано в следующем примере:

program FINDFACTORIAL;

var N:integer;

begin

writeln('Введите число');

readln(N);

if N<0 then writeln('Нет факториала')

else writeln('Фактрориал',N,'равен',FACTORIAL(N))

end.

Мы видим, что характерной особенностью построенной функции является наличие в ее теле оператора присваивания.

FACTORIAL:= VALUE*FACTORIAL(VALUE-1), где происходит вызов определяемой функции. Здесь идентификатор FACTORIAL в левой части оператора обозначает имя переменной для хранения значения функции, а в правой - имя вызываемой функции.

Важным моментом при составлении любой рекурсивной функции является организация выхода из рекурсии. В некоторых простых случаях должно существовать не рекурсивное решение. Рекурсивный процесс должен шаг за шагом так упрощать задачу, чтобы в конце концов для нее появилось не рекурсивное решение. В этих функциях должны проверяться значения аргумента для принятия решения о завершении. В нашем случае условием завершения рекурсии является VALUE=0.

При описании рекурсивных функций необходимо хорошо представлять процесс вычислений. Всякая рекурсия состоит из двух этапов: углубление (погружение) внутрь рекурсии и выход из нее. На первом этапе никаких вычислений не производится, а идет только настройка рабочей формулы на конкретные операнды. На втором этапе происходит процесс вычислений по настроенным формулам.

Рассмотрим рекурсивный процесс на примере вычисления факториала для N = 3. Получим следующие шаги:

1) N = 3, где N<>0, следовательно, FACTORIAL:=3*FACTORIAL(2);

2) N = 2, где N<>0, следовательно, FACTORIAL:=2*FACTORIAL(1);

3) N = 1, где N<>0, следовательно, FACTORIAL:=1*FACTORIAL(0);

4) N =0, следовательно, FACTORIAL:=1,

т.е. получили не рекурсивное значение. Углубление в рекурсию закончено, далее пойдет процесс выхода из нее с выполнением необходимых вычислений.

В выражение 1*FACTORIAL(0) вместо FACTORIAL(0) подставляется его значение 1, вычисляется произведение 1*1 и оно становится значением FACTORIAL(1). В выражение 2*FACTORIAL(1) вместо FACTORIAL(1) подставляется значение 1, вычисляется 2*1 и становится значением FACTORIAL(2). В выражение 3*FACTORIAL(2) вместо FACTORIAL(2) подставляется значение 2, вычисляется 3*2 и становится значением переменной FACTORIAL, которая возвращает в основную программу значение 3!.

Весь этот двухэтапный рекурсивный процесс реализуется в памяти ЭВМ с помощью организации в ней стека рекурсии. Дело в том, что для хранения значений переменной N (а значит, и переменной VALUE) отводится не одна ячейка, а стек с именем N. В этот стек последовательно заносятся значения 3, 2, 1, 0, причем значение 0 есть признак конца заполнения стека. Затем начинает работать цикл с телом FACTORIAL:= FACTORIAL * N, где значения N выбираются последовательно из стека в порядке 1,2,3. Исходным же значением переменной FACTORIAL является 1, как значение 0!.

Работа стека представлена на следующей схеме:

Заполнение стека

Стек №

Вычисление

(углубление)

(разуглубление)

FACTORIAL:=1

0

FACTORIAL:=1

FACTORIAL:=1*FACTORIAL(0)

1

FACTORIAL:=1*FACTORIAL

FACTORIAL:=2*FACTORIAL(1)

2

FACTORIAL:=2*FACTORIAL

FACTORIAL:=3*FACTORIAL(2)

3

FACTORIAL:=3*FACTORIAL

В заключение покажем, что часто рекурсивные функции строятся гораздо проще, чем "обычные", хотя вполне понятно, что не всякая функция может быть переделана на рекурсивную. Сделаем это на примере уже построенной ранее функции POWER.

Данная функция явно носит рекурсивный характер, исходя из ее определения: Xn = 1, если n = 0;

Xn = (Xn-1)*X, если n > 1.

function POWER(FACTOR:real; EXPONENT:integer): REAL;

begin

if EXPONENT < 0

then POWER:=1/POWER(FACTOR,abs(EXPONENT))

else if EXPONENT > 0

then POWER:= FACTOR*POWER(FACTOR,EXPONENT-1)

ELSE POWER:=1

end;

ЗАМЕЧАНИЕ. Помимо рекурсивных функций в языке Паскаль можно определять по тому же принципу и рекурсивные процедуры. Подробно о них будет сказано в следующих разделах, а пока покажем, как рекурсивная функция может быть переделана в рекурсивную процедуру на примере вычисления факториала:

procedure FACTORIAL(VALUE:integer; var F: integer);

begin

iF VALUE=0 then F:=1

else begin FACTORIAL(VALUE-1,F);

F:=F*VALUE

end;

end;

Здесь уже, в отличие от функции FACTORIAL, для вычисления N! необходимо вызвать эту процедуру с помощью оператора процедуры FACTORIAL(N,FN), где FN - переменная для возвращения из процедуры значения N!.

6. МАССИВЫ. ДАННЫЕ ТИПА ARRAY

Скалярный тип - простой тип данных. Скалярное данное неделимо. Массивы - это структурированные типы данных. Массив состоит из нескольких элементов. Ко всему массиву можно обращаться по его имени. Можно обращаться к его элементу, но для этого надо задать индекс (индексы). Массивы бывают одномерные и многомерные. Для объявления массива необходимо задать типы его индексов и компонент.

Тип компонент массива - это просто тип данных, ассоциированный с каждой компонентой массива. Тип компонент может быть любым REAL, INTEGER, CHAR, BOOLEAN, перечислимым, интервальным. В качестве компоненты массива может быть взят и тип массив.

Тип индекса должен быть одним из упорядоченных типов, т.е. любым скалярным типом, кроме REAL: INTEGER, CHAR, интервальный, перечислимый. Тип индекса определяет границы изменения индекса. Если сделана попытка использовать несуществующую компоненту, то возникает ошибка (ошибка неверного индекса).

6.1 Одномерные массивы

Одномерный массив можно задать двумя способами:

а) с помощью служебного слова TYPE описывается тип массива, а затем с помощью VAR вводится переменная этого типа;

б) с помощью слова VAR сразу описывается переменная типа массив;

Например, объявление массива из 100 элементов типа REAL можно осуществить следующими двумя способами:

а) type R100 = array[1..100] of real;

var A: R100;

б) var A: array[1..100] of real.

Здесь задан массив с именем "А" и его элементы имеют имена: А[1],..., A[100]. Чаще всего для типа индекса используют интервальный тип на основе типов INTEGER и CHAR. Однако можно в качестве индексов брать перечислимый тип.

ПРИМЕР 1. Подсчет числа вхождений букв в текст определенной длины

program COUNTER;

var COUNT: array['a'..'z'] of integer;

CH: char; N: integer;

begin

for CH:= 'a' to 'z' do

COUNT [CH]:= 0; N:= 0;

repeat

read(CH); N:= N+1;

if (CH >= 'a') and (CH <= 'z') then

COUNT [CH]:= COUNT [CH]+1;

until CH = '.';

for CH:= 'a' to 'z' do

writeln(CH, COUNT [CH]:10, COUNT [CH]*100/N:10:2);

end.

ПОЯСНЕНИЕ. В этом примере тип индекса есть интервальный тип на базе типа CHAR, а тип компонент есть целое число. Таким образом, элементы массива - числа, а их индексы - буквы, т.е. число элементов массива равно 26 (число букв латинского алфавита). Рассмотрим теперь случай, когда тип индекса задан перечислимым типом, а компоненты массива представлены компонентами интервального типа на базе типа INTEGER.

ПРИМЕР 2. Присваивание переменной с именем месяца числа дней этого месяца

DAY:

Значение элементов

31

28

31

30

31

30

31

31

30

31

30

31

Значение Индексов

JAN

FEB

MAR

APR

MAY

JUN

JUL

AUG

SEP

OKT

NOV

DEC

program NUMBRDAY;

type MONAT = (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG,

SEP, OKT, NOV, DEC);

var DAY: array [MONAT] of 28..31; T: MONAT;

begin

for T:= JAN to DEC do

case T of

JAN, MAR, MAY, JUL, AUG, OKT, DEC: DAY[T]:= 31;

APR, JUN, SEP, NOV: DAY[T]:= 30;

FEB: DAY[T]:= 28;

end;

end.

6.2 Многомерные массивы

Для определения позиции элемента в двумерном массиве необходимы два индекса. Любой двумерный массив есть матрица, а матрица есть таблица. Поэтому удобно описывать двумерные массивы путем указания границ изменения индексов (номеров) строк и столбцов.

Например, таблица символов M x N, где M - число строк и N - число столбцов, может быть описана:

var TAB: array[1..M, 1..N] of char.

ОБЩАЯ ФОРМА ЗАПИСИ

VAR <имя>:ARRAY [тип индекса строки, тип индекса столбца]

OF <тип компонент>;

Однако, двумерный массив можно интерпретировать как вектор-столбец, каждый элемент которого в свою очередь является одномерным массивом (вектор - строка). Этот подход к определению двумерного массива влечет его описание с помощью двух строк, где первая содержит описание строки, а вторая - описание столбца:

type LINE = array[1..N] of char;

STOLB = array[1..M] of LINE;

var TAB: STOLB.

Здесь TAB[I] - переменная типа LINE, а TAB[I][J] - переменная

типа CHAR.

ОБЩАЯ ФОРМА ЗАПИСИ

TYPE <тип строки>=ARRAY [тип индекса] OF <тип компонент>;

<тип столбца> = ARRAY[тип индекса] OF <тип строки>;

VAR <переменная массива>: <тип столбца(массива)>;

Эти два вида определения массивов задают и два способа обращения к элементам массива: TAB[I,J] - в первом случае и TAB[I][J] - во втором.

Вполне очевидно, что сказанное выше для двумерного массива распространяется и на массивы большей размерности. Например, описание VAR CUBE: ARRAY[1..M, 1..N, 1..K] OF INTEGER определяет задание трехмерного массива целых чисел.

6.3 Способы работы с массивами

Обработка массивов включает в себя, как правило, следующие компоненты: ввод массива (с клавиатуры или с помощью датчика случайных чисел), вывод полученного массива на экран и собственно его обработка. Все эти компоненты рекомендуется оформлять в виде отдельных процедур. При этом надо учитывать следующий фактор: если процедуре (или функции) будет передаваться массив, то надо объявить в ней этот массив как параметр с атрибутом VAR даже в том случае, если значение массива внутри процедуры не изменяется. Это нужно для того, чтобы не тратить времени и памяти на размещение внутри процедуры копии массива. Заметим, что параметр обязательно должен относиться к типу, имеющему имя.

ПРИМЕР 3. Сумма элементов таблицы над верхней диагональю

program SUMMA;

const M =...; {число строк таблицы}

N =...; {число столбцов таблицы}

type LINE = array[1..n] of integer;

TAB = array[1..m] of LINE;

var s,i,j:integer; MAS:TAB;

procedure VVODMASSIV(var MAS:TAB);

begin

¦ for i:=1 to M do

¦ for j:=1 to N do

¦ readln(MAS[i][j]);

end;

procedure VIVODMASSIV(var MAS:TAB);

begin

¦ for i:=1 to M do

¦ begin

¦ ¦ for j:=1 to N do

¦ ¦ write(MAS[i][j]:5,' '); writeln;

¦ end;

end;

procedure OBRABOTKA(MAS:TAB; var SUM:integer);

begin

¦ SUM:= 0;

¦ for i:=1 to M do

¦ for j:=1 to N do

¦ if j > i then SUM:= SUM+MAS[i][j];

end;

begin

¦ VVODMASSIV(MAS); writeln('исходный массив');

¦ VIVODMASSIV(MAS); OBRABOTKA(MAS,s);writeln;

¦ writeln('сумма элементов = ',s);

end.

7. ОБРАБОТКА ЛИТЕРНЫХ ВЕЛИЧИН. ДАННЫЕ ТИПА CHAR И STRING

В Паскале, как и в других языках программирования, предусмотрена обработка текстов или строк. Для этой цели в языке существуют два типа данных: SHAR и STRING.

7.1 Тип данных CHAR

Типу данных CHAR соответствуют символьные константы и переменные. Символьная константа есть какой-то символ алфавита, взятый в кавычки. Символьные переменные получают значения символьных констант через оператор присваивания:

ALPFA:='p'; A:='t'; B:='3'; C:=' '; D:=''.

Все символы алфавита образуют множество литер. Каждый символ имеет свой код в ASCII. Это позволяет использовать булевские сравнения: =, <>, <, <=, >, >=.

Данные этого типа описываются с помощью служебного слова CHAR.

Например, переменную ALPFA можно описать VAR ALPFA: CHAR.

ОБЩАЯ ФОРМА ЗАПИСИ: VAR <переменная>: CHAR;

При работе с данными типа CHAR, если у нас есть последовательность символов, существуют два способа ввода этих символов с клавиатуры.

При первом способе организуется цикл с помощью одного из операторов цикла, внутри которого помещается оператор READLN. При этом способе элементы последовательности вводятся поочередно и после набора на клавиатуре символа необходимо нажать клавишу ввода ENTER. Таким образом, здесь число нажатий клавиши ENTER совпадает с числом вводимых элементов последовательности.

ПРИМЕР 1. С клавиатуры последовательно вводятся символы. Признаком конца ввода является точка. Составить программу выбрасывания групп символов, расположенных между скобками (,). Сами скобки тоже выбрасываются

program SKOBKI;

var c: char; i: integer;

begin

¦ i:=0; read(c);

¦ while c <> '.' do

¦ begin

¦ ¦ if c='(' then i:=1

¦ ¦ else if c = ')' then i:=0

¦ ¦ else if i=0 then write(c);

¦ ¦ read(c);

¦ end;

end.

ПОЯСНЕНИЕ. I = 1 означает, что ранее была прочитана левая скобка, которой пока еще не нашлось парной правой. В этой ситуации прочитанные символы не выводятся на экран. В результате работы этой программы на экране будет представлена строка символов. Здесь вся последовательность символов вводится сразу по первому оператору READ, а затем в цикле из буфера клавиатуры выбираются, анализируются и печатаются символы вне круглых скобок. Например, если вводится последовательность "asg(zx)ytr.", то экран будет выглядеть так:

asg(zx)ytr. - результат работы оператора READ;

asgytr - результат работы оператора WRITE.

В этой программе можно было бы использовать оператор READLN, но тогда после набора каждого символа необходимо нажимать клавишу ввода. Кроме того, на экран будет выводиться не строка символов, а столбец, состоящий из вводимых и отпечатанных элементов. Например, при вводе последовательности "asg(zx)ytr." экран уже будет выглядеть так:

a g x t

a | g |) | t

s | (| y | r

s z y r.

Упорядоченность символов языка используется при написании циклов с параметром, где параметр цикла может пробегать буквенные значения.

ПРИМЕР 2. Программа вывода последовательности букв:

a,ab,abc,...,abc...xyz

program SUITE; РАБОТА ПРОГРАММЫ

var c,d: char; a

begin ab

for c:='a' to 'z' do abc

begin abcd

for d:='a' to c do write(d); abcde

writeln(' ');...

end; abcde...xyz

7.2 Массивы литер

В рассмотренных программах все символы вводились последовательно в процессе работы цикла или хранились временно в буфере клавиатуры. Это не всегда удобно. Поэтому в языках делают строки как последовательность литер. Строку можно задать, как массив литер, при этом в качестве длины строки может выступать верхняя граница массива. Например, VAR HAMLET: ARRAY[1..17] OF CHAR.

Здесь HAMLET - массив литер, компоненты которого имеют тип CHAR; индекс имеет нижнюю границу, равную 1, верхнюю - 17. Для ввода строки в массив HAMLET необходимо организовать цикл из 17 повторений. При каждом повторе этого цикла с клавиатуры вводится очередной символ строки и нажимается клавиша ввода:

Поскольку массивы литер являются обычными массивами, но их компоненты имеют тип CHAR, то они обладают всеми свойствами регулярных массивов. Для извлечения из массива-строки отдельного символа необходимо использовать индекс этого элемента. Например, можно вывести на экран строку HAMLET в обратном порядке с помощью следующего цикла:

for n:=17 downto 1 do write (HAMLET [n]).

ПРИМЕР 3. Дана последовательность символов CHAR: S1,S2,...,S10. Определить, совпадает ли начальная часть с ее конечной частью

program SOWPADENIE;

label 1;

type t = array[1..5] of char;

var s:t; y:char; i:integer;

begin

¦ for i:=1 to 5 do read(s[i]); readln;

¦ for i:=1 to 5 do

¦ begin

¦ ¦ read(y);

¦ ¦ if s[i] <> y then

¦ ¦ begin

¦ ¦ ¦ write('не совпадает');

¦ ¦ ¦ goto 1;

¦ ¦ end;

¦ end;

¦ write('совпадает'); 1:;

end.

ПОЯСНЕНИЕ. В данной программе сначала вводятся по циклу первые пять членов последовательности в массив S[I], причем все пять символов набираются сразу и набор завершается клавишей ввода. Затем с помощью оператора READLN очищается буфер клавиатуры, куда оператор READ(Y) заносит следующие пять символов. Во втором цикле из этого буфера поочередно выбираются символы и сравниваются с ранее введенными. Если все символы совпадают, то печатается текст 'совпадает'. В случае несовпадения печатается текст 'не совпадает' и дальнейшее считывание символов из буфера клавиатуры прекращается.

Чтобы не вводить всю вторую половину символов, а ограничиться только вводом до первого несовпадающего символа, необходимо в программе заменить оператор READ(Y) на оператор READLN(Y).

7.3 Тип данных STRING

Наряду с тем положительным, что дают нам массивы литер, они обладают существенным недостатком: их длину нельзя менять во время выполнения программы. Так в рассмотренном примере пункта 2.2 переменная HAMLET есть массив из 17 элементов и, следовательно, туда можно поместить только текст, содержащий ровно 17 символов.

Это не всегда удобно. Хотелось бы иметь такую переменную, в которую можно было бы поместить текст произвольной (но ограниченной) длины. Такую возможность предоставляет тип STRING. Здесь, объявив переменную:

var HAMLET: string[17],

можно ей путем оператора присваивания (а не через цикл) задать значение текста произвольной длины (от 0 до 17).

НАПРИМЕР:

HAMLET:= 'Быть или не быть';

HAMLET:= 'Бедный Йорик';

HAMLET:= ' '; HAMLET:= ''.

Отметим также, что при компиляции программы в случае объявления строки-массива в памяти ЭВМ резервируется место под массив, который должен быть полностью заполнен потом в процессе работы программы. Для типа STRING также резервируется место в памяти того же объема, но здесь необязательно его заполнять целиком. Незаполненные места представлены пробелами.

ОБЩАЯ ФОРМА ЗАПИСИ:

TYPE <имя типа> = STRING [N];

VAR <имя переменной>: <имя типа>;

или

VAR <имя переменной>: STRING [N];

Здесь N - целая константа, задающая максимальную длину текста.

Доступ к элементам строки производится с помощью индексов, т.к. в этом типе также все элементы имеют свой (числовой) индекс от 1 до N. В результате получается величина типа CHAR.

НАПРИМЕР: HAMLET:= 'ПРОГРАММА';

HAMLET [1] = 'П'; HAMLET [9] = 'А'.

Строковое выражение состоит из строковых (символьных) констант, переменных, указателей строковых функций и операции конкатенации (склеивания) строк, обозначаемой знаком "+". Строки можно сравнивать. В результате сравнения двух строк, получается истина только в том случае, если сравниваемые строки совпадают посимвольно и имеют одинаковую длину (принадлежат одному и тому же типу).

Текущая длина строковой переменной может быть определена с помощью встроенной функции LENGTH. Например, можно распечатать в цикле значение строки HAMLET:

for c:=1 to length(HAMLET) do write(HAMLET [c]).

Конечно, подобные циклы не надо использовать в реальных программах. Переменные типа STRING могут быть напечатаны с помощью единственного оператора WRITE или WRITELN. Для того, чтобы ввести значение типа STRING, необходимо использовать READLN или READ.

При этом, в отличие от ввода строки-массива, в типе STRING вся строка вводится целиком - клавиша ENTER нажимается один раз после последнего введенного символа.

ПРИМЕР 4. С клавиатуры вводится последовательность слов длиной в 4 символа. Напечатать эти слова, пока не встретится слово STOP.

Программа решения этой задачи зависит от способа введения слов с клавиатуры. Если слова вводятся отдельно друг от друга и после ввода слова сразу идет его печать, то это может быть реализовано с помощью следующего цикла:

repeat

readln(LINE_OF_TEXT); writeln(LINE_OF_TEXT);

until LINE_OF_TEXT = 'STOP',

где LINE_OF_TEXT есть переменная типа STRING[4].

Последовательность слов может быть введена сразу целиком, и для этого совсем необязательно вводить специальную переменную для хранения этого "длинного" слова. Здесь можно воспользоваться буфером клавиатуры для временного хранения всей последовательности слов. Оператор же READ в цикле будет "откусывать" от буфера по 4

символа, а оператор WRITELN - печатать это слово:

repeat

read(LINE_OF_TEXT);

writeln(LINE_OF_TEXT);

until LINE_OF_TEXT = 'STOP'.

Заметим, кстати, что если в программах с подобным циклом еще будут операторы READ, то рекомендуется перед ними сделать очистку буфера с помощью READLN.

Следует отметить также, что в первом случае слова можно вводить и меньшей длины, но работа завершится по набору слова STOP. Во втором случае (при наборе сплошной последовательности слов) выход из цикла будет реализован только при наличии в этой последовательности числа символов, кратных 4, из них последние 4 символа есть слово STOP.

7.4 Строковые функции и процедуры

Они введены для облегчения манипуляции со строками. Имеется 8 строковых функций и процедур.

1. Функция CONCAT (склеивание).

Синтаксис: concat(S1, S2,..., Sn: string): string.

Возвращает строку, полученную конкатенацией строк S1,...,Sn.

ПРИМЕР: NUMBER:= concat('12','34','50'); NUMBER = '123450'.

2. Функция LENGTH(длина).

Синтаксис: length(S: string): integer.

Возвращает длину строки S.

ПРИМЕР: N:= length('345'); N = 3.

3. Функция POS(позиция).

Функция POS в качестве аргументов использует две строки и определяет, содержится ли первая строка во второй. Возвращает номер символа, начиная с которого S входит в T. Если вхождения нет, то возвращает 0.

ПРИМЕР: N:= pos('E','HELLO'); N:= pos('A','HELLO');

N = 2. N = 0.

4. Функция COPY(вырезка фрагмента).

Синтаксис: copy(S: string; N1,N: integer): string.

Возвращает подстроку, полученную из N символов строки S, начиная с позиции N1. Значение переменной S при этом не меняется.

ПРИМЕР: FRAGMENT:= copy('PROGRAMM',2,3);

FRAGMENT = 'ROG'.

5. Процедура DELETE (стирание фрагмента).

Убирает из строки S LEN символов, начиная с POS, при этом длина строки уменьшается на LEN позиций.

ПРИМЕР: delete(FRAGMENT,2,3);

FRAGMENT:= 'PROGRAMM'; FRAGMENT = 'PRAMM'.

6. Процедура INSERT(вставка).

Синтаксис: insert(S: string; var D: string; POS: integer).

Вставляет строку S в строку D перед символом с номером POS, при этом длина строки D увеличивается на LENGTH(S) позиций.

ПРИМЕР: insert ('ROG', FRAGMENT, 2);

FRAGMENT:= 'PRAMM'; FRAGMENT = 'PROGRAMM'.

7. Процедура STR(преобразование в строку).

Синтаксис: str(I: integer; var S: string);

str(R: real; var S: string).

Преобразует I или R из числа в строку и записывает эту строку в S, причем R и I могут записываться форматно, как в процедуре WRITE.

ПРИМЕР: a) R:= 123.654; str(R:5:2, S); S = '123.65';

б) I:= 5683; str(I, S); s = '5683'.

8. Процедура VAL(преобразование в число).

Синтаксис: val(S: string; var I, J: integer).

val(S: string; var I: real; var J: integer).

Преобразует строковую переменную S в число типа I. Переменная J получает значение 0, если перевод прошел без ошибок. Если же сделана попытка конвертировать в число строку, где есть нецифровые символы, то переменная J принимает значение позиции первого нецифрового символа, при этом работа процедуры будет прервана.

ПРИМЕР: S:= '4326'; S:= '43p8';

val (S,I,J); val (S,I,J);

I = 4326, J = 0 I - не определено, J = 3.

Рассмотрим теперь пример на применение указанных функций и процедур обработки строк.

ПРИМЕР 4. Изменение порядка слов в строке

program REVERSE;

var OLD_LINE, NEW_LINE: string[50];

PROBEL: integer; WORD: string[50];

begin

¦ NEW_LINE:= ''; readln(OLD_LINE);

¦ OLD_LINE:= concat(OLD_LINE,' ');

¦ while OLD_LINE <> '' do

¦ begin

¦ ¦ PROBEL:= pos(' ', OLD_LINE);

¦ ¦ word:= copy(OLD_LINE, 1, PROBEL);

¦ ¦ NEW_LINE:= concat(WORD, NEW_LINE);

¦ ¦ delete(OLD_LINE, 1, PROBEL);

¦ end;

¦ writeln(NEW_LINE)

end.

ПОЯСНЕНИЕ. С клавиатуры вводится строка OLD_LINE и к ней справа подклеивается пробел. Это делается для того, чтобы строка имела одну и ту же структуру: слово плюс пробел. Затем в цикле, признаком конца которого является пустая константа, выделяется очередное по порядку слово и подклеивается слева в переменную NEW_ LINE. После выборки очередного слова из OLD_LINE оно оттуда выбрасывается, что приводит к постепенному уменьшению строки. Здесь переменная PROBEL служит для хранения позиции первого пробела в строке, а WORD - для выбранного из OLD_LINE слова.

Например, строка ' Наша Таня громко плачет' преобразуется в строку ' плачет громко Таня Наша'.

8. МНОЖЕСТВА. ДАННЫЕ ТИПА SET

Тип в программировании - это множество, для которого определен некоторый набор операций над его элементами. Сами элементы множества называются объектами (или значениями) данного типа. В языке Паскаль рассматриваются различные типы данных, которые по своей организации подразделяются на отдельные виды. Прежде всего следует отметить, что все типы данных делятся на стандартные и нестандартные.

Стандартные: REAL, INTEGER, CHAR, BOOLEAN. Для каждого из этих типов рассматриваются соответствующие операции над его элементами. В Паскале имеются средства, позволяющие определять, исходя из имеющихся типов, новые нестандартные типы. Примерами таких нестандартных типов являются данные типа STRING и ARRAY, т.е. литерный тип и массивы. Массив - это упорядоченный набор данных одного типа, у каждого из которых есть индекс (номер). Способ индексации, тип элементов, длина массива содержатся в определении того типа, которому принадлежит массив:

TYPE T = ARRAY[1..20] OF REAL.

Это определение типа, имя которого T. Объектами типа T будут упорядоченные наборы по 20 элементов, имеющих тип REAL; диапазон изменения значения индекса от 1 до 20. Определив с помощью TYPE тип T, можно теперь описать некоторую переменную этого типа:

Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11


© 2010 РЕФЕРАТЫ