Boolean — Тип Delphi


Обучающий курс. 10. Логические выражения в Delphi

Логические выражения — тема сравнительно небольшая, но очень важная. Логические выражения встречаются практически в каждой программе. Понять принцип их работы очень важно, чтобы при написании программ в Delphi не возникало трудностей с проверкой каких-либо данных.

Логический тип данных

С логическим типом данных мы уже неоднократно встречались при изучении свойств объектов. Этот тип данных состоит всего из двух значений: истина и ложь . На языке Pascal (а также на многих других языках) это соответственно True и False . В некоторых языках допускается использование чисел вместо этих переменных: 1 — истина, 0 — соответственно ложь. Итак, логический тип данных указывает, есть ли что-то или его нет, верно ли что-то или неверно.

В Pascal логический тип данных носит название Boolean (англ. — логический ). Значения, как уже было сказано — True и False . Простой пример объявления логической переменной и присвоения ей значения «ложь»:

Операции над логическими выражениями

А вот и самое интересное. Для логических выражений введены 4 операции. Работа с ними чем-то похожа на работу с числами. Рассмотрим подробно эти операции.

1. Отрицание: NOT («не»)

Как понятно из названия, данная операция меняет значение логического выражения на противоположное: если была истина, то станет ложь, а если была ложь, то станет истина. Выражение, над которым будет произведена операция, указывается либо после слова NOT через пробел, либо в скобках. Примеры:

m := not (k);
n := not m;
p := not ( not (m));

Подразумевается, что все переменные описаны типом данных Boolean . Итак, разберём, что здесь происходит:

  • Сначала мы присваиваем переменной k значение True ;
  • Далее, выполняя NOT для k получаем False: m становится равным False ;
  • n становится противоположным m , т.е. True ;
  • Над m делается двойное отрицание, т.е. значение p станет также False .

2. Логическое умножение (конъюнкция) — AND («и»)

В отличие от рассмотренного выше NOT , оператор AND работает уже с двумя (и более) выражениями. Логическое умножение равно истине тогда и только тогда, когда все выражения, связанные этим оператором, истинны. Если хотя бы один является ложью, то весь результат будет также ложью. Поэтому, собственно, операция и называется умножением: если истину обозначить за 1, а ложь — за 0, а числа перемножить, то при наличии хотя бы одного нуля весь результат будет нулевым. Примеры:

a := True;
b := False;
c := True;

d := a and b;
e := a and c;
f := not (b) and c;

Значение d будет False , т.к. один из операндов ( операнды — выражения, которыми управляют операторы) равен False ( b ). Переменная e примет значение True , ведь и a и c истинны. Наконец, f тоже станет True , ведь not(b) — это истина и c тоже истина.

3. Логическое сложение (дизъюнкция) — OR («или»)

Как и AND , OR работает с несколькими операндами. Название «или» уже отвечает на вопрос «что будет в итоге»: если хотя бы один из операндов — истина, то всё выражение будет истиной. Результат False будет только в случае, если все операнды будут ложными.

a := False;
b := True;

c := a or b;
d := not (b) or a;

Значение переменной c станет True , а переменной d — False .

4. Исключающее «или» — XOR

Данная операция выдат результат True , если один из операндов является истиной, а другой — ложью, т.е. выражения не должны быть одинаковыми.

a := True;
b := False;

c := a xor b;
d := not (a) xor b;
e := not (a) xor not (b);

Переменная c станет истиной, ведь a и b различны, а d — ложью, т.к. под сравнение попадут два значения False . Наконец, e станет истиной.

Этих четырёх операций — NOT , AND , OR , XOR достаточно для построения логического выражения любой сложности. Эти операторы могут как угодно комбинироваться и можно составлять большие выражения. Однако следует заботиться и о скорости работы. Если выражение вычисляется один раз — всё в норме, но если оно будет вычисляться несколько тысяч раз (например, обработка информации из большой базы данных), то грамотность составленного выражения будет отражаться на скорости выполнения операции. Если в программе появились грмоздкие логические выражения, следует задуматься об их упрощении: одно условие всегда будет проверяться быстрее, чем два.

Немного об оптимизации

В Delphi есть специальные методы оптимизации, в том числе и для логических выражений. Дело в том, что в некоторых случаях вычисление логического выражения полностью не требуется, чтобы получить результат. Простые примеры на AND и OR :

A := False;
B := True;
C := True;
D := True;

X := A and B and C and D;

Поскольку используется оператор AND , результат всего выражения будет истинным только в том случае, если все выражения будут истинны. В данном же случае уже первое выражение ( A ) ложно. Дальнейшая проверка просто не имеет смысла — всё равно результат останется False .

A := True;
B := False;
C := True;
D := False;

X := A or B or C or D;

Абсолютно неважно, какие значения имеют B , C и D , ведь A истинно, а значит OR в любом случае выдаст True .

Изначально такая оптимизация в Delphi включена, т.е. выражения не будут вычисляться полностью. Эту возможность можно отключить (правда, непонятно — зачем?) в свойствах проекта: Project » Options » Compiler » Complete boolean eval (если включить эту опцию, то выражения будут вычисляться полностью).

Где применяются логические выражения? Практически повсюду. Они могут использовать лишь в программном коде для каких-либо проверок, а могут быть связаны и с интерфейсом программы. Как уже было сказано ранее, многие свойства компонент заданы логическим типом данных. Например, давайте сделаем две кнопки и запрограммируем их так, чтобы на экране всегда была только одна. Помещаем на форму 2 кнопки ( TButton ) и одну из них ( Button2 например) делаем невидимой: в Инспекторе Объектов изменяем свойство Visible на False . Теперь дважды щёлкаем по Button1 и пишем (дописать следует только то, что находится между begin и end):

procedure TForm1.Button1Click(Sender: TObject);
begin
Button1.Visible := False;
Button2.Visible := not Button1.Visible;
end ;

Разберёмся, что здесь происходит. Сначала мы изменяем видимость 1-ой кнопки — скрываем её. А затем меняем видимость 2-ой кнопки на противоложное первому. Аналогично пишем обработчик 2-ой кнопки:

procedure TForm1.Button2Click(Sender: TObject);
begin
Button2.Visible := False;
Button1.Visible := not Button2.Visible;
end ;

Если теперь запустить программу и пощёлкать по кнопкам, то они будут по очереди появляться на экране. В принципе, вторые строки обоих обработчиков можно написать и немного иначе — просто присвоить другой кнопке Visible:=True — результат не изменится. Такой способ приведён лишь в качестве примера использования оператора NOT.

Небольшое замечание

Следует обратить внимание ещё вот на что. Если в выражении несколько операндов, то их следует брать в скобки, расставляя таким образом приоритеты выполнения.


Ссылки по теме

Популярные статьи
Информационная безопасность Microsoft Офисное ПО Антивирусное ПО и защита от спама Eset Software


Бестселлеры
Курсы обучения «Atlassian JIRA — система управления проектами и задачами на предприятии»
Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год. Электронный ключ
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2020. Все языки. Электронный ключ
Курс «Oracle. Программирование на SQL и PL/SQL»
Курс «Основы TOGAF® 9»
Microsoft Windows Professional 10 Sngl OLP 1 License No Level Legalization GetGenuine wCOA (FQC-09481)
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Windows Server 2020 Standard
Курс «Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации»
Антивирус ESET NOD32 Antivirus Business Edition
Corel CorelDRAW Home & Student Suite X8

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

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

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

Boolean — Тип Delphi

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

будет равен не 1, как в случае последовательного выполнения, а 6.2 .

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

Вот теперь X будет равен 1.

Помимо четырёх математических действий в Delphi доступно множество математических функций, таких, например, как тигонометрические, логарифмические, и т.д. Они становятся доступны в программе после добавления в секцию Interface uses модуля Math. Их описание также можно найти в модуле Math.pas (можно найти воспользовавшись поиском Windows). Многие из них можно реализовать и самому, но встроенные функции наверняка будут работать быстрее и лучше, т.к. написаны на языке ассемблера.

Логические выражения

Операторы Delphi

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

  • оператора присваивания
  • условного оператора
  • оператора цикла

С оператором присваивания «:=» мы уже знакомились в уроке Delphi 2. Он работает следующим образом. Переменная, стоящая в левой части оператора, становится равной той величине, которая находится справа. Типы этих величин должны совпадать. В выражении, стоящем справа, также может использоваться переменная, стоящая слева. С математической точки зрения это неправильно, но в программировании это означает, что из ячейки памяти берётся исходное значение, производятся вычисления, и результат записывается в эту же ячейку памяти, затирая прежнее значение. Пример:

В начале фрагмента переменная A равна 3, а в конце -25.

Условный оператор позволяет изменить порядок выполнения операторов в зависимости от выполнения некоторого условия. Вот как он записывается:

if условие then действие else альтернатива ;

Слова if (если), then (тогда), else (иначе) — зарезервированные. Действие и else альтернатива — это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие , если ложно, то выполняется альтернатива .
Условие представляет собой логическое выражение. В нём сравниваются значения выражений (в том числе также и логических), вызов функций, возвращающих значения типа Boolean, и комбинирование этих значений с помощью логических операций:

Знак
операции
Название операции Логические операции могут комбинироваться с помощью связок:
and (логическое И)
or (логическое ИЛИ)
xor (исключающее ИЛИ)
Для некоторых типов данных есть дополнительные операции. Например, для множеств — оператор in, которая проверяет, входит ли некоторое значение в множество. Например:
X := [2, 4, 5, 7, 8, 10] ;
Выражение 2 in X истинно (имеет значение true);
Выражение 6 in X ложно (имеет значение false);
= Равно
<> Не равно
> Больше
= Больше или равно
действие ;
Счётчик — это переменная, которая должна быть объявлена перед логическим блоком, в котором оператор цикла расположен, и её тип должен относиться к одному из перечислимых типов, обычно Integer.
Выражение-1 и выражение-2 могут быть как константой или идентификатором, так и вызовом функции.
Действие — один или несколько операторов Delphi. Если это группа операторов, то они должны быть заключены в логические скобки begin/end.
В начале работы оператора переменная-счётчик получает значение выражения-1 . Если при этом значение счётчика окажется меньше или равно значению выражения-2 , то выполняются операторы, входящие в действие . Это и есть один цикл. Затем переменная-счётчик принимает значение, следующее за текущим, и начинается новый цикл, то есть сравнение счётчика и выражения-2 , выполнение действия , и так далее, до тех пор, пока значение переменной-счётчика не превысит значение выражения-2 .
Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto:
for счётчик := выражение-1 downto выражение-2 do действие ;
Соответственно, выражение-1 должно быть больше или равно выражению-2 .

