ЗАПИСИ


Запись - это структура данных, состоящая из фиксированного количества компонентов, называемых полями записи. В отличие от массива компоненты (поля) записи могут быть различного типа. Чтобы можно было ссылаться на тот или иной компонент записи, поля именуются.
Структура объявления типа записи такова:
<имя типа> = record <сп.полей> end;
Здесь <имя типа> - правильный идентификатор; record/ end - зарезервированные слова {запись, конец); <сп.полей> - список полей; представляет собой последовательность разделов записи, между которыми ставится точка с запятой.
Каждый раздел записи состоит из одного или нескольких идентификаторов полей, отделяемых друг от друга запятыми. За идентификатором (идентификаторами) ставится двоеточие и описание типа поля (полей), например:
type
BirthDay = record Day, Month: Byte;
Year : Word end;
var
a,b : Birthday;
В этом примере тип BirthDay (день рождения) есть запись с полями Day, Month и Year (день, месяц и год); переменные а и в содержат записи типа BirthDay.
Как и в массиве, значения переменных типа записи можно присваивать другим переменным того же типа, например
а := b;
К каждому из компонентов записи можно получить доступ, если использовать составное имя, т. е. указать имя переменной, затем точку и имя поля:
a.day := 27;
b.year := 1939;
Для вложенных полей приходится продолжать уточнения:
type
BirthDay = record Day,Month: Byte;
Year : Word end;
var
с : record
Name : String;
Bd : BirthDay end;
begin
if c.Bd.Year = 1989 then ... end.
Чтобы упростить доступ к полям записи, используется оператор присоединения with:
with <переменная> do <оператор>;
Здесь with, do - зарезервированные слова (с, делать);
<переменная> - имя переменной типа запись, за которой, возможно,
следует список вложенных полей; <оператор> - любой оператор Object Pascal.
Например:
с.Bd.Month := 9;
Это эквивалентно
with c.Bd do Month := 9;
или with с do with Bd do Month := 9;
или with с, Bd do Month := 9;
Object Pascal разрешает использовать записи с так называемыми вариантными полями, например:
type
Forma = record Name : String;
case byte of
0: (Birthplace: String [40]);
1: (Country : String [20];
EntryPort : String [20];
EntryDate : 1..31;
ExitDate : 1..31)
end;
В этом примере тип Forma определяет запись с одним фиксированным полем Name и вариантной частью, которая задается предложением case ... of. Вариантная часть состоит из нескольких вариантов (в примере - из двух вариантов: 0 и 1). Каждый вариант определяется константой выбора, за которой следуют двоеточие и список полей, заключенный в круглые скобки. В любой записи может быть только одна вариантная часть, и, если она есть, она должна располагаться за всеми фиксированными полями.
Замечательной особенностью вариантной части является то обстоятельство, что все заданные в ней варианты “накладываются” друг на друга, т. е. каждому из них выделяется одна и та же область памяти.
Это открывает дополнительные возможности преобразования типов, например:
var
Mem4 : record case Byte of
0 : (by : array [0..3] of Byte);
1 : (wo : array [0..1] of Word);
2 : (lo : Longint) ;
end;
В этом примере запись мет4 имеет три варианта, каждый из которых занимает в памяти один и тот же участок из 4 байт. В зависимости от того, к какому полю записи мы обращаемся в программе, этот участок может рассматриваться как массив из 4 байт (поле by), массив из двух целых типа word (поле wo) или, наконец, как одно целое число типа Longint (поле l0). Например, этой записи можно сначала присвоить значение как длинному целому, а затем проанализировать результат по байтам или словам:
var
х : Word;
xb: Byte;
xl: Longint;
begin
with m do begin
lo := Trunc(2*pi*x);
if wo[l] =0 then if by[l] =0 then
xb := x[0] else
x := wo[0] else
xl := lo
end;
end.
Предложение case ... of, открывающее вариантную часть, внешне похоже на соответствующий оператор выбора, но на самом деле лишь играет роль своеобразного служебного слова, обозначающего начало вариантной части. Именно поэтому в конце вариантной части не следует ставить end как пару к case ... of. (Поскольку вариантная часть - всегда последняя в записи, за ней все же стоит end, но лишь как пара к record). Ключ выбора в предложении case ... of фактически игнорируется компилятором: единственное требование, предъявляемое к нему в Object Pascal, состоит в том, чтобы ключ определял некоторый стандартный или предварительно объявленный порядковый тип.
Имена полей должны быть уникальными в пределах той записи, где они объявлены, однако, если записи содержат поля-записи, т. е. вложены одна в другую, имена могут повторяться на разных уровнях вложения.
Множества
Множества - это наборы однотипных логически связанных друг с другом объектов. Характер связей между объектами лишь подразумевается программистом и никак не контролируется Object Pascal. Количество элементов, входящих в множество, может меняться в пределах от 0 до 256 (множество, не содержащее элементов, называется пустым). Именно непостоянством количества своих элементов множества отличаются от массивов и записей.
Два множества считаются эквивалентными тогда и только тогда, когда все их элементы одинаковы, причем порядок следования элементов в множестве безразличен. Если все элементы одного множества входят также и в другое, говорят о включении первого множества во второе. Пустое множество включается в любое другое.
Пример определения и задания множеств:
type
digitChar = set of '0'..'9';
digit = set of 0. .9;
var
sl,s2,s3 : digitChar;
s4,s5,s6 : digit;
begin
si = ['1', '2', '3'];
s2 = ['3', '2', '1'];
s3 = ['2', '3'];
s4 = [0..3, 6];
s5 = [4, 5];
s6 = [3..9];
end.
В этом примере множества si и s2 эквивалентны, а множество S3 включено в s 2 , но не эквивалентно ему.
Описание типа множества имеет вид:
<имя типа> = set of <базовый тип>;
Здесь <имя типа> - правильный идентификатор; set, of - зарезервированные слова (множество, из); <базовый тип> - базовый тип элементов множества, в качестве которого может использоваться любой порядковый тип, кроме Word, Integer, Longint, Int64.
Для задания множества используется так называемый конструктор множества: список спецификаций элементов множества, отделенных друг от друга запятыми; список обрамляется квадратными скобками. Спецификациями элементов могут быть константы или выражения базового типа, а также тип-диапазон того же базового типа.
Над множествами определены следующие операции:
* пересечение множеств; результат содержит элементы, общие для обоих множеств; например, s4*s6 содержит [3], s4*s5 -пустое множество (см. выше);
+ объединение множеств; результат содержит элементы первого множества, дополненные недостающими элементами из второго множества:
S4+S5 содержит [0,1,2,3,4,5,6];
S5+S6 содержит [3, 4, 5, 6, 7, 8, 9] ;
разность множеств; результат содержит элементы из первого множества, которые не принадлежат второму:
S6-S5 содержит [3,6,7,8,9];
S4-S5 содержит [0,1, 2, 3, 6] ;
= проверка эквивалентности; возвращает True, если оба множества эквивалентны;
<> проверка неэквивалентности; возвращает True, если оба множества неэквивалентны;
<= проверка вхождения; возвращает True, если первое множество включено во второе;
>= проверка вхождения; возвращает True, если второе множество включено в первое;
in проверка принадлежности; в этой бинарной операции первый элемент - выражение, а второй - множество одного и того же типа; возвращает True, если выражение имеет значение, принадлежащее множеству:
3 in s 6 возвращает True;
2*2 in si возвращает False.
Дополнительно к этим операциям можно использовать две процедуры.
include - включает новый элемент во множество. Обращение к процедуре:
Include(S,I)
Здесь s - множество, состоящее из элементов базового типа TSet Base; I - элемент типа TSetBase, который необходимо включить во множество.
exclude - исключает элемент из множества. Обращение:
Exclude(S,I)
Параметры обращения - такие же, как у процедуры include. В отличие от операций + и -, реализующих аналогичные действия над двумя множествами, процедуры оптимизированы для работы с одиночными элементами множества и поэтому отличаются высокой скоростью выполнения.
Учебная программа PRIMSET
В следующем примере, иллюстрирующем приемы работы с множествами, реализуется алгоритм выделения из первой сотни натуральных чисел всех простых чисел[ Простыми называются целые числа, которые не делятся без остатка на любые другие целые числа, кроме 1 и самого себя. К простым относятся 1, 2, 3, 5, 7, 11, 13 и т. д.. ]. В его основе лежит прием, известный под названием “решето Эратосфена”. В соответствии с этим алгоритмом вначале формируется множество BeginSet, состоящее из всех целых чисел в диапазоне от 2 до N. В множество primerset (оно будет содержать искомые простые числа) помещается 1. Затем циклически повторяются следующие действия:

  • взять из BeginSet первое входящее в него число Next и поместить его В PrimerSet;
  • удалить из BeginSet число Next и все другие числа, кратные ему, Т. е. 2*Next, 3*Next И Т.Д.

