Главная страница

учебник по паскалю. Программа 5 Алгоритм 5 Свойства алгоритма 6 Формы записи алгоритма 6


Скачать 2.21 Mb.
НазваниеПрограмма 5 Алгоритм 5 Свойства алгоритма 6 Формы записи алгоритма 6
Анкоручебник по паскалю.doc
Дата03.02.2017
Размер2.21 Mb.
Формат файлаdoc
Имя файлаучебник по паскалю.doc
ТипПрограмма
#1964
страница22 из 35
1   ...   18   19   20   21   22   23   24   25   ...   35

18.4. Открытые массивы



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

Способ подходит только для одномерных массивов. Использовать его с матрицами возможно, если интерпретировать матрицу как вектор (см. гл. 17).

Имеющиеся в программе векторы описываются в разделе var обычным способом, без определения типа type. В списке формальных параметров подпрограммы параметр-вектор указывается без диапазона размерности:

function sum(var x : array of real) : real;

При вызове подпрограммы фактический параметр-массив подставляется на место формального:

var a:array [1..5] of real;

s:real;

...

s:=sum(a);

Открытым остается вопрос -- как отслеживать из подпрограммы размерность переданного массива? Для этого в Паскале существуют стандартные функции Low и High. Их единственным параметром передается идентификатор массива, Low возвращает самое низкое допустимое значение индекса, а High -- самое высокое. Если A -- одномерный массив, величины Low(A) и High(A) можно непосредственно применять как границы цикла for:

function sum(var x : array of real) : real;

var i:word; s:real;

begin

s:=0;

for i:=Low(x) To High(x) Do s:=s+x[I];

sum:=s;

end;

Чтобы завершить пример, вызовем написанную функцию sum:

const a:array [1..5] of real=(1,2,3,4,5.5);

begin

writeln (sum(a):6:1);

end.

Как правило, номер первого элемента открытого массива равен нулю, однако, надежнее все-таки указывать Low. Приведем пример программы, включающей подпрограмму с открытыми массивами в качестве параметров.

Найти количество элементов вектора x[7], попадающих в интервал [0, 3] и количество элементов вектора y[5], попадающих в интервал [-1, 1].

Для ввода элементов массива с клавиатуры напишем процедуру Input, которой все-таки придется передавать размерность массива-параметра (ведь вводятся два вектора различной размерности). Поэтому в Input использован тот факт, что нумерация элементов открытого массива по умолчанию выполняется в нуля. Функции kol, вычисляющей количество элементов открытого массива, попадающих в интервал [x1,x2], достаточно стандартного указания Low и High:

var x:array [1..7] of real;

y:array [1..5] of real;

k1,k2,i:integer;
procedure Input (n:integer;

var a:array of real);

var i:integer;

begin

writeln ('Enter ',n,' items of array:');

for i:=0 to n-1 do read (a[i]);

end;
function Kol (var a:array of real;

x1,x2:real):integer;

var i,k:integer;

begin

k:=0;

for i:=Low(a) to High(a) do

if (a[i]>=x1) and (a[i]<=x2) then k:=k+1;

Kol:=k;

end;
begin

Input (7,x);

Input (5,y);

k1:=Kol(x,0,3);

k2:=Kol(y,-1,1);

writeln ('k1=',k1,' k2=',k2);

end.

Процедура Input могла бы быть реализована и без передачи фактической размерности отдельным параметром:

procedure Input (var a:array of real);

var i:integer;

begin

writeln ('Enter ',High(a)-Low(a)+1,

' items of array:');

for i:=Low(a) to High(a) do read (a[i]);

end;

{ . . . }

Input (x);

Input (y);

19. Множества и перечислимые типы



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

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

Для объявления множества достаточно записать оператор

set of тип;

где тип -- один из определенных программистом или предустановленных типов данных:

type charset: set of char;

var symbols: charset;

Вопреки этому примеру, стандартные типы данных мало применимы для множеств -- ведь исходный тип набора должен быть порядковым (см. п. 2.3) и не иметь более чем 256 различных значений с нижним и верхним пределом от 0 до 255 соответственно. Это связано с тем, что для хранения количества элементов множества выделяется только один байт оперативной памяти. Приведем другой пример для множества:

type charset= set of char;

var symbols:charset;

c1:char;

begin

symbols:=['A'..'Z','a'..'z'];

write ('Put one symbol:');

readln (c1);

if c1 in symbols then writeln ('OK')

else writeln ('Error');

end.