Условный оператор цикла удобно использовать в том случае, когда количество повторений заранее не известно:
while условие do
тело цикла ;
Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу.
Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к «зацикливанию» и «зависанию» программы.

Условный оператор повторения сначала выполняет тело цикла , а затем уже проверяет выполнение условия :
repeat
тело цикла
until условие ;
Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (т.е. true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until.

Вместе с операторами цикла используются специальные команды:

  • команда прерывания цикла
  • команда продолжения цикла

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

Справедливости ради стоит рассказать об ещё одном операторе, позволяющем изменить последовательность выполнения программы. Это оператор перехода:
goto метка ;
В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label:
label меткa ;
или
label список меток ;

Переходить можно как вниз, так и вверх по программе. Двоеточие отделяет метку от оператора, на который производится переход. Пример использования оператора перехода:

Из этого примера видно, что оператор end ; завершающий программу, никогда не будет выполнен, то есть программа зациклится. Именно поэтому, вообще, использование оператора перехода является плохим стилем программирования, и без его использования вполне можно обойтись использованием условных операторов и операторов цикла. Единственный случай, когда использование оператора goto может быть оправдано — это выход из нескольких вложенных циклов, что иначе требует применения нескольких операторов Break.

Пример. Сортировка одномерного массива

Рассматриваются процедуры программы, приводятся подробные комментарии. Также можно скачать проект в виде архива. Цикл while и операторы goto использованы только для демонстрации работы с ними. Здесь — более правильный вариант с применением цикла repeat и оператора break.
Параллельно замечу, что сортировка массива «методом пузырька» — неэффективный метод. Количество итераций (проходов цикла) растёт гораздо быстрее роста количества элементов, . Сортировка 50 000 элементов выполняется на моём компьютере секунд за пять. Но сортировка 100 000 — не за 10 секунд, а около 35 секунд! Можете поэкспериментировать, для этого достаточно во 2 варианте установить в описании массива нужное количество элементов.

Сортировка массивов — типичная задача, где используются циклы. Существует множество методов сортировки массивов. В рассматриваемом примере рассматривается сортировка массива методом «пузырька». В ручном режиме работы программы можно видеть, как числа поднимаются вверх по массиву, подобно всплывающему пузырьку, и становится понятным такое название метода.

type Point=Record //Объявляем тип: Запись
n, digit: Integer; //номер и значение: целые числа
end;
var
Form1: TForm1;
tab: array[1..20] of Point; //Создаём массив записей типа Point

procedure TForm1.FormCreate(Sender: TObject);
begin
StringGr ;//Инициализируем столбцы таблицы
StringGr ;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
Randomize; //Инициализируем «случайную» процедуру
For i:=1 to StringGrid1.RowCount-1 do
begin
tab[i].n:=i; //Присваиваем ячейкам массива порядковые номера
tab[i].digit:=Random(100); //Присваиваем ячейкам массива случайные значения в диапазоне от 0 до 100
StringGr ; //Нумеруем таблицу
StringGr >
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Application.Terminate; //Процедура завершения программы
end;

procedure TForm1.Button2Click(Sender: TObject);
var i, n: Integer; //переменные цикла
Sort: Boolean; //Переменная — признак окончания сортировки
Obmen: Point; //Служебная переменная перестановки значений массива
Label manual1, manual2; //Метки операторов перехода
begin
Sort:=True; //Признак неотсортированности массива
n:=StringGrid1.RowCount-1; //Количество строк в таблице (без заголовка)
if RadioButton1.Checked then goto manual1; //Переход на ручной режим
while(Sort=True) do //Начало автоматического режима: в предыдущем цикле было событие сортировки
manual1: //Начало ручного режима
begin
Sort:=False; //Допустим, что массив уже отсортирован (сортировка не нужна)
for i:=1 to n-1 do //Опять проверяем все значения от 1 до n
if(tab[i+1].digit
begin //Если неверно, то переставляем соседние значения:
Obmen:=tab[i]; //1. Сохраняем одно из значений
tab[i]:=tab[i+1]; //2. На его место переписываем соседнее значение
tab[i+1]:=Obmen; //3. Переписываем сохранённое значение на новое место
Sort:=True; //Признак того, что состоялось событие сортировки
end;
if RadioButton1.Checked then goto manual2; //Пропускаем переход к новому циклу автоматического режима
end; //Здесь заканчивается очередной цикл авторежима и осуществляется переход к новому
manual2:
for i:=1 to n do //Переписываем отсортированные значения массива в таблицу
begin
StringGr ;
StringGr >
end;
end;

Есть возможность немного улучшить процедуру сортировки, что ускорит её примерно на четверть. Дело в том, что после каждого завершённого цикла наибольший ещё неотсортированный элемент перемещается на своё место в низ таблицы. То есть, очередной k-й цикл уже последние k элементов может не просматривать. Для реализации этого нужно ввести переменную — счётчик циклов, и отнять её от переменной цикла. При этом те же 100 000 элементов сортируются уже за 24 секунды! Реализацию этого варианта предоставляю читателю, ввиду его крайней простоты.

Boolean — Тип Delphi

языки разные. вообще с некоторыми оговорками эти типы можно считать одинаковыми.

bool = longbool в delphi — являеться в сучности integer


> В чем разница между переменными типа bool и boolean?

> demon (29.11.2008 18:27:00) [0]

В справке описано, но кратко xBool не логический тип, а арифметический, используемый в недоязыках, как эквивалент логического. В Дельфи для поддержки АПИ введена ограниченая поддержка и его.

> Тын-Дын (29.11.2008 18:42:03) [3]


Зачем, это же производный (generic) тип и его длина меняется.

> Сравни SizeOf()
bool — 4
boolean — 1
теперь ясно, буду boolean использовать.

Windows Data Types

BOOL Boolean variable (should be TRUE or FALSE).
This type is declared in WinDef.h as follows:

typedef int BOOL;

BOOLEAN Boolean variable (should be TRUE or FALSE).
This type is declared in WinNT.h as follows:

typedef BYTE BOOLEAN;


> теперь ясно, буду boolean использовать.

Почему? И где?

ааа. речь о дельфевом bool. тогда да, 4 байта против 1.

> demon (29.11.2008 18:53:06) [6]

> isasa (29.11.2008 18:53:07) [7]

Ну так приходится расплачиваться за грехи предыдущих поколений

из [7] вытекает что программа исползующая boolean не будет работать в 9x системах, верно?

> [12] demon © (29.11.08 19:08)

Да нет, с чего бы?

> DVM (29.11.2008 18:54:08) [8]


> Да нет, с чего бы?

demon © (29.11.08 19:13) [15]

А если будет написано

> declared in abc.h

то это будет означать, что под Виндоус работать не будет, только под abcOS

В C и C++ нет отдельного логического типа, он получается из целых чисел, причём любое ненулевое значение считается истиной, нулевое — ложью. Из-за различной разрядности исторически появились «фундаментальные» ByteBool, WordBool и LongBool, устроенные по одному принципу, но отличающиеся разрядностью, и Bool — обобщённый тип, разрядность которого совпадает с разрядностью платформы, т.е. для Win32 Bool = LongBool.

В Паскале есть встроенный логический тип Boolean, который занимает 1 байт и принимает значения True (1) и False (0), прочие значения компилятором не допускаются. Это тоже исторически сложилось.

Так как API Windows в качестве логических типов использует типы C/C++, в Delphi для совместимости введена поддержка этих типов. Они могут использоваться там, где используется Boolean, и компилятор неявно выполняет необходимые преобразования.

[18]> В C нет отдельного логического типа

> Григорьев Антон (01.12.2008 8:57:18) [18]

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

> inoremap (01.12.2008 9:09:19) [19]

Не fixed, а Masked

У меня при приведении Bool к Boolean компилятор выдывал internal errror. Delphi7. Ругался на простую запись:
if BoolValue then

Когда я переписал на if BoolValue = True then, провалы прекратились.
С тех пор у меня фобия по использованию Bool.

Еще не понятно, как Д сравнивает эти типы между собой. Когда они не 0, они же всеравно могут не равнятся друг другу. Например: первый 1, второй 10. Это можно использовать, как «многозначную» логику.
Но вдруг Д принудительно конвертит все «True» типа LongBool к 1, например, через неявные/невидимые приведения к Boolean.
Проверить не было времени.

> int64 (01.12.08 11:00) [22]
> Еще не понятно, как Д сравнивает эти типы между собой. Когда
> они не 0, они же всеравно могут не равнятся друг другу.
> Например: первый 1, второй 10. Это можно использовать,
> как «многозначную» логику.

Однозначно определена только константа FALSE, только с ней и надо сравнивать.


> С тех пор у меня фобия по использованию Bool.

Вообще интересно почитать мнения программистов. :)
Ведь и Bool и Boolean где то нужно одно, а где то другое.
Иногда без Bool не обойтись, к примеру в структурах API.
Иногда Bool удобнее использовать, т.к. 0 — это false, а >0 это true.

Надо использовать только Bool и не заморачиваться. Иначе с API будут проблемы.

> Кто б сомневался (01.12.2008 17:32:24) [24]

Касательно нуля так, а вот не 0 обысно не Истина, а какое то значение — адрес, хендл, количество и т.л.

> blackman (01.12.2008 17:55:25) [25]

И с Bool тоже будут, точнее уже есть. Кто то кое где посчитал, что 1 это True, а тот откуда ни возмись появилось, не то что вы подумали, а FFFFFFFF и программы лопнули. Не единственный щелчок по носу. Некоторые проблемы описаны в справке. Гарантируется только 0 = False

Anatoly Podgoretsky © (01.12.08 20:11) [27]
Что значит кое кто и кое где? Огласите список фамилий! Накажем! :)