Цикл повторяется до тех пор, пока множество BeginSet не станет пустым.
Эту программу нельзя использовать для произвольного N, так как в любом множестве не может быть больше 256 элементов.
procedure TfmExample.bbRunClick(Sender: TObject);
// Выделение всех простых чисел из первых N целых
const
N = 255; // Количество элементов исходного множества
type
SetOfNumber = set of 1..N;
var
n1,Next,i: Word; // Вспомогательные переменные
BeginSet, // Исходное множество
PrimerSet: SetOfNumber; // Множество простых чисел
S : String;
begin
BeginSet := [2..N];
// Создаем исходное множество
PrimerSet:= [1]; // Первое простое число
Next := 2; // Следующее простое число
while BeginSet о [ ] do // Начало основного цикла
begin
nl := Next; //nl-число, кратное очередному простому (Next)
// Цикл удаления из исходного множества непростых чисел:
while nl <= N do
begin
Exclude(BeginSet, nl);
n1 := nl + Next // Следующее кратное
end; // Конец цикла удаления
Include(PrimerSet, next);
// Получаем следующее простое, которое есть первое
// число, не вычеркнутое из исходного множества
repeat
inc(Next)
until (Next in BeginSet) or (Next > N)
end;
// Конец основного цикла
// Выводим результат:
S := '1';
for i := 2 to N do
if i in PrimerSet then
S := S+', '+IntToStr(i);
mmOutput.Lines.Add(S)
end;
Перед тем как закончить рассмотрение множеств, полезно провести небольшой эксперимент. Измените описание типа SetOfNumber следующим образом:
type
SetOfNumber = set of 1..1;
и еще раз запустите программу из предыдущего примера. На экран будет выведено 1, 3, 5, 7
Множества BeginSet и PrimerSet состоят теперь из одного элемента, а программа сумела поместить в них не менее семи!
Секрет этого прост: внутреннее устройство множества таково, что каждому его элементу ставится в соответствие один двоичный разряд (один бит); если элемент включен во множество, соответствующий разряд имеет значение 1, в противном случае - 0. В то же время минимальной единицей памяти является один байт, содержащий 8 бит, поэтому компилятор выделил множествам по одному байту, и в результате мощность каждого из них стала равна 8 элементам. Максимальная мощность множества - 256 элементов. Для таких множеств компилятор выделяет по 16 смежных байт.
И еще один эксперимент: измените диапазон базового типа на 1..256. Хотя мощность этого типа составляет 256 элементов, при попытке компиляции программы компилятор сообщит об ошибке: Sets may have at most 256 elements (Множества могут иметь не более 256 элементов) т. к. нумерация элементов множества начинается с нуля независимо от объявленной в программе нижней границы. Компилятор разрешает использовать в качестве базового типа целочисленный тип-диапазон с минимальной границей 0 и максимальной 255 или любой перечисляемый тип не более чем с 256 элементами (максимальная мощность перечисляемого типа - 65536 элементов).
СТРОКИ
Для обработки текстов в Object Pascal используются следующие типы:

  • короткая строка shortString или string [n] , где n <= 255;
  • длинная строка string;
  • широкая строка WideString;
  • нуль-терминальная строка pchar.

