program VarPar;
{ Простая программа, демонстрирующая пример использования переменного
числа параметров заданного типа в Delphi.
Создано в марте 1995, автор Hallvard Vassbotn
hallvard@falcon.no
}uses WinCrt, SysUtils;
{ предопределения в System:
const
vtInteger = 0;
vtBoolean = 1;
vtChar = 2;
vtExtended = 3;
vtString = 4;
vtPointer = 5;
vtPChar = 6;
vtObject = 7;
vtClass = 8;
type
TVarRec = record
case Integer of
vtInteger: (VInteger: Longint; VType: Byte);
vtBoolean: (VBoolean: Boolean);
vtChar: (VChar: Char);
vtExtended: (VExtended: PExtended);
vtString: (VString: PString);
vtPointer: (VPointer: Pointer);
vtPChar: (VPChar: PChar);
vtObject: (VObject: TObject);
vtClass: (VClass: TClass);
end;
}const
TypeNames: array[vtInteger..vtClass] of PChar =
('Integer', 'Boolean', 'Char', 'Extended', 'String',
'Pointer', 'PChar', 'Object', 'Class');
{
Согласно on-line документации (поиск по слову TVarRec), массив параметров
array of const интерпретируется компилятором подобно массиву array of TVarRec.
Данный пример будет работать подобно тому, как если бы вы изменили
объявление TestMultiPar на:
procedure TestMultiPar(const Args: array of TVarRec);
Вы можете сделать реализацию обычного "очистителя" (без объявления
переменных), но интерфейс был бы менее понятным пользователям данного
модуля.
Компилятор видит параметры и формирует массив непосредственно в
стеке. Для каждого элемента массива также устанавливается поле
VType с одной из предопределенных констант vtXXXX. Фактически
значение всегда передается в виде четыре байта информации. Для
типов Boolean и Char полезную информацию содержит только первый
байт.
Теперь вы можете писать все те же хорошие программы, но вдобавок
поддерживающие переменное количество параметров с проверкой типов!
}function PtrToHex(P: pointer): string;
begin
Result := IntToHex(Seg(P^), 4) + ':' + IntToHex(Ofs(P^), 4);
end;
procedure TestMultiPar(const Args: arrayofconst);
var
ArgsTyped: array[0..$FFF0 div sizeof(TVarRec)] of TVarRec absolute Args;
i: integer;
beginfor i := Low(Args) to High(Args) dowith ArgsTyped[i] dobegin
Write('Args[', i, '] : ', TypeNames[VType], ' = ');
case VType of
vtInteger: writeln(VInteger);
vtBoolean: writeln(VBoolean);
vtChar: writeln(VChar);
vtExtended: writeln(VExtended^: 0: 4);
vtString: writeln(VString^);
vtPointer: writeln(PtrToHex(VPointer));
vtPChar: writeln(VPChar);
vtObject: writeln(PtrToHex(Pointer(VObject)));
vtClass: writeln(PtrToHex(Pointer(VClass)));
end;
end;
end;
var
MyObj: TObject;
begin
Writeln('Проверка выполнения функции с переменным количеством параметров и проверкой типов:');
MyObj := TObject.Create;
TestMultiPar([123, 45.67, PChar('ASCIIZ'), 'Здравствуй, мир!', true, 'X',
@ShortDayNames, TObject, MyObj]);
MyObj.Free;
{ Для того, чтобы обеспечить предварительную проверку типа при передаче параметров,
попробуйте следующее: }
writeln(Format('%d', ['привет']));
{ Переданный параметр не является ожидаемым типом. Строка формата '%d'
говорит о том, что параметр должен быть целой величиной, но вместо этого мы передаем
строку. Во время выполнения это вызовет исключительную ситуацию, и если вы не организовали
ловушку для объектов исключения, то Delphi выведет вам строку с описанием ошибки.
Использование функции C-типа sprintf в этом случае может привести к непредсказуемым
последствиям (читай: крах системы, GP и все что угодно) }end.
Программа на Delphi демонстрирует использование переменного количества параметров с проверкой типа. Используется запись TVarRec, чтобы хранить информацию о каждом параметре, включая его значение и тип.
Процедура TestMultiPar принимает массив константных значений как параметр, который затем конвертируется в массив записей TVarRec с помощью ключевого слова absolute. Это позволяет программе доступ к отдельным элементам массива и определить его тип.
Внутри цикла программа использует оператор case, чтобы обрабатывать каждый тип значения differently. Например, если значение является целым числом, оно будет печататься в виде строки; если это булево значение, оно будет печататься как "True" или "False".
Функция PtrToHex используется для конвертации значения указателя в строку hexadecimal.
Сюда входят следующие шаги:
Определена запись TVarRec с оператором case, который определяет тип каждого элемента.
Объявлен массив TypeNames, содержащий строки, представляющие каждый из возможных типов.
Процедура TestMultiPar принимает массив константных значений как параметр и конвертирует его в массив записей TVarRec с помощью ключевого слова absolute.
Внутри цикла программа использует оператор case, чтобы обрабатывать каждый тип значения differently.
Функция PtrToHex используется для конвертации значения указателя в строку hexadecimal.
Пример демонстрирует, как использовать переменное количество параметров с проверкой типа в Delphi. Он также показывает, как использовать ключевое слово absolute, чтобы доступ к отдельным элементам массива, и оператор case, чтобы обрабатывать различные типы значений.
В этом альтернативном решении используется функция Format, чтобы печатать значения параметров, и оно avoids использование оператора case внутри цикла. Вместо этого, оно использует одиночную строку writeln с форматированной строкой, которая зависит от типа значения.
Примечание: это программа предполагает, что запись TVarRec была определена так же, как в оригинальном коде.
Пример программы на Delphi, демонстрирующий использование переменного количества параметров с проверкой типов.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.