Если по-большому, bool и Boolean это изврат. Используем integer и все понятно и просто. Единственное, что этому мешает — компилятор :)

Ну погоревалм, а потом дружно стали переделывать библиотеки и программы на x <> 0 then
Наказывать то некого, сами себя наказали.
А вот двойственная природа функций в С и в ОС меня огорчает. Представляешь как им там в Борланде с переводом. Когда функция описана, как возвращающая BOOL а там черте знает что.
Но одну фамилие назову, бить надо Страуструпа или кто там до него был, вроде он крайний.

бить надо Страуструпа или кто там до него был, вроде он крайний
Низя! Я по его книге учился, когда С осваивал.
И borland НЕ прав хотя бы потому, что DELPHI появился позже C. Надо было учесть существующее.
К стати, нигде не говорится, что истина именно единица. Не ноль это да.
Где вообще увидели единицу?
Это и логично, поскольку анализируется не бит.
А вообще, все эти условности легко отбрасываются в асме. Различаем длину операнда, а не какие-то придуманные слова.


> И borland НЕ прав хотя бы потому, что DELPHI появился позже
> C. Надо было учесть существующее.

Это еще неизвестно, что раньше появилось Pascal или C. Оба где то в 1970 году, причем си даже на год попозже вроде.


DVM © (01.12.08 22:14) [31]
Я не о паскале, а о дельфи

> blackman (01.12.2008 21:56:30) [30]

Я точно не помню, но вроде бы была определена константа TRUE = 1 и это работало, пока вдруг Микрософт не стал возвращать вместо 1 значение -1, что соответствует определению bool

Ну дальше ты домыслишь сам.

вроде бы была определена константа TRUE = 1
Где? Такого я не видел.
Идея с -1 понятна, но как-то не очень верится. Остается только гадать.

> Anatoly Podgoretsky © (01.12.08 22:35) [33]
> Я точно не помню, но вроде бы была определена константа
> TRUE = 1 и это работало, пока вдруг Микрософт не стал возвращать
> вместо 1 значение -1, что соответствует определению bool
>
> Ну дальше ты домыслишь сам.

А не надо было борланду домысливать.
Понятно же, что в WinAPI — интерфейс Сишный, следовательно взгляд его писателей (вернее даже видение мира ввобще) — тоже сишный, под это и надо было подстравиваться, когда вводили BOOL и интерпретировали операции с ним.
А они «по правильному» сделали. Не подумали.

> KSergey (02.12.2008 12:45:35) [35]

Одно но, я не про Борланда рассказывал!

-1 это WordBool, в OLE

Вообще, булевский тип кем только не был: и int, и word, и byte


> Вообще, булевский тип кем только не был: и int, и word,
> и byte
>

А иногда и bit :)

> Anatoly Podgoretsky © (02.12.08 16:23) [36]
> Одно но, я не про Борланда рассказывал!

Это я понял, я немного про другое: в дельфи могли бы сами правильное сделать сравнение для не Boolean-типа под if

> clickmaker (02.12.2008 16:28:37) [37]

Кто работал правильно (var <> 0 ), не пользовался константами TRUE (var = TRUE), или в стандартной форме if var <> — не пострадал.

> KSergey (02.12.2008 16:46:39) [39]

Повторяю я не про Борланд рассказывал, хотя у Борланда свои проблемы с этим типом, но и описан нормальный путь по преобразованию в Boolean, наприер B := var <> 0.
Зато у Борланд проблема с двоичным, троичным назначением Bool — когда он и Bool и Integer одновременно. Борланд пошел тупо. Если значение равно 0 то это false, неудача, кой где удача. И тут проблема, надо было объявить результат не по описанию, а по использованию.

Delphi/Переменные

Переменная — область оперативной памяти, в которой лежит какое-то значение. Основные типы переменных в Delphi:

  • Integer — целые числа.
  • Real — целые и дробные числа.
  • Boolean — логический тип.
  • Char — символьный тип данных.
  • String — строковой тип данных.

Переменные указываются после ключевого слова var (variable — переменная). Общий вид указывания переменных:

В Delphi есть оператор присваивания — := .Общий вид присваивания:

Но с типом string и char, особое дело. Общий вид присваивания с типом string и char:

Типы данных в DELPHI

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

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

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

Что же касается объявлений var, то они задают компилятору некоторые действия, связанные с ранее объявленными типами. Тип переменной ограничивает как ее значения, так и операции, которые можно выполнять с этими значениями.

Определения типов и переменных могут размещаться в нескольких местах компонентов программы. Выглядят же они следующим образом.

type
typel = type definitioni; //Новые типы данных определяются в разделе «type». Каждому новому
// типу присваивается имя, затем он определяется через уже
//существующие типы.
type2 = type__definition2; // В одном разделе «type» можно объявить несколько типов.
//Самое простое определение типа состоит из имени типа,
type3 = typel; // определенного ранее.
// Новые переменные объявляются в
var // разделе «var». Каждой новой
var1: type definitions; // переменной сначала присваивается имя, а затем — тип (на основе
// ранее определенных типов).
var2, var3: type definition4; // В одном разделе «var» можно объявить несколько переменных.
// Нескольким переменным можно присваивать один и тот же тип.
var4 : typel; // Программу легче читать, если переменным присвоены
//существующие типы.

Синтаксис Object Pascal позволяет одновременно конструировать исключительно сложные типы и определение переменных. Однако определение типов в разделах type тех или иных блоков дает возможность использовать эти типы в разных частях программы. Новые типы определяются из типов следующих категории.

  • Простые типы для хранения информации в форме чисел и других «упорядоченных» значении.
  • Строковые типы для хранения последовательностей символов.
  • Структурные типы для одновременного хранения информации разных типов.
  • Указательные типы для косвенного обращения к переменным заданных типов.
  • Процедурные типы для обращения к процедурам и функциям, рассматриваемым как переменные.
  • Вариантные типы для хранения в одной переменной данных различных типов.

Обычно идентификаторы типов используются только при определении новых типов или объявлении переменных. Есть, однако, несколько функций, в которых имя типа может использоваться как часть выполняемого оператора. Например, функция SizeOf (Т) возвращает количество байтов, занимаемых переменной Т.

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

Простые типы данных

Порядковые типы
Целые типы
Символьные типы
Булевы типы
Перечислимые типы
Поддиапазонные типы
Действительные типы

Любой реально существующий тип данных, каким бы сложным он ни казался на первый взгляд, представляет собой простые составляющие, которыми процессор может манипулировать. В Object Pascal эти простые типы данных разбиты на две группы: порядковые, представляющие данные разных объемов, которыми процессор может легко манипулировать, и действительные, представляющие приближенно математические действительные числа. Разделение типов на порядковые и действительные несколько условно. Точно так же простые данные можно было бы разделить на числа и не числа. Однако в языке Object Pascal порядковые и действительные данные трактуются по-разному, и такое разделение даже полезно.

Порядковые типы

Из простых типов данных порядковые — самые простые. В этих типах информация представляется в виде отдельных элементов. Связь между отдельными элементами и их представлением в памяти определяет естественные отношения порядка между этими элементами. Отсюда и название порядковые.

В Object Pascal определены три группы порядковых типов и два типа, определяемых пользователем. Группы — это целые, символьные и булевы типы. Порядковые типы, задаваемые пользователем, — это перечисления и поддиапазоны.

Все значения любого порядкового типа образуют упорядоченную последовательность, и значение переменной порядкового типа определяется его местом в этой последовательности. За исключением переменных целых типов, значения которых могут быть как положительными, так и отрицательными, первый элемент любого порядкового типа имеет номер 0, второй элемент — номер 1 и т.д. Порядковый номер целого значения равен самому значению. Отношение порядка определяет общие для данных всех порядковых типов операции. Некоторые стандартные функции такого вида встроены в Object Pascal. Они представлены в табл. 1.1.

Для всех порядковых типов в Object Pascal существует операция задания типа для преобразования целых значений в значения соответствующих порядковых типов. Если Т — имя порядкового типа, а Х — целое выражение, то Т (X) воз-вращает значение Т с порядковым номером X.

Таблица 1.1. Операции над порядковыми типами

Минимальное значение порядкового типа Т

Максимальное значение порядкового типа Т

Порядковый номер значения выражения порядкового типа. Для целого выражения — просто его значение. Для остальных порядковых типов Ord возвращает физическое представление результата выражения, трактуемое как целое число. Возвращаемое значение всегда принадлежит одному из целых типов


Предыдущее по порядку значение. Для целых выражений эквивалентно Х-1

Следующее по порядку значение. Для целых выражений эквивалентно Х+1

Уменьшает значение переменной на 1. Эквивалентно V := Pred(V)

Увеличивает значение переменной на 1. Эквивалентно V := Succ(V)

Целые типы

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

Обратите внимание, что один из этих целых типов назван именно целым (integer). Это может иногда приводить к путанице, но мы легко сможем ее избежать, применяя термин целый к. группе типов, a integer — к конкретному типу, определяемому в программе этим ключевым словом. Переменные физических целых типов имеют разные диапазоны значений в зависимости от того, сколько байтов памяти они занимают (что равно значению, возвращаемому функцией SizeOf для данного типа). Диапазоны значений для всех физических типов перечислены в табл. 1.2.

Таблица 1.2. Физические целые типы

8 бит, со знаком

16 бит, со знаком

-2 147 483 648-2 147 483 647

32 бит, со знаком

8 бит, без знака

16 бит, без знака

Диапазоны значений и форматы физических целых типов не зависят от микропроцессора и операционной системы, в которых выполняется программа. Они не меняются (или, по крайней мере, не должны меняться) с изменением реализации или версии Object Pascal.

Диапазоны значений логических целых типов (Integer и Cardinal) определяются совершенно иным образом. Как видно из табл. 1.3, они никак не связаны с диапазонами соответствующих физических типов. Обратите внимание, что в Delphi по умолчанию задано 32-разрядное представление.

Таблица 1.3. Логические целые типы

16 бит, со знаком (SmalIInt)

-2 147 483 648-2 147 483 647

32 бит, со знаком (Longint)

16 бит, без знака (Word)

32 бит, без знака (Longint)

