
V1: MyRec;
V2: record
N: longint ;
FIO: string[40] ;
BirthDate: DateTime ;
end;
procedure Proc1(v: MyRec) ;
begin
Writeln(v.FIO) ;
with v do
begin
Writeln(N) ;
Writeln(BirthDate.Day:2,’.’, BirthDate.Month:2,’.’, BirthDate.Year:4) ;
end;
end;
procedure Proc2(v: MyRec) ;
begin
Writeln(v.FIO) ;
with v do
begin
Writeln(N) ;
with v.BirthDate do
Writeln(Day,’.’, Month,’.’, Year) ;
end;
end;
begin
N := 2 ;
v1.N := 1;
v1.FIO := ‘Ivanov I.I.’;
v1.BirthDate.Year := 1950;
v1.BirthDate.Month := 10;
v1.BirthDate.Day := 2;
Proc1(v1) ; // Нормально
// Proc1(v2) ; // Ошибка
Proc2(v1) ; // Нормально
readln ;
end.
Упакованные записи
type
{$PACKRECORDS 1}
MyRecordType1A = record
A: byte;
B: word;
end;
{$PACKRECORDS 2}
MyRecordType1B = packed record
A: byte;
B: word;
end;
MyRecordType1C = record
A: byte;
B: word;
end;
{$ALIGNMENT ON}
{$ALIGN 8}
MyRecordType1D = record
A: byte;
B: word;
end;
begin
writeln(SizeOf(MyRecordType1A)); // 3
writeln(SizeOf(MyRecordType1B)); // 3
writeln(SizeOf(MyRecordType1C)); // 4
writeln(SizeOf(MyRecordType1D)); // 4
readln;
end.
Распакованные массивы символов хранятся в памяти ЭВМ по одному символу в машинном слове, упакованные - по одному символу в байте
Билет №17
Пример. Найти все способы расстановки восьми ферзей на шахматной доске 8×8, при которых ферзи не бьют друг друга.
Разности
индексов у элементов матрицы размера
:
Суммы индексов у элементов матрицы размера :
uses CRT;
var
c: char;
n: integer;
mG: array [1..8] of boolean; // Вертикали
mDP: array [2..16] of boolean; // Диагонали, параллельные побочной
mDM: array [-7..7] of boolean; // Диагонали, параллельные главной
x: array [1..8] of integer;
procedure PutNextQueen(i: integer);
var
j, k: integer;
begin
for j := 1 to 8 do
begin
if mG[j] and mDP[i + j] and mDM[i - j] then
begin
x[i] := j;
if i < 8 then
begin
mG[j] := false; mDP[i + j] := false; mDM[i - j] := false;
PutNextQueen(i + 1);
mG[j] := true; mDP[i + j] := true; mDM[i - j] := true;
end
else
begin
for k:=1 to 8 do write(x[k]:5);
writeln;
Inc(n);
if n mod 20 = 0 then
// Останавливать вывод после показа очередной порции из 20 вариантов
begin
c := ReadKey;
if c = #27 then halt;
if c = #0 then c := ReadKey;
// Код «0» означает, что клавиша отправила в буфер клавиатуры
// два кода, второй из которых также должен быть извлечен
end;
end;
end;
end;
end;
begin
for n := 1 to 8 do x[n]:=0;
for n := 1 to 8 do mG[n] := true;
for n := 2 to 16 do mDP[n] := true;
for n := -7 to 7 do mDM[n] := true;
n := 0;
PutNextQueen(1);
writeln(‘n=’, n);
end.
Билет №18
Тип «Множество»
<Объявление типа «Множество»> :: =
type
<Имя типа «Множество»> =
Set Of <Список (перечисление) или диапазон значений>;
<Объявление переменной типа «Множество»> :: =
var
<Имя переменной> : Set Of <Список (перечисление) или диапазон значений>;
//или
<Имя переменной> : <Имя типа «Множество»>;
Операции над множествами:
+ Объединение
- Вычитание
* Пересечение
Проверка отношения двух множеств:
= Равно
<> Не равно
<= Левое множество содержится в правом
>= Левое множество содержит в себе правое
Проверка принадлежности элемента множеству:
in Левый элемент принадлежит правому множеству
Пример
type
EnglishLetterType = 'A' .. 'z'; // Все английские буквы
EnglishLettersSetType = set of EnglishLetterType;
SetOfDigitsType = set of 0 .. 9; // Все десятичные цифры
MonthesType = (June, July, August); // Все летние месяцы
var
EnglishLetters: EnglishLettersSetType;
P: SetOfDigitsType;
A, B, C: set of 0 .. 9;
M: MonthesType;
Билет №19
Тип «Денежный»
var
x: Currency;
Диапазон изменения: –922337203685477.5808 . . 922337203685477.5807
Объем памяти: 8 байт.
Тип Variant
var
V1, V2, V3, V4: Variant;
I: Integer; D: Double; S: string;
begin
V1 := 1; // integer value, integer type
V2 := 1234.5678; // real value, real type
V3 := ‘1000’; // string value, string type
V4 := V1 + V2 + V3; // double value 2235.5678, double type
I := V1;
D := V2;
S := V3; // S=’1000’
I := V4; // I = 2236
end;
Delphi: Help, “Variant type conversions”
VB6, VBA-MS/Office: Тип Variant разрешен.
VBScript: Все переменные есть переменные типа Variant.
VB.Net: Тип Variant запрещен.
Тип «дата-время»
Тип TDateTime содержит значение даты и времени. Она сохраняется как переменнаяDouble, с датой как целая часть, а время как дробная. Дата сохраняется как число дней с 30 декабря 1899. Не понятно, почему не 31 декабря. 01 января 1900 имеет значение 2. Поскольку TDateTime фактически является Double, то вы можете выполнять над ним вычисления, как будто это было число. Это очень полезно для вычислений типа разницы между двумя датами.
Пример кода : Обнаружение различия между двумя датами |
var day1, day2 : TDateTime; diff : Double; begin day1 := StrToDate('12/06/2002'); day2 := StrToDate('12/07/2002'); ShowMessage('day1 = '+DateToStr(day1)); ShowMessage('day2 = '+DateToStr(day2)); diff := day2 - day1; ShowMessage('day2 - day1 = '+FloatToStr(diff)+' days'); end; |
day1 = 12/06/2002 day2 = 12/07/2002 day2 - day1 = 30 days |
Билет №20
Пример.
Найти наиболее «дешевый» путь от элемента
матрицы
размера
до элемента
.
Второй способ решения задачи.
Проект ProjectBoth прилагается. В нём реализованы оба подхода к решению задачи.
Идея метода динамического программирования состоит в следующем. Для каждого элемента строится оптимальный путь от него до конца пути. Сначала это делается для всех элементов, которые в одном шаге от конца пути. Затем для всех элементов, которые в двух шагах от конца пути. Затем для всех элементов, которые в трёх шагах от конца пути. И так далее.
Пусть
матрица цен имеет размер
и выглядит так:
Пусть
есть цена оптимального пути от элемента
до конца пути.
Множество предпоследних элементов (1-я волна):
,
двигаться можно только вниз;
,
двигаться можно только вправо.
Множество «предпредпоследних» элементов (2-я волна):
,
двигаться можно только вниз;
,
двигаться лучше вправо;
,
двигаться можно только вправо.
Множество «предпредпредпоследних» элементов (3-я волна):
,
двигаться можно только вниз;
,
двигаться лучше вниз;
,
двигаться лучше вправо;
,
двигаться можно только вправо.
Таким
образом, можно найти цены и начальное
направления оптимального пути для всех
«волн», а значит, и для всех элементов
матрицы, заканчивая элементом
.
Результат поиска показан в виде постановки
при каждом элементе матрицы двух
индексов: цена оптимального пути от
этого элемента до конца (нижний индекс),
направление оптимального пути от этого
элемента (верхний индекс).
const
mMax = 16;
nMax = 16;
type
MyRecord = record
CellPrice: integer;
{$ifdef RecoursiveRejim}
Frequency: integer;
{$endif}
PathPrice: integer;
Dyrection: char;
end;
MyRowType = array of MyRecord; // Строка матрицы
// MyRowType – тип «Указатель на массив элементов типа MyRecord».
MyMatrixType = array of MyRowType; // Вся матрица
// MyMatrixType – тип «Указатель на массив элементов типа MyRowType».
var
// mA: array of MyRowType;
m, n, p: integer;
A: MyMatrixType;
procedure BestPathNonRecoursive(var C: MyMatrixType);
var
i, j, k, ir, id: integer;
begin
C[m][n].PathPrice := 0;
for k := m + n - 1 downto 1 do
for i := m downto 1 do
begin
j := k - i;
if j > n then break;
if j < 1 then continue;
if Right(i, j) then
ir := C[i][j + 1].CellPrice + C[i][j + 1].PathPrice
else
ir := -1;
if Down(i, j) then
id := C[i + 1][j].CellPrice + C[i + 1][j].PathPrice
else
id := -1;
if (ir >= 0) and (id >= 0) then
begin
if ir < id then
begin
C[i][j].Dyrection := 'r';
C[i][j].PathPrice := ir;
end
else
begin
C[i][j].Dyrection := 'd';
C[i][j].PathPrice := id;
end;
end
else
if ir >=0 then
begin
C[i][j].Dyrection := 'r';
C[i][j].PathPrice := ir;
end
else
if id >= 0 then
begin
C[i][j].Dyrection := 'd';
C[i][j].PathPrice := id;
end;
end;
end;
Билет №21
program Project3A;
{$APPTYPE CONSOLE}
uses
SysUtils;
const
mMax = 20;
nMax = 20;
type
MyRecord = record
CellPrice, Frequency: integer;
Direction: char;
end;
MyArray = array[1 .. mMax, 1 .. nMax] of MyRecord;
var
m, n, p, q: integer;
A: MyArray;
procedure InitArray(var C: MyArray);
var
i, j: integer;
begin
Randomize;
m := 3 + Random(mMax – 2);
n := 3 + Random(nMax – 2);
Writeln('m=', m , ' n=', n);
for i := 1 to m do
for j := 1 to n do
begin
C[i][j].CellPrice := Random(mMax + nMax);
C[i][j].Frequency := 0;
C[i][j].Direction := '?';
end;
end;
procedure ShowPrices(var C: MyArray);
var
i, j: integer;
begin
Writeln('ShowPrices');
for i := 1 to m do
begin
for j := 1 to n do
Write(C[i][j].CellPrice : 5);
Writeln;
end;
end;
procedure ShowFrequencies(var C: MyArray);
var
i, j: integer;
begin
Writeln('ShowFrequencies');
for i := 1 to m do
begin
for j := 1 to n do
Write(C[i][j].Frequency : 5);
Writeln;
end;
end;
procedure ShowDirections(var C: MyArray);
var
i, j: integer;
begin
Writeln('ShowDirections');
for i := 1 to m do
begin
for j := 1 to n do
Write(C[i][j].Direction : 3);
Writeln;
end;
end;
function Right(i, j: integer): boolean;
begin
if j < n then Right := true else Right := false;
end;
function Down(i, j: integer): boolean;
begin
if i < m then Down := true else Down := false;
end;
function BestPathRecoursive(i, j: integer; var C: MyArray): integer;
var
id, ir: integer;
begin
Inc(C[i][j].Frequency);
if (i = m) and (j = n) then
BestPathRecoursive := 0
else
begin
if Right(i, j) then
ir := C[i][j + 1].CellPrice + BestPathRecoursive(i, j + 1, C)
else
ir := -1;
if Down(i, j) then
id := C[i + 1][j].CellPrice + BestPathRecoursive(i + 1, j, C)
else
id := -1;
if (ir >= 0) and (id >= 0) then
begin
if ir < id then
begin
C[i][j].Direction := 'r';
BestPathRecoursive := ir;
end
else
begin
C[i][j].Direction := 'd';
BestPathRecoursive := id;
end;
end
else
if ir >=0 then
begin
C[i][j].Direction := 'r';
BestPathRecoursive := ir;
end
else
if id >= 0 then
begin
C[i][j].Direction := 'd';
BestPathRecoursive := id;
end;
// else
// Halt;
end;
end;
procedure ShowPath(var C: MyArray);
var
k, i, j: integer;
begin
i := 1;
j := 1;
p := 0;
for k := 1 to m + n - 2 do
begin
Write(' ', C[i][j].Direction);
if C[i][j].Direction = 'r' then
Inc(j)
else
if C[i][j].Direction = 'd' then
Inc(i);
// else
// Halt;
p := p + C[i][j].CellPrice;
end;
Writeln;
end;
begin
InitArray(A);
ShowPrices(A);
q := BestPathRecoursive(1, 1, A);
Writeln('Price of best path = ', q);
ShowPath(A);
Writeln('Price of best path = ', p);
ShowDirections(A);
ShowFrequencies(A);
Readln;
end.
Билет №22
Стандартные процедуры и функции для работы с любыми файлами
Синтаксис TP7:
procedure Assign(var F: <Файловый тип>; <Имя файла>: string);
Процедура связывает файловую переменную с реальным файлом.
procedure Erase(var F: <Файловый тип>);
Удаляет файл.
procedure Rename(var F: <Файловый тип>; <Новое имя файла>: string);
Переименовывает файл
procedure MKDir(<Имя папки>: string);
Создает пустую папку
procedure RMDir(<Имя папки>: string);
Удаляет пустую папку
function IOResult: integer;
Возвращает код ошибки при работе с файлом.
Синтаксис Delphi:
procedure AssignFile(var F: <Файловый тип>; <Имя файла>: string);
Процедура аналогична процедуре Assign.
Замечание
Существуют альтернативные варианты процедур:
procedure Rename(var F <Файловый тип>; <Новое имя файла>: PChar);
procedure MKDir(<Имя папки>: PChar);
procedure RMDir(<Имя папки>: PChar);
PChar – специальный «строковый» тип, разговор о нѐм пойдѐт позже.
Замечание
Файловых типов в языке Паскаль может быть три: текстовые файлы,
типизированные файлы и файлы без типа.
Тип «Текстовый файл», или файл последовательного доступа, предназначен для
работы с т.н. текстовыми файлами (на дисках и не только). Признаком текстового
файла является множество байтовых пар с кодами 13 и 10. В литературе для них
встречается обозначение CR (Carriage Return, возврат каретки) и LF (Line Feed,
перевод строки). Между парами с кодами 13 и 10 обычно стоят символы
разговорных алфавитов, образующие осмысленный текст. Для служебных целей
текстовые файлы могут содержать, например, числа, представляющие входной
набор данных для программы.
<Объявление текстовой файловой переменной> ::=
<Имя файловой переменной>: text;
Стандартные процедуры для работы с текстовыми файлами
Синтаксис TP7:
procedure Reset(var F: <Файловый тип>);
Процедура открывает файл для чтения (данных из файла).
procedure Rewrite(var F: <Файловый тип>);
Процедура открывает файл для записи (данных в файл).
procedure Append(var F: <Файловый тип>);
Процедура открывает файл для ДОзаписи данных в конец файла.
procedure Close(var F: <Файловый тип>;
Процедура закрывает ранее открытый файл.
procedure Assign(var F: <Файловый тип>; <Имя файла>: string);
Процедура связывает файловую переменную с реальным файлом.
function EOLN(var F: <Файловый тип>) boolean;
Функция возвращает значение true, если маркер файла переместился за последний байт строки (достигнут конец строки).
function SeekEOLN(var F: <Файловый тип>) boolean;
Функция возвращает значение true, если маркер файла переместился за последний байт строки (достигнут конец строки), или если конец строки не достигнут, но до конца строки присутствуют только пробелы и знаки табуляции.
function SeekEOF(var F: <Файловый тип>) boolean;
Функция возвращает значение true, если маркер файла переместился за последний байт файла (достигнут конец файла), или если конец файла не достигнут, но до конца файла присутствуют только пробелы и знаки табуляции.
procedure Flush(var F <Файловый тип>);
Процедура немедленно освобождает буфер записываемого файла. Если процедура не применяется, буфер освобождается только тогда, когда он заполнен, или при закрытии файла.
procedure Read(var F <Файловый тип>; <Список ввода>);
Производится чтение данных из текстового файла в переменные, представленные в <Списке ввода>. Разделителями между данными служат пробелы либо символы подчеркивания. Переход на следующую строку файла происходит только в случае, если текущая строка уже исчерпана.
procedure Readln(var F < Файловый тип>; <Список ввода>);
Производится чтение данных из текстового файла в переменные, представленные в <Списке ввода> аналогично тому, как это делается процедурой Read. Когда список ввода исчерпан, производится перевод маркера на начало следующей строки текстового файла, даже если до конца текущей строки остаются данные, которые не прочтены.
procedure Write(var F <Файловый тип>; <Список вывода>);
Производится запись данных из <Списка вывода> в текстовый файл.
procedure Writeln(var F <Файловый тип>; <Список вывода>);
Производится запись данных из <Списка вывода> в текстовый файл. Когда список вывода исчерпан, производится перевод маркера на начало следующей строки текстового файла.
Синтаксис Delphi:
<Объявление текстовой файловой переменной> ::=
<Имя файловой переменной>: textfile;
procedure AssignFile(var F: <Файловый тип>; <Имя файла>: string);
procedure CloseFile (var F: <Файловый тип>);
Билет №23