Из примера видно, что переменным типа множества можно присваивать список диапазонов соответствующего типа (мы уже знакомились с диапазонами в п. 7.8). В дальнейшем переменная типа множества может быть использована для контроля правильности входных данных с помощью оператора in:

if c1 in symbols then writeln ('OK')

Слева от оператора in может быть указано выражение любого перечислимого типа T, а справа -- набор с типом, совместимым с типом T.

Любые совместимые по типам данных множества можно объединять операций "+", вычитать операцией "-" и пересекать операцией "*". При этом результаты операций с множествами соответствуют правилам логики множеств:

  • порядковое значение c находится в множестве A+B только в том случае, если c находится в A или B;

  • порядковое значение c находится в множестве A-B только в том случае, если c находится в A и не находится в B;

  • порядковое значение c находится в множестве A*B только в том случае, если c находится и в A, и в B.

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

В следующем примере множество латинских букв получается операцией сложения подмножеств латинских прописных и латинских строчных букв.

type Latin = set of 'A'..'z';

const SmallLatin : Latin = ['A'..'Z'];

BigLatin : Latin = ['a'..'z'];

var LatinLetters : Latin;

c:char;

begin

LatinLetters := BigLatin + smallLatin;

repeat

write ('Введите символ или ',

'пробел для выхода:');

reset (input);

readln (c);

if c in LatinLetters then

writeln (c,' - латинская буква');

until c=' ';

end.

Как в примере выше, полезно бывает создавать из множеств подмножества при указании конструктора, содержащего выражения диапазонов в квадратных скобках [ ... ]:

type Digits = set of 0..9; {Множество цифр}

Letters = set of 'A'..'Z';

{Множество латинских букв}

const EvenDigits : Digits =

[0, 2, 4, 6, 8];

{Подмножество четных цифр}

Vowels : Letters =

['A', 'E', 'I', 'O', 'U', 'y'];

{Подмножество гласных букв}

HexDigits : set of '0'..'z' =

['0'..'9', 'A'..'F', 'a'..'f'];

{Символы 16-ричных чисел}

type shortWeekDays =

(Pn,Vt,sr,ch,Pt,sb,Vs);

{Перечислимый тип "дни недели"}

const Holidays : set of shortWeekDays

= [sb, Vs];

{Подмножество "Выходные" дней недели}

var wd:shortWeekDays;

{Переменная типа "Дни недели"}

i:integer;

begin

wd:=Pn;

for i:=1 to 7 do begin

if wd in Holidays then

writeln (ord(wd), ' - Выходной день')

else writeln (ord(wd), ' - Будний день');

Inc(wd);

end;

end.

Тип данных shortWeekDays в этом примере является перечислимым типом. Перечислимые типы определяют упорядоченные наборы значений, перечисляя идентификаторы, которые обозначают эти значения. Их порядок следует из последовательности, в которой они были перечислены. Оператор перечисления имеет общий вид

type имя = (идентификатор,

идентификатор,..., идентификатор);

Возможные значения перечисления, заданные оператором type, должны быть идентификаторами Паскаля, поэтому назвать дни недели по-русски в последнем описании type было бы невозможно.

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

type suit = (Club, Diamond, Heart, Spade);

При этом объявлении Heart является константой типа suit. Стандартная функция ord возвращает порядковый номер перечислимой константы, в нашем примере

ord(Club) = 0

ord(Diamond) = 1

ord(Heart) = 2

Как показано в листинге, переменным перечислимого типа можно присваивать константы, входящие в описание типа и увеличивать их значения как любые порядковые числа оператором Inc(wd), но эти значения нельзя читать или записывать "напрямую" операторами семейства read/write. В качестве альтернативы их можно приводить к целочисленным значениям стандартной функцией ord, при этом всегда первая константа списка имеет значение 0 (в нашем случае -- константа Pn). Оператор in в листинге позволяет проверить, попадает ли величина в подмножество, созданное для элементов исходного типа множества. Таким образом, основное назначение множеств и перечислимых типов -- удобная для человека запись выражений с "понятными" названиями констант вместо чисел. С точки зрения компилятора данные типа множества и перечисления являются целочисленными величинами.

Для ограничения диапазона исходных данных можно также непосредственно объявить тип-диапазон:

type Hour=0..23; minute=0..59;

Здесь объявлены переменные типов "час" и "минута", для переменных этих типов будут проверяться ограничения на попадание в указанные при описании диапазоны значений. Если переменной типа-диапазона присвоено недопустимое значение, программа отреагирует на это сообщением “Constant out of range”.

1   ...   18   19   20   21   22   23   24   25   ...   35


написать администратору сайта