Над целыми данными выполняются все операции, определенные для порядковых типов, но с ними все же удобнее работать как с числами, а не с «нечисленными порядковыми типами». Как и «живые» числа, данные целых типов можно складывать (+), вычитать (-) и умножать (*). Однако некоторые операции и функции, применяемые к данным целых типов, имеют несколько иной смысл.

Возвращает абсолютное целое значение Х

Возвращает целую часть частного деления Х на Y

Возвращает остаток частного деления Х на Y

Возвращает булево True (истина), если Х — нечетное целое, и False (ложь) — в противном случае

Возвращает целый квадрат Х (т.е. Х*Х)

Символьные типы

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

В реализациях языка Pascal для первых микропроцессоров была применена 7-битовая схема, названная ASCII (American Standard Code for Information Interchange — Американский стандартный код для обмена информацией). Эта схема и поныне широко распространена, но информация хранится, как правило, в 8-битовых участках памяти. Дополнительный бит удваивает число возможных представлений символов, но реализации расширенного набора символов ASCII часто бывают далеки от стандарта. В данной версии Delphi определен набор 8-битовых символов, известный как расширенный (extended) ANSI (American National Standards Institute — Американский национальный институт стандартов). Как бы то ни было, символьную схему приходится воспринимать так, как ее воспринимает операционная система. Для оконных операционных систем фирмы Microsoft это схема ANSI, включающая ограниченное число предназначенных для вывода международных знаков. В стремлении же применить более обширный набор международных знаков весь компьютерный мир переходит к 16-битовой схеме, именуемой UNICODE, в которой первые 256 знаков совпадают с символами, определенными в схеме ANSI.

Для совместимости со всеми этими представлениями в Object Pascal определены два физических символьных типа и один логический.

Физические типы перечислены ниже.

Однобайтовые символы, упорядоченные в соответствии с расширенным набором символов ANSI

Символы объемом в слово, упорядоченные в соответствии с международным набором символов UNICODE. Первые 256 символов совпадают с символами ANSI

Символьные типы объемом в двойное слово (32 бит) отсутствуют.

Логический символьный тип именуется char. В классическом языке Pascal char- единственный символьный тип. В Delphi char всегда соответствует физическому типу данных AnsiChar. У американских программистов ассоциация символа с однобайтовой ячейкой памяти укоренилась за долгие годы настолько, что им зачастую просто не приходит в голову, что можно использовать другие схемы кодирования. Однако дискуссии по интернационализации программ в Internet и World Wide Web могут существенно изменить их отношение к проблеме объема символьных данных. Применяя логический тип char, следует делать реализации для других микропроцессоров и операционных систем, в которых char может определяться как WideChar. При написании программ, которые могут обрабатывать строки любого размера, для указания этого размера рекомендуется применять функцию SizeOf, не задавая ее жестко постоянной. Функция Ord (С), где С — любая переменная символьного типа, возвращает целое значение, которым символ С представлен в памяти.

Преобразует целую переменную в переменную типа char с тем же порядковым номером. В Delphi это эквивалентно заданию типа Char (X)

Преобразует строчную букву в прописную

Булевы типы

На ранней стадии обучения программисты осваивают понятие бита, два состояния которого можно использовать для записи информации о чем-либо, представляющем собой одно из двух. Бит может обозначать 0 или 1, ДА или НЕТ, ВКЛЮЧЕНО или ВЫКЛЮЧЕНО, ВЕРХ или НИЗ, СТОЯТЬ или ИДТИ. В Object Pascal информация о чем-либо, что можно представить как ИСТИНА (True) или ЛОЖЬ (False), хранится в переменных булевых типов. Всего таких типов че-тыре, и они представлены в табл. 1.4.

Таблица 1.4. Размеры переменных булевых типов

2 байт (объем Word)

4 байт (объем Longint)

По аналогии с целыми и символьными типами, подразделяющимися на физические и логические, естественно предположить, что ByteBool, WordBool и LongBool — физические типы, Boolean — логический. Но в данном случае это не совсем так. Все четыре типа различны. Для Object Pascal предпочтителен тип Boolean, остальные определены для совместимости с другими языками программирования и операционными системами.

Переменным типа Boolean можно присваивать только значения True (истина) и False (ложь). Переменные ByteBool, WordBool и LongBool могут принимать и другие порядковые значения, интерпретируемые обычно как False в случае нуля и True — при любом ненулевом значении.

Перечислимые типы

Type enum type = (first value, value2, value3, last value);


Обычно данные перечислимых типов содержат дискретные значения, представляемые не числами, а именами. Тип Boolean- простейший перечислимый тип в Object Pascal. Булевы переменные могут принимать два значения, выражаемые именами True и False, а сам тип определен в Object Pascal так, как будто он объявлен следующим образом:

Type Boolean = (False, True);

С помощью типа Boolean в Object Pascal выполняются сравнения, большинство же перечислимых типов — это просто списки уникальных имен или идентификаторов, зарезервированных с конкретной целью. Например, можно создать тип MyColor (мой цвет) со значениями myRed, myGreen и myBlue (мой красный, мой зеленый, мой синий). Это делается совсем просто:

Type MyColor = (myRed, myGreen, myBlue);

В этой строке объявлены четыре новых идентификатора: MyColor, myRed, myGreen и myBlue. идентификатором MyColor обозначен порядковый тип, следовательно, в синтаксисе Object Pascal можно применять этот идентификатор везде, где разрешены перечислимые типы. Остальные три идентификатора- это значения типа MyColor. Подобно символьным и булевым типам перечислимые не являются числами, и использовать их наподобие чисел не имеет смысла. Однако перечислимые типы относятся к порядковым, так что значения любого такого типа упорядочены. Идентификаторам в списке присваиваются в качестве порядковых номеров последовательные числа. Первому имени присваивается порядковый номер 0, второму — 1 и т.д.

Поддиапазонные типы

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

Type subrange type = low value. high value;

Поддиапазонные переменные сохраняют все особенности исходного типа. Единственное отличие состоит в том, что переменной поддиапазонного типа можно присваивать только значения, входящие в заданный поддиапазон. Контроль за соблюдением этого условия задается командой проверки диапазона (range checking).

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

Действительные типы

В переменных действительных типов содержатся числа, состоящие из целой и дробной частей. В Object Pascal определено шесть действительных типов. Все типы могут представлять число 0, однако они различаются пороговым (минимальным положительным) и максимальным значениями, которые могут представлять, а также точностью (количеством значащих цифр) и объемом. Действительные типы описываются в табл. 1.5.

Таблица 1.5. Действительные типы.

Количество значащих цифр

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

Заметьте, именно почти. Несмотря на название действительные, переменные этих типов отличаются от математических действительных чисел. В Object Pascal действительный тип — это подмножество математических действительных чисел, которые можно представить в формате с плавающей запятой и фиксированным числом цифр. Для невнимательных программистов ситуация усугубляется тем, что в стандартных форматах IEEE (Institute of Electrical and Electronic Engi-neers — Институт инженеров- электриков и электронщиков), применяемых в программах Delphi и вообще в большинстве программ для Windows, возможно точное представление только чисел с фиксированным числом бит в дробной части. Удивительно, но такое простое число, как 0,1, записывается в расширенном формате IEEE с некоторой погрешностью, пусть очень небольшой. Из-за этого представление с плавающей запятой оказывается несколько неудобным для программ, в которых сохраняется и выводится фиксированное число десятичных разрядов численных значений. Это относится и к программам, работающим с »живыми» деньгами.

Для частичного решения этой проблемы в Object Pascal определены два формата с фиксированной запятой. Тип Comp (computational — вычислительный) содержит только целые числа в диапазоне от -2 63 +1 до 2 63 -1, что примерно соответствует диапазону от -9,2х10 18 до 9,2х10 18 . При программировании операций с американской валютой разработчикам обычно приходится искать естественный способ записи денежных сумм, в котором целая часть числа определяет количество долларов, дробная — центов. Если такие значения записывать в переменные типа Comp, придется представлять их в виде целого числа центов. В этом случае следует умножать значение на 100 для обращения центов в доллары, а затем делить на 100, чтобы снова получить центы.

Этих забот можно избежать, если воспользоваться типом Currency. В этом случае задачу выбора масштаба возьмет на себя компилятор. Физически значения Currency записываются в память того же объема, что и Comp, как целые числа, однако компилятор не забывает вовремя разделить значение на 10 000 (не на 100!) для его приведения в соответствие с денежным знаком и умножить на 10 000 перед записью в память. Это обеспечивает абсолютную точность в четыре десятичных знака после запятой.

В Delphi есть модуль System, содержащий ряд процедур обработки данных действительных типов. Наиболее распространенные из них перечислены в табл. 1.6. Много полезных процедур содержится также в модулях SysUtils и Math.

Таблица 1.6. Функции действительных типов

Абсолютная величина х

Косинус х (х выражается в радианах, а не в градусах)

Экспоненциальная функция от х

Дробная часть х

Целая часть х. Несмотря на название, возвращает действительное значение (с плавающей запятой), т.е. просто устанавливает нуль в дробной части

Натуральный логарифм от х

Ближайшее к х целое значение. Возвращает значение целого типа. Условие «ближайшее к х» не работает, если верхнее и нижнее значения оказываются равноудаленными (например, ес-ли дробная часть точно равна 0,5). В этих случаях Delphi перекладывает решение на опера-ционную систему. Обычно процессоры Intel решают эту задачу в соответствии с рекоменда-цией IEEE округлять в сторону ближайшего четного целого числа. Иногда такой подход на-зывают «банкирским округлением»

Квадрат х, т.е. X*X

Квадратный корень от х

Целая часть х. В отличие от Int, возвращающей действительное значение, Trunc возвращает целое

В выражениях Delphi поддерживает три физических строковых формата: короткий (ShortString), длинный (LongString) и широкий (WideString). Их можно комбинировать в операторах присваивания и выражениях (все необходимые преобразования Delphi выполняет автоматически).

Переменные типов AnsiString и WideString — это динамически распределяемые массивы символов, максимальная длина которых ограничивается только наличием памяти. Разница между ними состоит в том, что в AnsiString знаки записываются в формате char, а в WideString- в формате WideChar. Обычно вполне достаточно одного типа AnsiString, однако при работе с международными наборами символов, такими как UNICODE, удобнее использовать WideString.

