Set — Ключевое слово Delphi
При создании любой серьёзной программы не обойтись без дополнительных, более сложных, чем числа и строки, типов данных. В Delphi программист может для своих целей конструировать собственные типы данных. Чтобы ввести в программу (описать) новый тип данных, применяется оператор с ключевым словом type:
type название_типа = описание_типа;
Перечислимый тип — это тип данных, диапазоном значений которого является просто набор идентификаторов. Это может применяться в тех случаях, когда нужно описать тип данных, значения которого нагляднее представить не числами, а словами. Перечислимый тип записывается взятой в круглые скобки последовательностью идентификаторов — значений этого типа, перечисляемых через запятую. При этом, первые элементы типа считаются младшими по сравнению с идущими следом. Например, тип, описывающий названия футбольных команд, можно сформировать так:
type FootballTeam = (Spartak, Dinamo, CSKA, Torpedo, Lokomotiv);
var MyTeam: FootballTeam;
begin
MyTeam:=Spartak;
end;
Вообще, под перечислимыми типами понимают все типы, для которых можно определить последовательность значений и их старшинство. К ним относятся:
- все целочисленные типы, для которых всегда можно указать число, следующее за числом N;
- символьные типы (Char): за символом ‘a’ всегда следует ‘b’, за ‘0’ следует ‘1’, и так далее;
- логические типы — тип Boolean также представляет собой перечислимый тип: type Boolean = (false, true);
Структурные типы данных используются практически в любой программе. Это такие типы, как
- массивы
- записи
- множества
Массив — это структура данных, доступ к элементам которой осуществляется по номеру (или индексу). Все элементы массива имеют одинаковый тип.
Описание массива имеет вид:
type имя_типа_массива = array [диапазон] of тип_элемента;
Диапазон определяет нижнюю и верхнюю границы массива и, следовательно, количество элементов в нём. При обращении к массиву индекс должен лежать в пределах этого диапазона. Массив из ста элементов целого типа описывается так:
type TMyArray = array [1 .. 100] of Integer;
Теперь можно описать переменные типа TMyArray:
var A, B: TMyArray;
Вместо присвоения типа можно явно описать переменные как массивы:
var A, B : array [1..100] of Integer;
Для доступа к элементу массива нужно указать имя массива и индекс элемента в квадратных скобках. В качестве индекса может выступать число, идентификатор или выражение, значение которых должно укладываться в диапазон, заданный при описании массива:
Иногда требуется узнать верхнюю или нижнюю границу массива. Для этого служат встроенные функции:
High() — вернёт число, являющееся верхней границей массива;
Low() — вернёт число, являющееся нижней границей массива.
В скобки нужно подставить массив, границы которого требуется узнать.
Выражение B := A означает, что каждый элемент массива B будет равен элементу с таким же индексом массива A. Такое присвоение возможно только если оба массива объявлены через некий поименованный тип, или перечислены в одном списке. И в случае:
его использовать невозможно (но возможно поэлементное присвоение B[1] := A[2]; и т.д.).
Массивы могут иметь несколько измерений, перечисляемых через запятую. Например, таблицу из четырёх столбцов и трёх строк:
|
можно описать в виде массива с двумя измерениями:
type MyTable = array[1..4, 1..3] of Integer;
var X : MyTable;
Y : Integer;
begin
Y:=X[3, 2];
end;
Теперь в результате операции присвоения Y будет равен 7.
Многомерный, например, двумерный массив можно описать как массив массивов:
type TMyArray = array [1 .. 4] of array [1 .. 3] of Integer;
Результат будет аналогичен предыдущему примеру.
Каждое измерение многомерного массива может иметь свой собственный тип, не обязательно целый.
Кроме вышеописанных, так называемых статических массивов, у которых количество элементов неизменно, в Delphi можно использовать динамические массивы, количество элементов в которых допускается изменять в зависимости от требований программы. Это позволяет экономить ресурсы компьютера, хотя работа с такими массивами происходит гораздо медленнее. Описываются динамические массивы аналогично статическим, но без указания диапазона индексов:
type TDinArray = array of Integer;
var A : TDinArray;
После создания в динамическом массиве нет ни одного элемента. Необходимый размер задаётся в программе специальной процедурой SetLength. Массив из ста элементов:
Нижняя граница динамического массива всегда равна нулю. Поэтому индекс массива A может изменяться от до 99.
Многомерные динамические массивы описываются именно как массивы массивов. Например, двумерный:
type T3DinArray = array of array of Integer;
var A : T3DinArray;
В программе сначала задаётся размер по первому измерению (количество столбцов):
SetLength(A, 3);
Затем задаётся размер второго измерения для каждого из трёх столбцов, например: SetLength(A[0], 3); | Sets with EnumerationsA commonly used scenario in Delphi code is to mix both enumerated types and set types. Here’s an example: Question: will the message be displayed? Answer: no Sets in Delphi Control PropertiesWhen you need to apply «bold» to the font used in TEdit controls, you either use the Object Inspector or the following code: The Font’s Style property is a set type property! Here’s how it is defined: So, an enumerated type TFontStyle is used as the base type for the set type TFontStyles. The Style property of the TFont class is of type TFontStyles — therefore a set type property. Another example includes the result of the MessageDlg function. A MessageDlg function is used to bring up a message box and obtain the user’s response. One of the parameters of the function is the Buttons parameter of type TMsgDlgButtons. TMsgDlgButtons is defined as a set of (mbYes, mbNo, mbOK, mbCancel, mbAbort, mbRetry, mbIgnore, mbAll, mbNoToAll, mbYesToAll, mbHelp). If you display a message to the user containing Yes, OK and Cancel buttons and you want to execute some code if either the Yes or Ok buttons were clicked you can use the next code: Final word: sets are great. Sets might appear confusing to a Delphi beginner, but as soon as you start using set type variables you will find out they provide much more then it sounded in the beginning. Delphi» default » ключевое слово с типами записей в старых версиях Delphiу меня есть этот код в библиотеке объездов Delphi, которую я пытаюсь портировать: что значит » default » ключевое слово делать? Я!—6предположим что-то типа: правильно ли мое предположение? 1 ответовDefault() — недокументированная внутренняя функция, введенная для поддержки дженериков. Дизайн Delphi generics был сильно вдохновлен .NET generics, и вы можете извлечь выгоду из чтения analagous документации для .net:https://msdn.microsoft.com/en-GB/library/xwth0h0d.aspx цель Default() позволяет инициализировать переменную по умолчанию. При работе с универсальными типами Default() позволяет сделать это для переменной, тип которой является универсальным. если вы хотите воспроизвести поведение Default() сделать следующее: вызов Finalize необходимо в случае, если тип управляется. То есть, если тип управляется или содержит какие-либо управляемые члены. Управляемые типы включают строки, динамические массивы, интерфейсы, варианты, анонимные методы и т. д. если тип не содержит управляемых типов, то вызов Finalize можно опустить. Это не помешает включить его, Хотя, потому что компилятор устранит его, если он не нужен. Если вы можете быть на 100% уверены, что управляемым типам не назначено значение, вы также можете опустить этот вызов. инициализация по умолчанию означает следующее:
что такое использование встроенного ключевого слова в delphiКто-нибудь может сказать, как использовать встроенное ключевое слово в delphi 5 ответовЭто подсказка компилятору, что функция /процедура должна быть (если возможно) встроенной, то есть при вызове она должна быть расширена как макрос, а не вызываться. Это оптимизация для (очень) небольших функций, где затраты на вызов будут значительными. Вы найдете много примеров, например, в windows.pas Что на самом деле происходит, зависит от сложности функции, общего /частного доступа и вашей версии Delphi. Другие ответили, что делает inline, но я просто хотел отметить, что есть опция Compiler для включения, выключения или автоматического включения. Проверьте «Процедуры вызова и функции» в D2009 документах для очень хорошего объяснения механики inline. Вот ссылка на онлайн-документы: Он сообщает компилятору генерировать код для подпрограммы inline; в том месте, где она вызывается, вместо перехода к подпрограмме и обратно. Для процедур, которые переводятся в очень короткий ассемблер, это может быть преимуществом для производительности, потому что фактический код относительно короткий по сравнению с подготовкой параметра, фактическим вызовом и прологом /эпилогом процедуры. Если процедура слишком длинная, это может снизить производительность и испортить ваш код. Он заимствован из C в том смысле, что он сообщает компилятору, что это короткая подпрограмма, которая часто вызывается, и рекомендует, чтобы компилятор рассматривал функцию как макрос и интегрировал код функции непосредственно в программу в вызываемой точке, а не в используйте вызов функции. Это дает более быстрый код, потому что нет затрат на вызов функции, но за счет более крупной программы. Обратите внимание, что, как и в C, это рекомендация для компилятора, на самом деле это не обязательно, и оптимизатор может переопределить вас. Где это сделать? Ну, как разматывание петли, это метод, который очень редко используется в наше время. Классическое место для его использования — глубокая вложенная структура, критичная в реальном времени, например, рендеринг кода в графическом приложении, где несколько машинных вызовов, сбриваемых на каждой итерации, могут увеличить частоту обновления экрана. Нажмите Ctrl + Alt + C (все окно отладки ЦП) во время отладки в Delphi перед вызовом встроенной функции. И вы увидите, что встроенные функции запускаются без «вызова» и перехода к другому адресу. Это функция оптимизации. Set Of String?You are familiar with this block: Is there any way to declare Set Of STRING ? or is there similar code that i can use instead? The important part of this block is If C In mySet Then ShowMessage(‘Exists’); I wanna use something like this about a set of string. 5 Answers 5You can make use of this. Sets are implemented using bit arrays. So no, you cannot have a ‘set of string’. Use a TStringList instead, ie: The RTL System.StrUtils unit provides a very interesting method for this: Use it like this: It is shame, but Delphi still don’t have even very basic data structures, like sets. Suggestion of «Fabricio Araujo» is very limited in usage — you have to know all possible strings, so it is useless when you read them from somewhere. It is also impossible to have more then 256 items in such «alsmost set of strings». Remy Lebeau suggested to use TStringList for that purpose, but it is absolutely inefficient when you have big sets. In modern versions of Delphi it is possible to use TDictionary to keep unordered set of anything, including strings: It is case sensitive. If you need case insensitive implementation, you can make all strings lowercased before put/look then in set (use AnsiLowerCase function for that). Fabricio Araujo posted the best answer to the original question. For the question «Is MonthAbbr in the set of allowed abbreviations of month names?»
So your code might read For the implementation, the simplest general answer is to use a sorted TStringList in Delphi 7 (as the question is tagged). Зарезервированные слова Delphivar A, B : Integer; begin A:=3; B:=4; A:=A*A+B*B; end; if (условие) then (действие) else (альтернатива) ; Слова if (если), then (тогда), else (иначе) — зарезервированные. Действие и else альтернатива — это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие, если ложно, то выполняется альтернатива. (применяется, когда известно количество повторений цикла) for счётчик := выражение-1 to выражение-2 do действие ; Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto: for счётчик := выражение-1 downto выражение-2 do действие ; Цикл с предусловием (применяется, когда неизвестно количество повторений цикла) while условие do тело цикла ; Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу. Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к «зацикливанию» и «зависанию» программы. Цикл с постусловием (применяется, когда неизвестно количество повторений цикла) repeat тело цикла until условие ; Повторения сначала выполняет тело цикла, а затем уже проверяет выполнение условия: Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (т.е. true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until. Позволяет изменить последовательность выполнения программы. В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label: Перечислить возможные значения в DelphiУ меня есть алгоритм вычисления в Delphi с множеством различных опций, и мне нужно попробовать каждую комбинацию опций, чтобы найти оптимальное решение. Я задавался вопросом об использовании цикла Integer для их перечисления: Это не компилируется. Мне было интересно, был ли какой-нибудь довольно простой способ конвертировать из Integer в Set (большинство вопросов в Интернете пытаются пойти другим путем, от Set to Integer), и если да, то что это такое? Другая возможность — просто использовать Integer как бит-поле: а затем проверьте членство побитно и: Я пробовал это, и он работает, но похоже, что работа с наборами будет более естественной и лучше использовать систему типов (даже если я выйду за пределы указанной системы типов для перечисления наборов). Есть ли лучший/более безопасный способ перечисления всех возможных комбинаций комбинаций, чем перечисление основного целочисленного представления?
Set — Ключевое слово DelphiПрежде чем перейдем к дальнейшему описанию языка Delphi, формально опреде- CalculateValue Блог GunSmoker-а. when altering one’s mind becomes as easy as programming a computer, what does it mean to be human. 22 декабря 2008 г.Новое ключевое слово static в DelphiНедавно я переводил пост Почему методы класса должны быть помечены словом «static», чтобы их можно было использовать в качестве функции обратного вызова? Реймонда Чена. Там я оставил весь код «как есть» — на C++. Здесь я рассмотрю этот вопрос с точки зрения Delphi. Как известно, в языке есть такие сущности как процедуры/функции и методы. Причём начинающие программисты часто путают эти два понятия. Функция (в дальнейшем здесь будет также подразумеваться и процедура) — это код. Процедурная переменная — это указатель на код. Например: Метод — это тоже код, но код, связанный с классом. Указатель на метод — это ссылка на код + ссылка на конкретный объект. Например: Когда путают одно с другим компилятор чаще всего показывает такое сообщение: «Incompatible types: regular procedure and method pointer». Чаще всего или забывают писать «of object» в объявлении своих процедурных типов или пытаются передать в функцию (чаще всего как callback — т.е. функцию обратного вызова) метод класса вместо обычной функции (а самым упорным это иногда удаётся). Что делает эти две сущности такими принципиально несовместимыми? Функция — это просто код. Она не имеет связи с данными, отличными от тех, что передаются в её параметры. Методы класса помимо работы с параметрами (как и обычная функция) ещё могут оперировать с данными объекта (вот оно: «код» vs «код + данные»), например: С функциями такое невозможно — обратите внимание, как вы манипулируете с P3 (он же: Self.P3) в методе. Собственно сам объект (это встроенная переменная Self) неявно передаётся в метод первым параметром. Поэтому, если метод объявлен как function(const P1, P2: Integer): Integer of object — с двумя параметрами, то, на самом деле, он трактуется как функция с тремя параметрами: function(Self: TSomeObj; const P1, P2: Integer): Integer . Именно это различие (на бинарном уровне) делает несовместимыми обычные функции и методы. Соответственно, указатель на обычную функцию — это просто указатель (pointer), только что типизированный (это я про TDoSomethingFunc) — т.е. 4 байта. А вот указатель на метод — это уже запись или, если будет угодно, два указателя — один на код, второй — на данные, т.е. всего 8 байт. Понятно, что если у вас что-то предназначено для передачи указателя на функцию, то никакими силами указатель на метод вы туда не пропихнёте. Хотя бы потому, что размер у них разный. Ещё в Delphi есть классовые методы. Это такие методы, которые можно вызывать не имея на руках объект. В этом случае вместо объекта в неявный параметр Self передаётся информация о классе. Т.е. в классовых методах вы не можете использовать информацию о конкретном объекте (например, читать/писать его поля), но можете использовать информацию о классе — например, вызывать конструктор класса. Также методы класса могут быть виртуальными. Заметим, что сигнатура функции, реализующей метод, всё ещё совпадает с сигнатурой обычного метода: неявный параметр (данные класса вместо Self) + все явные параметры метода. Например: Теперь ещё один шажок и мы переходим к тому, о чём говорил Реймонд Чен. Классовый метод можно объявить статическим (только в новых версиях Delphi). В этом случае у него не будет неявного параметра. Разумеется, при этом он не может использовать информацию экземпляра и класса. Зато он и не отличается от обычной функции. Рассматривая пример с потоком, вот что мы могли бы написать в старых Delphi без поддержки статических классовых методов: Теперь, с введением нового ключевого слова static, появилась возможность писать так: При этом Реймонд говорит о том, что если у Execute сделать модель вызова stdcall, то бинарные сигнатуры параметра CreateThread, методов ThreadProc и Execute совпадут — поэтому, мол, умный компилятор уменьшит код ThreadProc до простого jmp. Увы, но компилятор Delphi не настолько умён — в этом случае он генерирует полный вызов вместе с передачей параметра. |