Общим для этих типов является то, что каждая строка трактуется как одномерный массив символов, количество символов в котором может меняться в работающей программе: для string [n] длина строки меняется от 0 до n, для string и pchar - от 0 до 2 Гбайт.
В стандартном Паскале используются только короткие строки String [n] . В памяти такой строке выделяется n+i байт, первый байт содержит текущую длину строки, а сами символы располагаются начиная со 2-го по счету байта. Поскольку для длины строки в этом случае отводится один байт, максимальная длина короткой строки не может превышать 255 символов. Для объявления короткой строки максимальной длины предназначен стандартный тип ShortString (эквивалент String[255]).
В Windows широко используются нуль-терминальные строки, представляющие собой цепочки символов, ограниченные символом #о. Максимальная длина такой строки лимитируется только доступной памятью и может быть очень большой.
В 32-разрядных версиях Delphi введен новый тип string, сочетающий в себе удобства обоих типов. При работе с этим типом память выделяется по мере надобности (динамически) и ограничена имеющейся в распоряжении программы доступной памятью. Замечу, что в Delphi 1 тип string эквивалентен String [2 55], т. е. определяет короткую строку максимально возможной длины.
Для совместимости с компонентами, основывающимися на OLE-технологии, в Delphi 32 введены также широкие строки, объявляемые стандартным типом wideString. По своим свойствам они идентичны длинным строкам string, но отличаются от них тем, что для представления каждого символа используются не один, а два байта.
Примеры объявлений строковых типов:
var
ssS: String[250];// Короткая строка длиной до 250 символов
ssMax: ShortString;// Короткая строка длиной до 255 символов
stS : String; // Длинная строка
swS: WideString;// Широкая строка
pcS: PChar; // Ссылка на нуль-терминальную строку
acS: array [0..1000] of Char; // Нуль-терминальная строка
// длиной до 1000 символов
При объявлении переменной sss компилятор выделит для ее размещения 250 + 1 = 251 байт и поместит в первый байт 0 - текущую длину строки. При выполнении такого фрагмента программы:
procedure TfmExample.bbRunClick(Sender: TObject);
var
ssS: String[250];
begin
ssS :='Строка символов';
ssS[6] := ' и'; // Символы в строке нумеруются, начиная с 1
IbOutput.Caption := ssS; // Выводится “Строки символов”
end;
сначала в переменную ssS будет помещена цепочка символов строка символов, причем 1-й байт получит значение 15 (количество символов в строке). После выполнения второго оператора символ с индексом б (индексация байтов начинается с 0, но, поскольку первый байт содержит текущую длину, первый символ в строке имеет индекс 1) будет заменен на “и”, и в переменной окажется цепочка строки символов.
Совершенно другим будет механизм работы с памятью при объявлении длинной строки sts: компилятор выделит для переменной 4 байта, достаточные для размещения номера той ячейки памяти, начиная с которой будет фактически располагаться символьная строка. Говорят, что sts ссылается на строку. Такого рода переменные-ссылки называются указателями и обсуждаются в гл. 9. При выполнении первого оператора такого обработчика:
procedure TfmExample.bbRunClick(Sender: TObject);
var
stS, stSS: String;
begin
stS :='Строка символов';
stSS := stS;
stS := 'Это - '+stS;
stS[7] := ' c' ; // Символы в строке нумеруются, начиная с 1
IbOutput.Caption := stS; //Выводится “Это - строка символов”
end;
программа (а не компилятор!) определит длину цепочки символов Строка символов, обратится к ядру перационной системы (ОС) с требованием выделить для нее участок памяти длиной 15+5=20 байт, поместит в переменную sts номер первого выделенного байта [ На самом деле в stS запоминается дескриптор выделенного участка памяти, см. гл. 9. ] и, начиная с него, разместит в этом участке цепочку символов, завершив ее терминальным нулем и 4-байтным счетчиком ссылок. Такое размещение на этапе прогона программы называется динамическим, в то время как размещение на этапе компиляции - статическим. Счетчик ссылок играет важную роль в механизме работы с памятью. С его помощью реализуется “кэширование” памяти: при выполнении оператора
stSS := stS;
память для размещения значения переменной stSS не выделяется, в переменную stSS помещается содержимое указателя sts, а счетчик ссылок в связанной с ним памяти увеличивается на единицу. Таким образом, оба указателя будут ссылаться на одну и ту же область памяти, счетчик ссылок которой будет содержать значение 2. При выполнении оператора
stS := 'Это - '+stS;
счетчик ссылок уменьшается на единицу, выделяется новая область памяти длиной 2 о + б = 2 б байт, указатель на эту область помещается в stS, а в саму память переписывается цепочка символов Это -строка символов, терминальный ноль и содержащий единицу счетчик ссылок. Теперь переменные stS и stss будут ссылаться на разные участки памяти, счетчики ссылок которых будут содержать по единице. Выделенная для размещения строки String область памяти освобождается, если ее счетчик ссылок стал равен нулю.
Похожим образом осуществляется работа с памятью при объявлении переменной pcs типа pchar: компилятор считает эту переменную указателем и выделит для нее 4 байта:
procedure TfmExample.bbRunClick(Sender: TObject);
var
pcS: PChar;
begin
pcS :='Строка символов';
pcS[5] := 'и'; {Символы в нуль-строке нумеруются,начиная с 0}
IbOutput.Caption := pcS; // Выводится “Строки символов”
end;
Программа потребует от ОС 15 + 1 = 16 байт, разместит в памяти цепочку символов и завершающий ее терминальный 0 и поместит адрес выделенного участка памяти в pcs.
Примечание
В стандартном паскале, при обращении к области памяти, на которую ссылается указатель , требуется за именем указателя ставить специальный символ .“^”. В Object Раsса1 интенсивно используется динамическая, память, и поэтому, это жесткое требование смягчено: в большинстве случаев (и при обращении к типу pchar в том числе) символ "^" ставить не следует.
И, наконец, последнее объявление acs как массива символов. В Object Pascal считается совместимым с pchar одномерный массив символов с нулевой нижней границей. В отличие от pcs память для такой переменной выделяется статически (в нашем примере компилятор выделит в сегменте данных для переменной acs 1001 байт).
Для размещения в acs нуль-терминальной цепочки символов используется процедура strcopy:
procedure' TfmExample.bbRunClick(Sender: TObject) ;
var
acS: array [0..1000] of Char;
begin
StrCopy(acS,'Строка символов') ;
acS[5] := 'и'; { Символы в нуль-строке нумеруются,начиная с 0}
lbOutput.Caption := acS; // Выводится “Строки символов”
end;
Необходимость в нуль-терминальных строках возникает только при прямом обращении к API-функциям ОС. При работе с компонентами Delphi в основном используются более удобные длинные строки.