Тип ShortString-это, по существу, массив Array [0..255] of char. Первый его элемент задает динамическую длину строки, которая может принимать значения от 0 до 255 символов. Символы, составляющие строку, занимают места от 1 до 255. Тип ShortString предназначен, в основном, для обеспечения совместимости с ранними версиями Delphi и Borland Pascal.

Логический строковый тип именуется просто String. Отнесение его к типу AnsiString или ShortString задается командой $Н. По умолчанию задается < $Н+>, и String совпадает с AnsiString. Если задать команду <$Н- >, то String будет совпадать с ShortString и иметь максимальную длину, равную 255 символам.

Для совместимости с другими языками программирования в Delphi поддерживается класс строк с конечным нулем. Зарезервированных слов или идентификаторов для этого класса не существует.

Строки с конечным нулем состоят из ненулевых символов и оканчиваются символом с порядковым номером 0 (#0). В отличие от типов AnsiString, ShortString и WideString, строки с нулевым окончанием не имеют указателя длины. Конец в этих стооках обозначается нулем.

Физически строки с нуль-окончанием подобны массивам символов с нумерацией элементов от нуля, наподобие array [ 0 . . X] of char, где Х — некоторое положительное целое, большее нуля, хотя никаких объявлении подобного рода не происходит. Вместо этого определяется переменная-указатель PChar и распределяется необходимый объем памяти. При необходимости строке AnsiString можно присвоить тип PChar.

В табл. 1.7 перечислены некоторые процедуры и функции обработки данных строковых типов.

Таблица 1.7. Строковые функции

Возвращает последовательное соединение строк. Эквивалентна оператору sl+s2+s3

Возвращает подстроку длиной максимум len символов, начинающуюся в позиции pos строки s

Delete(s, pos, len)

Удаляет максимум len символов из строки s, начиная с позиции pos

Insert(sourse, tar-get, pos)

Вставляет строку source в строковую переменную target, начиная с позиции pos

Возвращает динамическую длину строки. Подобна функциям LEN в Basic и strlen — в C/C++


Возвращает место первого вхождения подстроки substring в строку s. Подобна функциям SUBSTR в Basic и strstr () — в C/C++

Задает новую динамическую длину newlen строковой переменной s

Задает содержимое и длину строки

Преобразует численное значение х в строковую переменную s

Возвращает строку с конкретным числом символов

Делает данную строку уникальной со счетом обращений 1

Преобразует строку s в соответствующее численное представление v

Записи
Фиксированные записи
Вариантные записи
Массивы
Множества
Файловый тип

На элементарном уровне наиболее полезными типами данных являются те, в которых содержится численная и строковая (символьная) информация. Объединив несколько образцов этих элементарных типов, можно создавать более сложные типы данных.

Структурные типы данных предоставляют возможность создавать новые типы, расширяя определения уже существующих таким образом, чтобы данные новых типов могли содержать более одного значения. Элементами данных структурных типов можно манипулировать как поодиночке, так и вместе, и эти элементы сами могут быть структурными. Никаких ограничений на подобное вложение одной структуры в другую не существует.

Ниже перечислены структурные типы, определенные в Delphi .

  • Записи
  • Массивы
  • Множества
  • Файлы
  • Классы
  • Указатели на классы

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

Записи

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

record
fieldnamel: fieldtypel;
fieldname2, fieldname3: fieldtype2;
case optional tagfield: required ordinal type of
1: variantnamel: varianttype3;
2, 3: variantname2: varianttype4;
end;

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

Фиксированные записи

В фиксированной части записи определяется одно или несколько независимых полей. Каждому полю обязательно присваивается имя и тип:

record
fieldnamel: fieldtypel;
fieldname2, fieldname3: fieldtype2;
end;

Имея доступ к информации в записи, можно обрабатывать всю запись целиком (все поля одновременно) или только отдельное поле. Для обращения к отдельному полю наберите имя записи, точку и идентификатор поля, например

Для доступа ко всей записи просто укажите ее имя.

Вариантные записи

Вариантная часть типа record дает возможность по-разному трактовать область памяти, совместно занимаемую вариантами поля:

record
case optional tagfield: required ordinal type of
1: variantnamel: varianttype3;
2, 3: variantname2: varianttype4;
end;

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

Каждый вариант обозначается минимум одной константой. Все константы должны быть порядковыми и совместимыми по типу с меткой поля.

Необязательное поле — это идентификатор дополнительного поля в фиксированной части записи, общий для всех вариантов. Обычно с его помощью определяют, когда к какому варианту обращаться.
Необязательное поле можно не указывать, однако порядковый тип необходим. При отсутствии необязательного поля программе придется выбирать подходящий вариант каким-то иным образом.
Данные некоторых типов бессмысленно интерпретировать различным образом, и в Object Pascal на некоторые критические типы наложено соответствующее ограничение. Как следствие, в вариантную часть записи нельзя включать длинные строки и переменные типа Variant, а также структурные переменные, содержащие эти типы.

Массивы

Массивы могут быть одно- или многомерными, как в следующем примере.

array [ordinal_type] of type_definition;
array [ordinal typel, ordinal type2] of type definition;

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

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

var MyArray: Array [1..10] of Integer;

Тогда обращение к его третьему элементу будет выглядеть, как MyArray[З], и выполняться, как к переменной Integer.

Множества

Зарезервированное слово set (множество) определяет множество не более чем из 256 порядковых значений:

Set of ordinal type

Минимальный и максимальный порядковые номера исходного типа (на основе которого определяется множественный тип) должны быть в пределах между 0 и 255. Переменная множественного типа содержит (или не содержит) любое значение исходного порядкового типа. Каждое значение из заданного диапазона может принадлежать или не принадлежать множеству. Рассмотрим следующий пример.

Type CharSet = set of AnsiChar; // Тип множества символов. ANSI.
var MyAlphaSet: CharSet; // Переменная типа CharSet.

Переменная set может содержать все элементы множества или не содержать ни одного. При присвоении значения переменной множественного типа элементы множества (порядковые значения) указываются в квадратных скобках:

MyAlphaSet := [‘А’, ‘Е’, ‘Г, ‘О’, ‘U’, ‘Y’]; // Все прописные гласные.

Пустые квадратные скобки задают пустое множество, не содержащее ни одного элемента. Это относится ко всем множественными типам.

Файловый тип

Тип file предназначен для доступа к линейной последовательности элементов, которые могут представлять данные любого типа, кроме содержащих типы file и class. Объявление файлового типа подобно объявлению массива, только без указания числа элементов.

file of Typel // Файл определенного типа, содержащий
// записи фиксированной длины.
file // Файл без типа или «блочный».
textfile // Файл с записями переменной длины, разделенными символами CR
//и LF («возврат каретки» и «новая строка»).

Механизм ввода-вывода информации как никакой другой аспект программирования зависит от языка и реализации. В большинстве случаев предполагается, что программисту незачем вникать во внутреннюю структуру переменных, управляющих вводом-выводом, и при передаче информации следует полностью полагаться на предназначенные для этого процедуры. Их реализация должна оставаться чем-то наподобие черной магии. В Basic файлы обозначаются числовыми значениями — дескрипторами. В C/C++ программисты манипулируют указателями на структуру FILE. И только в Delphi файловая структура — это переменная.

Переменная указательного типа содержит значение, указывающее на переменную обычного типа — адрес этой переменной (табл. 1.8).

pointer // Указатель без типа.
^typel // Указатель с типом.

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


Только исходный тип указателей может совпадать с собственно типом.

Таблица 1.8. Средства работы с указателями

Распределяет новый участок динамической памяти и записывает его адрес в переменную указательного типа

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

Создает новую динамическую переменную заданного объема и записывает ее адрес в переменную указательного типа

Указатели и адресные функции

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

Возвращает адрес указанного объекта

Проверяет, равно ли значение процедурной функции Nil

Преобразует адрес в указатель

type
PointerType = ^NotYetDefinedType;

Однако необъявленный тип необходимо объявить ниже в том же блоке объявления типов.

Определенный в Object Pascal тип Pointer- это указатель без типа. Обратиться к переменной через такой указатель невозможно (к переменной типа Pointer нельзя дописывать символ «^»). Однако можно задать ей другой указательный тип.

По значениям переменных тип Pointer совместим с остальными указательными типами.

Тип Variant
Вариантные значения
Процедуры обработки вариантных массивов
OLE Automation

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

Объявление процедурного типа подобно объявлению заголовка процедуры или функции. Единственная разница состоит в том, что опускается имя. следующее обычно после ключевых слов procedure и function.

Вне типа Class в Object Pascal разрешены только глобальные процедурные переменные. Это означает, что процедурной переменной не может быть присвоена процедура или функция, объявленная внутри другой процедуры или функции.

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

В Delphi указатели процедурного типа на методы применяются для сопоставления событий с образцами текста программы. С точки зрения синтаксиса, единственное отличие процедурного типа для метода от обычного процедурного типа состоит в фразе of object, следующей за прототипом процедуры или функции в случае метода. Особым образом применяется в процедурных методах указательное значение Nil. Это единственное указательное значение, которое можно присвоить процедурной переменной. После присвоения такого значения процедурная переменная становится неопределенной. Состояние определенности можно проверить с помощью функции Assigned.

Глобальные процедурные типы и процедурные типы для методов взаимно несовместимы. Нельзя присваивать значение одного типа переменной другого.

Физически процедурные типы в Delphi совпадают с указательными, однако они различаются синтаксически, поэтому нельзя обращаться к функции или процедуре через указатель. Тем не менее при обращении к процедурной переменной задействуется именно значение указательного типа. В C/C++ переменная может иметь тип указателя на функцию. В версиях языка С до введения стандарта ANSI для обращения к соответствующей функции приходилось явно адресовать указатель. В версиях С, со-ответствующих стандартам ANSI, возможны как явная, так и неявная адресации указателей. Delphi удобна для тех, кому близок стиль ANSI.

Тип Variant

Тип Variant предназначен для представления значений, которые могут динамически изменять свой тип. Если любой другой тип переменной зафиксирован, то в переменные типа Variant можно вносить переменные разных типов. Шире всего тип Variant применяется в случаях, когда фактический тип данных изменяется или неизвестен в момент компиляции.

Вариантные значения

При рассмотрении типа Record мы ознакомились с вариантной частью записи, где в одном фрагменте памяти можно хранить информацию нескольких типов. Такой метод недостаточно нагляден. Много ли пользы от того, чтобы найти в памяти действительное значение с фиксированной запятой и интерпретировать его, как целое! Тип Variant (не имеющий ничего общего с вариантной частью записи) более «проворен» и полезен в управлении данными разных типов. Переменным типа Variant можно присваивать любые значения любых целых, действительных, строковых и булевых типов. Для совместимости с другими языками программирования предусмотрена также возможность присвоения этим переменным значений даты/времени и объектов OLE Automation. Кроме того, вариантные переменные могут содержать массивы переменной длины и размерности с элементами указанных типов.

Все целые, действительные, строковые, символьные и булевы типы совместимы с типом Variant в отношении операции присваивания. Вариантные переменные можно сочетать в выражениях с целыми, действительными, строковыми, символьными и булевыми; при этом все необходимые преобразования Delphi выполняет автоматически. Можно произвольно задавать для выражении тип Variant в форме Variant (X).

В Object Pascal определены два особых значения Variant. Значение Unassigned применяется для указания, что вариантной переменной пока не присвоено значение какого бы то ни было типа. Значение Null указывает на наличие в переменной данных неизвестного типа или потерю данных. Разницу между этими двумя значениями трудно уловить. Значение Unassigned присваивается вариантным переменным автоматически при их создании, независимо от того, локальная это переменная или глобальная, и является ли она частью другой, структурной, переменной, такой как запись или массив. Unassigned означает, что к данной вариантной переменной еще не обращались. Null же означает, что к вариантной переменной обращались, но не ввели в нее никакой информации. Таким образом, Null указывает, что значение вариантной переменной недействительно или отсутствует.

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

Интересна проблема использования вариантной переменной как массива. Элементы этого массива должны быть одного типа. На первый взгляд, это вполне естественное условие. Однако элементам массива можно присвоить и тип Variant! Тогда каждый элемент сможет содержать информацию разных типов, в том числе массив Variant. Как правило, вариантные массивы создаются с помощью процедуры VarArrayCreate.

Для передачи двоичной информации между контроллерами автоматизации OLE и серверами обычно применяются вариантные массивы с элементами varByte. Вариантные массивы типа varByte не могут подвергаться никаким преобразованиям. Нельзя также переформатировать содержащуюся в них двоичную информацию. Эффективный доступ к ним осуществляется с помощью процедур VarArrayLock и VarArrayUnlock.

Элементы вариантного массива не могут иметь тип varString. Для создания вариантных массивов со строковыми элементами следует выбрать тип varOleStr.

Процедуры обработки вариантных массивов

В табл. 1.9 перечислены стандартные процедуры и функции обработки вариантных массивов, определенные в модуле System.

Таблица 1.9. Процедуры и функции обработки вариантных массивов

Основные типы данных Delphi

К основным типам данных языка Delphi относятся: П целые числа (integer); П дробные числа (real); П символы (char);

Целые числа и числа с плавающей точкой могут быть представлены в различных форматах (табл. П1.1 и П2.2).

Таблица П1.1. Целые числа

-2 147 483 648.. 2 147 483 647

Таблица П1.2. Числа с плавающей точкой

Кол-во значащих цифр

Когда тот или иной физик использует понятие «физический вакуум», он либо не понимает абсурдности этого термина, либо лукавит, являясь скрытым или явным приверженцем релятивистской идеологии.

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

Для защиты релятивизма Поль Дирак ввел афизическое и алогичное понятие отрицательной энергии, а затем и существование «моря» двух компенсирующих друг друга энергий в вакууме — положительной и отрицательной, а также «моря» компенсирующих друг друга частиц — виртуальных (то есть кажущихся) электронов и позитронов в вакууме.

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

НОВОСТИ ФОРУМА
Рыцари теории эфира
01.10.2020 — 05:20: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]69vJGqDENq4[/Youtube][/center]
[center]14:36[/center]
Osievskii Global News
29 сент. Отправлено 05:20, 01.10.2020 г.’ target=_top>Просвещение от Вячеслава Осиевского — Карим_Хайдаров.
30.09.2020 — 12:51: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Ok]376309070[/Ok][/center]
[center]11:03[/center] Отправлено 12:51, 30.09.2020 г.’ target=_top>Просвещение от Дэйвида Дюка — Карим_Хайдаров.
30.09.2020 — 11:53: ВОСПИТАНИЕ, ПРОСВЕЩЕНИЕ, ОБРАЗОВАНИЕ — Upbringing, Inlightening, Education ->
[center][Youtube]VVQv1EzDTtY[/Youtube][/center]
[center]10:43[/center]

