Зарезервированное слово with
Обычно для получения доступа к полям записи необходимо всегда вначале указывать имя записи. Но применение зарезервированного слова with позволяет указывать имя записи только один раз. Это зарезервированное слово служит для определения блока, в котором можно непосредственно обращаться к полям указанной записи. Синтаксис записи блока with показан ниже:
with ИмяЗаписи do begin Поле_1:= значение; Поле_2:= значение; Поле_n:= значение; end;
Блок with позволяет уменьшить объем исходного кода, особенно при использовании записи с большим количеством полей или записи с действительно длинным именем.
with Book do begin Title:= 'Bring Me the Head of Prince Charming'; Authors[1]:= 'Roger Zelazny'; Authors[2]:= 'Robert Sheckley'; PageCount:= 280; end;
Следующий пример иллюстрирует определение полей записи в другой записи и использование массивов записей.
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils; type TSex = (sxMale, sxFemale);
TAuthor = record FirstName: string; MiddleName: string; LastName: string; Age: Integer; Sex: TSex; end;
TBook = record ISBN: string; Title: string; PageCount: Integer; Authors: array[1..4] of TAuthor; end;
var TownLibrary: array[1..100] of TBook; begin with TownLibrary[1] do begin Title:= 'StarShip Troopers'; with Authors[1] do begin FirstName:= 'Robert'; MiddleName:= 'A.'; LastName:= 'Heinlein'; Sex:= sxMale; end; end;
Readln; end.
Параметры массивов и открытых массивов В функции и процедуры массивы можно передавать в качестве параметров, но нельзя указывать диапазон для параметра-массива. В следующем примере дается объявление процедуры, которое приводит к ошибке компиляции.
procedure WriteStrings(Str: array [1..20] of string); Begin
end;
Если процедуре нужно передать массив, состоящий из 20 строк, потребуется создать новый тип данных, а затем создать процедуру, которая принимает новый тип данных в качестве параметра. Для создания нового типа данных необходимо использовать зарезервированное слово type.
Чтобы создать новый тип данных, который представляет массив из 20 строк, необходимо написать такой код:
program Project1;
{$APPTYPE CONSOLE}
Uses SysUtils; Type TSmallArray = array [1..20] of string; Begin
End.
Теперь, когда новый тип данных, представляющий массив, создан, его можно успешно передавать в качестве параметра процедуре или функции.
Type TSmallArray = array [1..20] of string;
procedure WriteStrings(StrArray: TSmallArray); Var item: string; Begin for item in StrArray do Writeln(item); end;
С этим решением связан один недостаток; процедура WriteString может принимать только переменную TSmallArray и, следовательно, мы ограничены массивом, состоящим из 20 строк. Если нужно работать с массивами других размеров, необходимо определить параметр типа открытого массива. Синтаксис параметра открытого массива аналогичен синтаксису объявления динамического массива:
procedure ИмяПроцедуры (ИмяМассива: array of ТипДанных);
Параметры открытого массива позволяют передавать процедуре или функции массивы различных размеров. При этом можно передавать статические и динамические массивы и массивы нестандартных типов.
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;
type TSmallArray = array[1..20] of string;
var SmallArray: TSmallArray; DynamicArray: array of string; StaticArray: array[1..100] of string;
procedure WriteStrings(StrArray: array of string); var item: string; begin for item in StrArray do Writeln(item); end;
begin WriteStrings(SmallArray); WriteStrings(DynamicArray); WriteStrings(StaticArray);
Readln; end.
Параметры открытого массива позволяют создавать массив непосредственно в вызове процедуры или функции. Этот процесс называют также передачей конструктора открытого массива. Конструктор открытого массива — это последовательность значений или выражений, заключенная в квадратные скобки и разделенная запятыми. Синтаксис использования конструктора открытого массива в вызове процедуры показан ниже:
procedure ИмяПроцедуры ([ выражение_1, выражение_2, выражение_n);
Для создания массива строк внутри вызова процедуры WriteStrings можно использовать следующую строку кода:
WriteStrings(['Open', 'Array', 'Constructor']);
Параметры открытого массива могут оказаться весьма полезными при необходимости создания вспомогательной функции или процедуры, которая может работать с диапазоном значений. Например, если нужно создать функцию, вычисляющей среднее значение параметров, версия функции, которая может принимать массив значений, значительно более удобна, чем те, которые не могут это делать.
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils, Math;
function Average(num1, num2: Integer): Integer; overload; inline; begin Result:= (num1 + num2) div 2; end;
{функции открытых массивов не могут быть помечены директивой inline} function Average(nums: array of Integer): Integer; overload; var n: Integer; begin Result:= 0; for n in nums do Inc(Result, n); Result:= Result div Length(nums); end;
begin Writeln(Average(2, 4)); Writeln(Average([56, 21, 33, 44, 59])); Readln; end.
Указатели и свободная память Три фундаментальных свойства, которые должна учитывать компьютерная программа при сохранении данных. Перечислим их здесь еще раз: • где хранится информация • какое значение там хранится • вид хранящейся информации Для реализации этих свойств использовался один из возможных методов — определение простой переменной. Оператор объявления определяет тип и символическое имя значения, а также заставляет программу выделить область памяти для значения и внутренними средствами отслеживать ее адрес. Теперь рассмотрим второй метод. Он приобретает особое значение при разработке классов. Этот метод основан на указателях, которые являются переменными, сохраняющими адреса значений вместо непосредственно самих значений. Но прежде чем рассматривать указатели, обратимся к способу явного определения адресов обычных переменных. Этот способ заключается в применении к переменной операции определения адреса, представленной знаком @. Например, если home — переменная, @home является ее адресом. Применение этого оператора продемонстрировано в листинге Программа 3_4 // использование оператора @ для определения адреса
program Project1;
{$APPTYPE CONSOLE}
Uses SysUtils; Var Donuts: Integer; Cups: Real;
Begin Donuts:= 6; Cups:= 4.5; Write('Donuts value = ', Donuts); Writeln(' and Donuts address = ', Integer(@Donuts)); Write('Cups value = ', Cups:1:1); Writeln(' and Cups address = ', Integer(@Cups));
Readln; end. Результат: Donuts value = 6 and Donuts address = 4252192 Cups value = 4.5 and Cups address = 4252196 При отображении адресов оператор WriteLn использует десятичное представление. В нашей реализации значение переменной donuts хранится в ячейке памяти с меньшей величиной адреса по сравнению с переменной cups. Разность между двумя адресами составляет 4. Это имеет смысл, поскольку переменная donuts имеет тип Integer, размерность которого составляет четыре байта. Конечно, в разных системах значения адресов будут различными. Кроме того, значение переменной cups может предшествовать в памяти значению переменной donuts. При этом разница адресов будет составлять 8 байтов, поскольку переменная cups имеет тип Real. Используя в таком случае обыкновенные переменные, можно обработать значение как именованную величину, а его адрес как производную величину. Теперь ознакомимся с принципом использования указателей. В соответствии с новой стратегией обработки хранящихся в памяти данных местоположение значения трактуется как именованная величина, а значение — как производная (порожденная) величина. Специальный тип переменной — указатель — содержит адрес значения. Таким образом, имя указателя представляет местонахождение значения в памяти. Применяя операцию ^, называемую косвенным значением или операцией разыменования, получаем значение, хранящееся по данному адресу. Предположим, что manly — это указатель. Тогда выражение manly представляет собой адрес, a manly^ — значение по данному адресу. Комбинация manly^ становится эквивалентом обычной переменной типа Integer. Эти моменты отражены в листинге 3_5. Здесь также показано, как объявлять указатель. Программа 3_5 // наша первая переменная-указатель program Project1; {$APPTYPE CONSOLE} Uses SysUtils; Var updates: Integer; //объявление переменной p_updates: ^Integer; //объявление указателя на значением типа Integer Begin
updates:= 6; p_updates:= @updates; //присвоение адреса значения типа Integer указателю //выражения значений двумя способами Writeln('Values: updates = ', updates, ', p_updates^ = ', p_updates^); //выражение адресов двумя способами Write('Addresses: @updates = ', Integer(@updates)); Writeln(', p_updates = ', Integer(p_updates)); //использование указателя для изменения значения p_updates^:= p_updates^ + 1; Writeln('Now updates = ', updates); Readln; end. Результат Values: updates = 6, p_updates^ = 6 Addresses: @updates = 4252192, p_updates = 4252192 Now updates = 7 Очевидно, что переменная updates типа Integer и переменная-указатель p_updates являются всего лишь двумя сторонами одной и той же медали. Переменная updates представляет прежде всего значение, а операция @ используется для получения адреса, тогда как переменная p_updates представляет адрес, а операция ^ служит для получения значения. Поскольку p_updates указывает на значение updates, выражения p_updates^ и updates совершенно эквивалентны. Выражение p_updates^ можно использовать точно так же, как переменную типа Integer. Как видно из программы, можно даже присваивать значения переменной p_updates^. При этом изменяется указываемое значение переменной updates.
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|