И несколько слов о широких строках, 32-разрядные версии Windows используют три сорта символов: однобайтный символ ANSI, двухбайтный символ и символ Unicode. Однобайтный символ связан с одним из 256 возможных значений, которые трактуются в зависимости от установленной в Windows национальной страницы (для размещения кириллицы используется страница 1251). 256 символов вполне достаточны для отображения национального алфавита любого европейского языка. Для отображения алфавитов некоторых азиатских языков этого недостаточно. В этом случае используется двухбайтный символ, в котором младший байт обычно кодируется семибитным ASCII-кодом, а старший указывает, как должен трактоваться этот код (каким символом он будет изображаться в документе или на экране). Символ Unicode в памяти занимает одно слово, которое имеет 65536 возможных значений. Специальная международная комиссия по Unicode выработала соглашение, позволяющее с помощью этого кода представить все символы всех языков мира. Двухбайтные символы и символы Unicode объявляются стандартным типом widecnar, а составленные из них строки - типом widestring. Все Windows-программы, использующие OLE-технологию обмена строками, должны кодировать символы в соответствии с Unicode.

Типы String и ShortString


Несмотря на разницу во внутреннем представлении, короткие строки ShortString и длинные строки string имеют для программиста одинаковые свойства.
Текущую длину строки можно получить с помощью функции Length. Например, следующий оператор уничтожает все ведомые (хвостовые) пробелы:
while (Length(stS) о 0) and (stS[Length(stS)] = ' ' ) do
SetLentgh(stS, Length (stS) - 1);
В этом примере стандартная процедура setLength устанавливает новую длину строки. К строкам можно применять операцию “+” -сцепление, например:
stS := 'а' + 'b'; // stS содержит "ab"
stS := stS + ' с '; // stS содержит "abc"
Если длина сцепленной строки превысит максимально допустимую длину N короткой строки, то “лишние” символы отбрасываются. Следующая программа, например, выведет символ “I”:
Procedure TfmExamlpe.bbRunClick(Sender: TObject);
var
ssS: String[1];
begin
ssS := '123';
IbOutput := ssS;
end;
Операции отношения =, <>, >, <, >=, <= выполняются над двумя строками посимвольно, слева направо с учетом внутренней кодировки символов. Если одна строка меньше другой по длине, недостающие символы короткой строки заменяются значением #о.
Следующие операции отношения дадут значение True:
'''' < '.'
'А' > '1'
'Object' < ' Object Pascal'
'Пас' > 'Pasc al'
Все остальные действия над строками и символами реализуются с помощью описываемых ниже стандартных процедур и функций (в квадратных скобках указываются необязательные параметры).
Таблица 7.7. Процедуры и функции для работы со строками

 
При преобразовании с помощью функций StrToxxx строка может содержать недопустимые для типа ххх символы. В этом случае возбуждается исключительная ситуация EConvertError. При обратных преобразованиях xxxToStr формат получаемой строки зависит от установленных в Windows системных параметров: разделителей даты, времени, целой и дробной частей вещественного числа.
Примечание
Обычно разделителем групп разрядов в русской языке принято считать пробел. Однако в русифицированном варианте Windows для этих целей на самом деле используется, не пробел, а символ-#160, внешне похожий на пробел Убедиться: в, этом можно с помощью такой несложной программы:
procedure TfmExample.bbRunClick (Sender : TObject) ;
var S: String;
begin
S:=FloatToStrF(1000,ffNumber,4,0);
EdOutput.Yext:=IntToStr(Ord(S[2]));
end;
Если вы действительно хотите использовать пробел, его нужно явно указать в окошке. Разделитель: групп разрядов (Пуск.| Настройка | Панель управления | Язык и стандарты | Числа)
В Delphi 4...6 изменена функция StrToDate для того, чтобы упростить ввод двух цифр года с учетом смены столетия. С этой целью в модуле system введена глобальная переменная TwoDigitYearCenturywindow, которая определяет цифровой рубеж столетия. Если две цифры года больше или равны значению этой переменной, цифры года относятся к текущему столетию, если меньше - переносятся в следующее. Пусть, например, TwoDigitYearCenturywindow содержит значение 50. Тогда любые две цифры года в диапазоне 00..49 дополняются базой 2000 (2000, 2001,...,2049), в то время как цифры в диапазоне 50..99 дополняются базой 1900 (1950, 1951,...,1999). Такой прием позволяет в известной мере смягчить проблему двухцифровых годов на рубеже столетия, однако полным ее решением будет, разумеется переход на четырехцифровое представление года. По умолчанию TwoDigitYearCenturywindow имеет значение 0, и поэтому любые две цифры года дополняются базой 1900.
Используемая в процедуре DateTimeToString и в функции FormatDateTime строка Format может содержать такие символы-спецификаторы (в примерах показаны строки для времени 19 часов 45 минут и даты 8 июня 1999 года):
Таблица 7.8. Спецификаторы формата даты/времени

 Замечу, что любые другие символы, указанные в строке Format, a также заключенные в апострофы или кавычки специальные символы-спецификаторы помещаются в выходную строку без преобразования, поэтому спецификаторы 'h час n мин' дадут строку 19 час 45 мин, а 'h час "n" мин' - 19час n мин.
При форматном преобразовании времени-даты или других типов в строку и обратно могут пригодиться следующие системные переменные.
Таблица 7.9. Системные переменные, управляющие стандартным отображением данных

Например, многие бухгалтерские программы в западных странах используют еженедельный отчет. В этом случае может пригодиться следующая подпрограмма, которая по заданной дате возвращает год, номер недели от его начала, дату понедельника и дату воскресенья:
procedure WeekToDates(aDate: TDateTime;
var Week: Byte;
var Year: Word;
var FirstDate, LastDate: TDateTime);
{Возвращает для указанной даты aDate год Year, номер недели от начала года Week, а также даты начала и конца недели} var
S: String;
begin
//Получаем в S символы года для даты aDate:
DateTimeToString(S,'yyyy',aDate) ;
//Формируемдату 1 января:
FirstDate := StrTo-Date('01'+DateSeparator+'01'+DateSeparator+S) ;
Year := StrToInt(S); //Возвращаем год
//Формируем последнюю дату 1-йнедели:
LastDate := FirstDate;
DateTimeToString(S,'dddd',LastDate) ;
while SOLongDayNames [1] do
// LongDayNames [1 ]= 'воскресенье '
begin
LastDate := LastDate+1;
DateTimeToString(S,'dddd',LastDate);
end;
Week := 1;
//Циклическинаращиваем FirstDate, LastDate и Week, пока
// LastDate не станет больше или равна aDate:
while LastDate<aDate do
begin
inc(Week);
FirstDate := FirstDate+7;
LastDate := LastDate+7
end
end; // WeekToDates

Для форматного преобразования вещественных чисел предназначены функции FloatToStrF и FormatFloat. Первая использует значение Format перечисляемого типа TFloatFormat и два дополнительных параметра - Precision и Digits. Правила использования параду метров функции FloatToStrF показаны в следующей таблице' (примеры преобразования даются для value = П = 3,141593654, Precision = 5 и Digits = 2):

Как и в случае даты/времени, любые другие символы строки Format, а также заключенные в апострофы или кавычки специальные символы-спецификаторы помещаются в выходную строку без преобразования: для value = 71*1000 спецификаторы'#, рубля' дадут строку 3 142 рубля. С помощью символа “;” можно задавать различные формы представления положительного, отрицательного и нулевого числа. При этом набор спецификаторов без “;” относится ко всем числам; если используется один символ “;”, то спецификаторы слева от него применяются для форматирования положительных чисел, справа - отрицательных, а вывод нулей подавляется; при использовании двух символов “; ” первый набор - для положительных, второй - для отрицательных и третий - для нулевых чисел. Например, спецификаторы '#;нуль' для value = -1 выведут нуль, а для value = о ничего не выведут, в то время как спецификаторы '#;00;нуль' для value = -1 выведут 01, а для value = 0 - строку нуль. Спецификаторы '#;;нуль' для value = -1 выведут -1, т. к. в этом случае спецификатор для отрицательных чисел не задан и для их вывода будет использован спецификатор положительных чисел, в то время как спецификаторы '#; ;нуль' подавляют вывод отрицательных чисел.
Мощная функция преобразования Format (табл. 7.7) перешла в Object Pascal из языка Си. Она позволяет преобразовать сразу несколько элементов открытого массива аргументов в соответствии с указаниями форматирующей строки. Например, Format('Строка "%s" содержит %d символов',['Паскаль',7]) даст такой результат: Строка "Паскаль" содержит 7 символов.
Элементами массива аргументов могут быть константы и/или переменные целого и вещественного типа, строки и указатели.
Форматирующая строка - это произвольная строка, в которую в любом месте можно вставить форматирующий спецификатор. Количество форматирующих спецификаторов должно быть не больше количества элементов массива аргументов - в противном случае возникнет исключительная ситуация. Каждому элементу массива аргументов по порядку их перечисления в конструкторе массива функция ставит в соответствие форматирующий спецификатор по порядку его следования в форматирующей строке: первому аргументу - первый спецификатор, второму - второй и т. д. Если количество спецификаторов меньше количества аргументов, “лишние” аргументы игнорируются.
Форматирующий спецификатор всегда начинается символом процента и в общем случае имеет такую структуру (в квадратных скобках указываются необязательные элементы):
"%" [index ":"] ["-"] [width] ["." prec] type
Здесь: index ":" - индекс открытого массива, с помощью этого элемента можно явно указать аргумент, который будет обрабатывать спецификатор; "-" указывает на необходимость прижать отформатированный спецификатором текст к левой границе отведенного для него пространства; width - число, определяющее количество символов для обработанного спецификатором текста; если это число меньше требуемого, этот элемент спецификатора игнорируется, если больше - дополняется справа (если есть элемент "-") или слева (если он отсутствует) нужным количеством пробелов; "." prec - задает точность представления целых и вещественных типов; type - символ, определяющий тип форматирования (см. таблицу ниже).
Таблица 7.12. Форматирующие спецификаторы для функции Format

Функция не чувствительна к высоте букв, указывающих тип преобразования. Параметры index, ргес и width задаются явно (числами в форматирующей строке) или неявно - с помощью символа “*”. В этом случае в качестве параметра берется значение очередного аргумента в списке аргументов (он должен быть целым числом). Например, два следующих обращения дадут одинаковый результат:
Format ('%*.*f, [8, 2, 123.456]);
Format ('%8.2f, [123.456]);

 

 
На главную | Содержание | < Назад....Вперёд >
С вопросами и предложениями можно обращаться по nicivas@bk.ru. 2013 г. Яндекс.Метрика