интервью Раввина Борода https://cursorinfo.co.il/all-news/rav.
мой телеграмм https://t.me/peshekhonovandrei
мой твиттер https://twitter.com/Andrey54708595
мой инстаграм https://www.instagram.com/andreipeshekhonow/


[b]Мой комментарий:
Андрей спрашивает: Краснодарская синагога — это что, военный объект?
— Да, военный, потому что имеет разрешение от Росатома на манипуляции с радиоактивными веществами, а также иными веществами, опасными в отношении массового поражения. Именно это было выявлено группой краснодарцев во главе с Мариной Мелиховой.

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

[center][Youtube]CLegyQkMkyw[/Youtube][/center]
[center]10:22 [/center]

Доминико Риккарди: Россию ждёт страшное будущее (хотелки ЦРУ):
https://tainy.net/22686-predskazaniya-dominika-rikardi-o-budushhem-rossii-sdelannye-v-2000-godu.html

Завещание Алена Даллеса / Разработка ЦРУ (запрещено к ознакомлению Роскомнадзором = Жид-над-рус-надзором)
http://av-inf.blogspot.com/2013/12/dalles.html

[center][b]Сон разума народа России [/center]

Клуб программистов

Delphi programming

Подписаться на рассылку:

Boolean

Принимает только значения «Истина»(True) и «Ложь»(False)

type Boolean = (False, True);

Описание:

Тип Boolean предоставляет набор логических значений «Истина»(True) и «Ложь»(False)

В отличие от других языков, это не число — он позволяет задать только эти значения. Это делает код более надежным.

Пример кода:

var
same : Boolean;
small, large, i : Integer;

begin
small := 23;
large := 455555;

// Test directly to see if these numbers are the same size
if small = large
then ShowMessage(‘small = large’)
else ShowMessage(‘small <> large’);

// Use a Boolean to hold and test this outcome
same := (small = large);
if same
then ShowMessage(‘small = large’)
else ShowMessage(‘small <> large’);

// Assign a direct logical value to this Boolean
same := True;
if same
then ShowMessage(‘same is True’)
else ShowMessage(‘same is False’);
end;

Boolean — Тип Delphi

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

будет равен не 1, как в случае последовательного выполнения, а 6.2 .

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

Вот теперь X будет равен 1.

Помимо четырёх математических действий в Delphi доступно множество математических функций, таких, например, как тигонометрические, логарифмические, и т.д. Они становятся доступны в программе после добавления в секцию Interface uses модуля Math. Их описание также можно найти в модуле Math.pas (можно найти воспользовавшись поиском Windows). Многие из них можно реализовать и самому, но встроенные функции наверняка будут работать быстрее и лучше, т.к. написаны на языке ассемблера.

Логические выражения

Операторы Delphi

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

  • оператора присваивания
  • условного оператора
  • оператора цикла

С оператором присваивания «:=» мы уже знакомились в уроке Delphi 2. Он работает следующим образом. Переменная, стоящая в левой части оператора, становится равной той величине, которая находится справа. Типы этих величин должны совпадать. В выражении, стоящем справа, также может использоваться переменная, стоящая слева. С математической точки зрения это неправильно, но в программировании это означает, что из ячейки памяти берётся исходное значение, производятся вычисления, и результат записывается в эту же ячейку памяти, затирая прежнее значение. Пример:

В начале фрагмента переменная A равна 3, а в конце -25.

Условный оператор позволяет изменить порядок выполнения операторов в зависимости от выполнения некоторого условия. Вот как он записывается:

if условие then действие else альтернатива ;

Слова if (если), then (тогда), else (иначе) — зарезервированные. Действие и else альтернатива — это любые операторы Delphi, или несколько операторов, заключённых в логические скобки begin/end, или вызов подпрограммы. Если условие истинно, то выполняется действие , если ложно, то выполняется альтернатива .
Условие представляет собой логическое выражение. В нём сравниваются значения выражений (в том числе также и логических), вызов функций, возвращающих значения типа Boolean, и комбинирование этих значений с помощью логических операций:

Знак
операции
Название операции Логические операции могут комбинироваться с помощью связок:
and (логическое И)
or (логическое ИЛИ)
xor (исключающее ИЛИ)
Для некоторых типов данных есть дополнительные операции. Например, для множеств — оператор in, которая проверяет, входит ли некоторое значение в множество. Например:
X := [2, 4, 5, 7, 8, 10] ;
Выражение 2 in X истинно (имеет значение true);
Выражение 6 in X ложно (имеет значение false);
= Равно
<> Не равно
> Больше
= Больше или равно
действие ;
Счётчик — это переменная, которая должна быть объявлена перед логическим блоком, в котором оператор цикла расположен, и её тип должен относиться к одному из перечислимых типов, обычно Integer.
Выражение-1 и выражение-2 могут быть как константой или идентификатором, так и вызовом функции.
Действие — один или несколько операторов Delphi. Если это группа операторов, то они должны быть заключены в логические скобки begin/end.
В начале работы оператора переменная-счётчик получает значение выражения-1 . Если при этом значение счётчика окажется меньше или равно значению выражения-2 , то выполняются операторы, входящие в действие . Это и есть один цикл. Затем переменная-счётчик принимает значение, следующее за текущим, и начинается новый цикл, то есть сравнение счётчика и выражения-2 , выполнение действия , и так далее, до тех пор, пока значение переменной-счётчика не превысит значение выражения-2 .
Возможна работа оператора цикла, при котором переменная-счётчик будет не увеличиваться, а уменьшаться. В этом случае ключевое слово to заменяется на downto:
for счётчик := выражение-1 downto выражение-2 do действие ;
Соответственно, выражение-1 должно быть больше или равно выражению-2 .

Условный оператор цикла удобно использовать в том случае, когда количество повторений заранее не известно:
while условие do
тело цикла ;
Этот цикл будет выполняться до тех пор, пока истинно условие (логическое выражение, возвращающее значение типа Boolean). При этом если это выражение сразу равно false, тело цикла не будет выполнено ни разу.
Нужно очень внимательно следить за написанием условия и контролем завершения цикла, так как в результате ошибки цикл while будет повторяться бесконечное количество раз, что приведёт к «зацикливанию» и «зависанию» программы.

Условный оператор повторения сначала выполняет тело цикла , а затем уже проверяет выполнение условия :
repeat
тело цикла
until условие ;
Таким образом, этот вариант цикла гарантирует, что тело цикла будет выполнен по крайней мере один раз. И будет выполняться до тех пор, пока условие не станет истинным (т.е. true). Стоит отметить, что это единственный оператор Delphi, в котором тело цикла не требуется заключать в логические скобки begin/end. Начало и конец тела цикла определяются по ключевым словам repeat и until.

Вместе с операторами цикла используются специальные команды:

  • команда прерывания цикла
  • команда продолжения цикла

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

Справедливости ради стоит рассказать об ещё одном операторе, позволяющем изменить последовательность выполнения программы. Это оператор перехода:
goto метка ;
В качестве метки может использоваться любой допустимый идентификатор или число в диапазоне от 0 до 9999. Метку предварительно необходимо объявить в разделе описания переменных, но с помощью не ключевого слова var, а ключевого слова label:
label меткa ;
или
label список меток ;


Переходить можно как вниз, так и вверх по программе. Двоеточие отделяет метку от оператора, на который производится переход. Пример использования оператора перехода:

Из этого примера видно, что оператор end ; завершающий программу, никогда не будет выполнен, то есть программа зациклится. Именно поэтому, вообще, использование оператора перехода является плохим стилем программирования, и без его использования вполне можно обойтись использованием условных операторов и операторов цикла. Единственный случай, когда использование оператора goto может быть оправдано — это выход из нескольких вложенных циклов, что иначе требует применения нескольких операторов Break.

Пример. Сортировка одномерного массива

Рассматриваются процедуры программы, приводятся подробные комментарии. Также можно скачать проект в виде архива. Цикл while и операторы goto использованы только для демонстрации работы с ними. Здесь — более правильный вариант с применением цикла repeat и оператора break.
Параллельно замечу, что сортировка массива «методом пузырька» — неэффективный метод. Количество итераций (проходов цикла) растёт гораздо быстрее роста количества элементов, . Сортировка 50 000 элементов выполняется на моём компьютере секунд за пять. Но сортировка 100 000 — не за 10 секунд, а около 35 секунд! Можете поэкспериментировать, для этого достаточно во 2 варианте установить в описании массива нужное количество элементов.

Сортировка массивов — типичная задача, где используются циклы. Существует множество методов сортировки массивов. В рассматриваемом примере рассматривается сортировка массива методом «пузырька». В ручном режиме работы программы можно видеть, как числа поднимаются вверх по массиву, подобно всплывающему пузырьку, и становится понятным такое название метода.

type Point=Record //Объявляем тип: Запись
n, digit: Integer; //номер и значение: целые числа
end;
var
Form1: TForm1;
tab: array[1..20] of Point; //Создаём массив записей типа Point

procedure TForm1.FormCreate(Sender: TObject);
begin
StringGr ;//Инициализируем столбцы таблицы
StringGr ;
end;

procedure TForm1.Button1Click(Sender: TObject);
var i: Integer;
begin
Randomize; //Инициализируем «случайную» процедуру
For i:=1 to StringGrid1.RowCount-1 do
begin
tab[i].n:=i; //Присваиваем ячейкам массива порядковые номера
tab[i].digit:=Random(100); //Присваиваем ячейкам массива случайные значения в диапазоне от 0 до 100
StringGr ; //Нумеруем таблицу
StringGr >
end;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Application.Terminate; //Процедура завершения программы
end;

procedure TForm1.Button2Click(Sender: TObject);
var i, n: Integer; //переменные цикла
Sort: Boolean; //Переменная — признак окончания сортировки
Obmen: Point; //Служебная переменная перестановки значений массива
Label manual1, manual2; //Метки операторов перехода
begin
Sort:=True; //Признак неотсортированности массива
n:=StringGrid1.RowCount-1; //Количество строк в таблице (без заголовка)
if RadioButton1.Checked then goto manual1; //Переход на ручной режим
while(Sort=True) do //Начало автоматического режима: в предыдущем цикле было событие сортировки
manual1: //Начало ручного режима
begin
Sort:=False; //Допустим, что массив уже отсортирован (сортировка не нужна)
for i:=1 to n-1 do //Опять проверяем все значения от 1 до n
if(tab[i+1].digit
begin //Если неверно, то переставляем соседние значения:
Obmen:=tab[i]; //1. Сохраняем одно из значений
tab[i]:=tab[i+1]; //2. На его место переписываем соседнее значение
tab[i+1]:=Obmen; //3. Переписываем сохранённое значение на новое место
Sort:=True; //Признак того, что состоялось событие сортировки
end;
if RadioButton1.Checked then goto manual2; //Пропускаем переход к новому циклу автоматического режима
end; //Здесь заканчивается очередной цикл авторежима и осуществляется переход к новому
manual2:
for i:=1 to n do //Переписываем отсортированные значения массива в таблицу
begin
StringGr ;
StringGr >
end;
end;

Есть возможность немного улучшить процедуру сортировки, что ускорит её примерно на четверть. Дело в том, что после каждого завершённого цикла наибольший ещё неотсортированный элемент перемещается на своё место в низ таблицы. То есть, очередной k-й цикл уже последние k элементов может не просматривать. Для реализации этого нужно ввести переменную — счётчик циклов, и отнять её от переменной цикла. При этом те же 100 000 элементов сортируются уже за 24 секунды! Реализацию этого варианта предоставляю читателю, ввиду его крайней простоты.

Delphi/Переменные

Переменная — область оперативной памяти, в которой лежит какое-то значение. Основные типы переменных в Delphi:

  • Integer — целые числа.
  • Real — целые и дробные числа.
  • Boolean — логический тип.
  • Char — символьный тип данных.
  • String — строковой тип данных.

Переменные указываются после ключевого слова var (variable — переменная). Общий вид указывания переменных:

В Delphi есть оператор присваивания — := .Общий вид присваивания:

Но с типом string и char, особое дело. Общий вид присваивания с типом string и char:

Boolean — Тип Delphi

Порядковые типы
Из простых типов данных порядковые — самые простые. В этих типах информация представляется в виде отдельных элементов. Связь между отдельными элементами и их представлением в памяти определяет естественные отношения порядка между этими элементами. Отсюда и название порядковые.
В Object Pascal определены три группы порядковых типов и два типа, определяемых пользователем. Группы — это целые, символьные и булевы типы. Порядковые типы, задаваемые пользователем, — это перечисления и поддиапазоны.
Все значения любого порядкового типа образуют упорядоченную последовательность, и значение переменной порядкового типа определяется его местом в этой последовательности. За исключением переменных целых типов, значения которых могут быть как положительными, так и отрицательными, первый элемент любого порядкового типа имеет номер 0, второй элемент — номер 1 и т.д. Порядковый номер целого значения равен самому значению. Отношение порядка определяет общие для данных всех порядковых типов операции. Некоторые стандартные функции такого вида встроены в Object Pascal. Они представлены в табл. 1.1.

Для всех порядковых типов в Object Pascal существует операция задания типа для преобразования целых значений в значения соответствующих порядковых типов. Если Т — имя порядкового типа, а Х — целое выражение, то Т (X) воз-вращает значение Т с порядковым номером X.

Совет: Программисты, работающие на С и C++, для приращения или уменьшения значений переменных привыкли заметку использовать операторы «++» и «—«, возвращающие следующее и предыдущее значения. Программисты Delphi всегда разбивают эти операции на более простые составляющие с помощью функций Pred, Succ. Dec и Inc.


    Таблица 1.1. Операции над порядковыми типами

ОперацияОписание
Low (T)Минимальное значение порядкового типа Т
High(T)Максимальное значение порядкового типа Т
Ord(X)Порядковый номер значения выражения порядкового типа. Для целого выражения — просто его значение. Для остальных порядковых типов Ord возвращает физическое представление результата выражения, трактуемое как целое число. Возвращаемое значение всегда принадлежит одному из целых типов
Pred(X)Предыдущее по порядку значение. Для целых выражений эквивалентно Х-1
Succ(X)Следующее по порядку значение. Для целых выражений эквивалентно Х+1
Dec(V)Уменьшает значение переменной на 1. Эквивалентно V := Pred(V)
Inc(V)Увеличивает значение переменной на 1. Эквивалентно V := Succ(V)

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

    Integer
    Shortint
    Smallint
    Longint
    Byte
    Word
    Cardinal

Обратите внимание, что один из этих целых типов назван именно целым (integer). Это может иногда приводить к путанице, но мы легко сможем ее избежать, применяя термин целый к. группе типов, a integer — к конкретному типу, определяемому в программе этим ключевым словом. Переменные физических целых типов имеют разные диапазоны значений в зависимости от того, сколько байтов памяти они занимают (что равно значению, возвращаемому функцией SizeOf для данного типа). Диапазоны значений для всех физических типов перечислены в табл. 1.2.

    Таблица 1.2. Физические целые типы


    ТипДиапазон значенииФизический формат
    Shortint-128-1278 бит, со знаком
    Smallint-32 768-32 76716 бит, со знаком
    Longint-2 147 483 648-2 147 483 64732 бит, со знаком
    Byte0-2558 бит, без знака
    Word0-65 53516 бит, без знака


Диапазоны значений и форматы физических целых типов не зависят от микропроцессора и операционной системы, в которых выполняется программа. Они не меняются (или, по крайней мере, не должны меняться) с изменением реализации или версии Object Pascal.
Диапазоны значений логических целых типов (Integer и Cardinal) определяются совершенно иным образом. Как видно из табл. 1.3, они никак не связаны с диапазонами соответствующих физических типов. Обратите внимание, что в Delphi по умолчанию задано 32-разрядное представление.

Таблица 1.3. Логические целые типы


    ТипДиапазон значенийФизический формат
    Integer-32 768-32 76716 бит, со знаком (SmalIInt)
    Integer-2 147 483 648-2 147 483 64732 бит, со знаком (Longint)
    Cardinal0-65 53516 бит, без знака (Word)
    Cardinal0-2 14748364732 бит, без знака (Longint)

Совет: В С и C++ для целых значений определены типы int, short int (или просто short) и long int (или просто long). Тип int из C/C++ соответствует типу Integer из Delphi, a long из C/C++ — Longint из Delphi. Однако Shortint из C/C++ соответствует в Delphi не Shortint, a Smalltlnt. Эквивалент Shortint из Delphi в C/C++— это signed char. Тип unsigned char в C/C++ соответствует типу Byte из Delphi. В C/C++ существует еще тип unsigned long, аналога которому в Delphi нет.

Над целыми данными выполняются все операции, определенные для порядковых типов, но с ними все же удобнее работать как с числами, а не с «нечисленными порядковыми типами». Как и «живые» числа, данные целых типов можно складывать (+), вычитать (-) и умножать (*). Однако некоторые операции и функции, применяемые к данным целых типов, имеют несколько иной смысл.

Операция Результат
Abs (X) Возвращает абсолютное целое значение Х
Х Div Y Возвращает целую часть частного деления Х на Y
Х Mod Y Возвращает остаток частного деления Х на Y
Odd (X) Возвращает булево True (истина), если Х — нечетное целое, и False (ложь) — в противном случае
Sqr (X) Возвращает целый квадрат Х (т.е. Х*Х)

Символьные типы
Смысл символьных данных очевиден, когда они выводятся на экран или принтер. Тем не менее, определение символьного типа может зависеть от того, что подразумевать под словом символ. Обычно символьные типы данных задают схему взаимодействия между участками памяти разного объема и некоторым стандартным методом кодирования/декодирования для обмена символьной информацией. В классическом языке Pascal не задано никакой схемы, и в конкретных реализациях применялось то, что на том же компьютере мог использовать каждый.
В реализациях языка Pascal для первых микропроцессоров была применена 7-битовая схема, названная ASCII (American Standard Code for Information Interchange — Американский стандартный код для обмена информацией). Эта схема и поныне широко распространена, но информация хранится, как правило, в 8-битовых участках памяти. Дополнительный бит удваивает число возможных представлений символов, но реализации расширенного набора символов ASCII часто бывают далеки от стандарта. В данной версии Delphi определен набор 8-битовых символов, известный как расширенный (extended) ANSI (American National Standards Institute — Американский национальный институт стандартов). Как бы то ни было, символьную схему приходится воспринимать так, как ее воспринимает операционная система. Для оконных операционных систем фирмы Microsoft это схема ANSI, включающая ограниченное число предназначенных для вывода международных знаков. В стремлении же применить более обширный набор международных знаков весь компьютерный мир переходит к 16-битовой схеме, именуемой UNICODE, в которой первые 256 знаков совпадают с символами, определенными в схеме ANSI.
Для совместимости со всеми этими представлениями в Object Pascal определены два физических символьных типа и один логический.
Физические типы перечислены ниже.

AnsiChar Однобайтовые символы, упорядоченные в соответствии с расширенным набором символов ANSI
WideChar Символы объемом в слово, упорядоченные в соответствии с международным набором символов UNICODE. Первые 256 символов совпадают с символами ANSI


Символьные типы объемом в двойное слово (32 бит) отсутствуют.
Логический символьный тип именуется char. В классическом языке Pascal char— единственный символьный тип. В Delphi char всегда соответствует физическому типу данных AnsiChar. У американских программистов ассоциация символа с однобайтовой ячейкой памяти укоренилась за долгие годы настолько, что им зачастую просто не приходит в голову, что можно использовать другие схемы кодирования. Однако дискуссии по интернационализации программ в Internet и World Wide Web могут существенно изменить их отношение к проблеме объема символьных данных. Применяя логический тип char, следует делать реализации для других микропроцессоров и операционных систем, в которых char может определяться как WideChar. При написании программ, которые могут обрабатывать строки любого размера, для указания этого размера рекомендуется применять функцию SizeOf, не задавая ее жестко постоянной. Функция Ord (С), где С — любая переменная символьного типа, возвращает целое значение, которым символ С представлен в памяти.


    Chr (X)Преобразует целую переменную в переменную типа char с тем же порядковым номером. В Delphi это эквивалентно заданию типа Char (X)
    UpCaseПреобразует строчную букву в прописную



Совет: Процессор не различает типы char, определенные в C/C++ и Delphi. Однако функционально каждый из этих языков трактует данный тип совершенно по-разному. В C/C++ это целый тип, переменной которого можно присваивать целые значения. Переменной int можно присвоить символьное значение, а переменной char — целое. В Delphi символьные типы жестко отделены от численных. Для присвоения численному значению символьного здесь необходимо воспользоваться функцией Ord. В языке Basic один символ представляется так же, как и строка символов. Функция Chr из Delphi эквивалентна функции CHR$ из Basic. Функция Ord из Delphi, возвращающая код ANSI символьной переменной, подобна функции A3 С из Basic, аргумент которой представляет односимвольную строку.

Булевы типы
На ранней стадии обучения программисты осваивают понятие бита, два состояния которого можно использовать для записи информации о чем-либо, представляющем собой одно из двух. Бит может обозначать 0 или 1, ДА или НЕТ, ВКЛЮЧЕНО или ВЫКЛЮЧЕНО, ВЕРХ или НИЗ, СТОЯТЬ или ИДТИ. В Object Pascal информация о чем-либо, что можно представить как ИСТИНА (True) или ЛОЖЬ (False), хранится в переменных булевых типов. Всего таких типов че-тыре, и они представлены в табл. 1.4.


    Таблица 1.4. Размеры переменных булевых типов


    ТипРазмер
    Boolean1 байт
    ByteBool1 байт
    WordBool2 байт (объем Word)
    LongBool4 байт (объем Longint)


По аналогии с целыми и символьными типами, подразделяющимися на физические и логические, естественно предположить, что ByteBool, WordBool и LongBool — физические типы, Boolean — логический. Но в данном случае это не совсем так. Все четыре типа различны. Для Object Pascal предпочтителен тип Boolean, остальные определены для совместимости с другими языками программирования и операционными системами.
Переменным типа Boolean можно присваивать только значения True (истина) и False (ложь). Переменные ByteBool, WordBool и LongBool могут принимать и другие порядковые значения, интерпретируемые обычно как False в случае нуля и True — при любом ненулевом значении.

Совет: Булевы типы в Delphi можно сравнить с типом LOGICAL языка FORTRAN. В Basic, С и C++ булевы типы как таковые отсутствуют. Булевы выражения в этих языках применяются точно так же, как во всех остальных, однако результаты этих выражений интерпретируются не как значения отдельного типа, а как целые числа. Как в Basic, так и в C/C++ булевы выражения дают численные результаты, интерпретируемые как False в случае 0 и True — в случае любого ненулевого значения. Это совместимо с порядковыми значениями булевых выражений в Delphi. В C/C++ простые сравнения дают результат 1 (True) или 0 (False). Это эквивалентно булевым значениям Delphi. Только результат сравнения в Delphi выводится как булевый, а не целый. В большинстве случаев типу Boolean из Delphi соответствует тип char в C/C++. В Basic зарезервированы слова TRUE (эквивалентно константе -1) и FALSE (эквивалентно константе 0). В Basic TRUE меньше FALSE, в Delphi, наоборот, False меньше True.

Перечислимые типы
Type enum type = (first value, value2, value3, last value);
Обычно данные перечислимых типов содержат дискретные значения, представляемые не числами, а именами. Тип Boolean— простейший перечислимый тип в Object Pascal. Булевы переменные могут принимать два значения, выражаемые именами True и False, а сам тип определен в Object Pascal так, как будто он объявлен следующим образом:
Type Boolean = (False, True);
С помощью типа Boolean в Object Pascal выполняются сравнения, большинство же перечислимых типов — это просто списки уникальных имен или идентификаторов, зарезервированных с конкретной целью. Например, можно создать тип MyColor (мой цвет) со значениями myRed, myGreen и myBlue (мой красный, мой зеленый, мой синий). Это делается совсем просто:
Type MyColor = (myRed, myGreen, myBlue);
В этой строке объявлены четыре новых идентификатора: MyColor, myRed, myGreen и myBlue. идентификатором MyColor обозначен порядковый тип, следовательно, в синтаксисе Object Pascal можно применять этот идентификатор везде, где разрешены перечислимые типы. Остальные три идентификатора— это значения типа MyColor. Подобно символьным и булевым типам перечислимые не являются числами, и использовать их наподобие чисел не имеет смысла. Однако перечислимые типы относятся к порядковым, так что значения любого такого типа упорядочены. Идентификаторам в списке присваиваются в качестве порядковых номеров последовательные числа. Первому имени присваивается порядковый номер 0, второму — 1 и т.д.

Совет: В С и C++ есть тип enema, аналогичный перечислимому типу Delphi. Но в этих языках можно произвольно присваивать идентификаторам постоянные значения. В Delphi же соответствие имен и их значений фиксиро-вано: первому имени присваивается значение 0, каждому последующему — на единицу больше. В С тип enum применяется лишь как средство быстрого определения набора целых постоянных. В C++ объявленные в перечислимом типе идентификаторы можно присваивать только переменным того же типа.

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

Type subrange type = low value. high value;

Поддиапазонные переменные сохраняют все особенности исходного типа. Единственное отличие состоит в том, что переменной поддиапазонного типа можно присваивать только значения, входящие в заданный поддиапазон. Контроль за соблюдением этого условия задается командой проверки диапазона (range checking).
Необходимость явно определять поддиапазонный тип возникает нечасто, но все программисты неявно применяют эту конструкцию при определении массивов. Именно в форме поддиапазонной конструкции задается схема нумерации элементов массива.

Илон Маск рекомендует:  session_start - инициализирует данные сессии
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL