- •1. Двоичная система счисления.
- •2. Восьмеричная система счисления.
- •3. Шестнадцатеричная система счисления.
- •4. Сложение и вычитание в 2, 8 и 16 c/c.
- •2. Вещественные числа (числа с плавающей запятой).
- •3. Логические данные.
- •2. Зарезервированные слова.
- •X a8 alpha Massiv z52d9 eps Res_52_a ___75
- •6. Метка.
- •2. Целые типы данных.
- •4. Вещественные типы.
- •1. Раздел описания меток.
- •2. Раздел описания констант.
- •3. Раздел описания типов.
- •4. Раздел описания переменных.
- •6. Раздел операторов.
- •7. Последовательность разделов.
- •1. Формульно-словесный способ.
- •2. Блок-схемный способ.
- •Ввод - вывод одномерного массива
- •2. Ввод массива из текстового файла.
- •3. Вывод одномерного массива на экран.
- •Примеры обработки одномерных массивов
- •1. Параметр цикла должен быть ординального типа.
- •2. Параметр должен быть описан в том же блоке, где находится сам оператор цикла.
- •5. В теле цикла параметр не должен изменяться.
- •6. Начальное и конечное значения параметра цикла вычисляются только один раз, до начала цикла.
- •7. При нормальном завершении цикла значение его параметра считается неопределенным.
- •Контроль ординальных переменных
- •Вставка элемента в упорядоченный массив
- •Удаление элементов из массива
- •«Школьный» алгоритм сортировки
- •Группировка массива методом прямой выборки
- •Группировка массива методом прямого обмена
- •Var c : array[1..10,1..15,1..8] of real.
- •1. Ввод элементов матрицы с клавиатуры.
- •2. Ввод матрицы из текстового файла.
- •3. Вывод матрицы на экран.
- •Тождественные и совместимые типы
- •Обработка в процедуре одномерных массивов с различными именами типов
- •Обработка в процедуре матриц с различными именами типов
- •Var s : string[V],
- •Процедуры и функции для обработки строк
- •Определение битовой структуры поля памяти
- •Процедуры и функции для файлов любого типа
- •Var p : pointer;
- •1. Формирование стека из текстового файла.
- •7. Определение значения и местоположения максимального элемента в стеке.
- •8. Удаление из стека максимального элемента.
- •9. Добавление элемента в упорядоченный стек.
- •2. Добавление нового элемента в очередь.
- •3. Удаление элемента из очереди.
- •6. Удаление произвольного элемента из очереди.
- •7. Добавление нового элемента в произвольное место очереди.
- •1. Формирование дека.
- •Var sin : integer;
- •Процедура заполнения FillChar
- •Процедура перемещения данных move
- •Управление экраном в текстовом режиме
- •Сохранение и восстановление экрана
- •Interface
- •Implementation
- •Процедуры управления текстовым режимом экрана
- •Intr(n:byte; Var Reg:Registers),
- •If KeyPressed then
- •Автоматическая оптимизация программ
- •1. Свертывание констант.
- •2. Слияние констант.
- •3. Вычисление по короткой схеме.
- •4. Удаление неиспользуемого кода.
- •If false then
- •5. Эффективная компоновка.
- •Оверлейная структура программы
- •Interface
- •Implementation
- •Interface
- •Implementation
- •Использование сопроцессора
Обработка в процедуре матриц с различными именами типов
Обработка матриц различного размера (с разными именами типов) организуется в процедуре с помощью аппарата приведения типов или с помощью абсолютных переменных в основном аналогично тому, как это выполняется для одномерных массивов. Разница в их обработке связана с тем, что внутреннее представление одномерного массива и матрицы неодинаково.
Элементы одномерного массива расположены в памяти последовательно.
Пример 1.
Type RealAr = array[1..1000] of real;
Xar = array[1..500] of real;
Var X : Xar;
Y : RealAr;
c,d : real;
Begin ................
c:=X[100];
d:=RealAr(X)[100];
При старте программы выделяется память для переменных X, Y, c и d, соответственно 3000, 6000, 6 и 6 байтов. Поле X имеет следующую структуру:
X+0 X+6 X+12 X+18 . . . X+2988 X+2994
|
|
|
|
|
|
|
|
|
|
. . .
На этой схеме снизу указаны элементы массива X, сверху - их адреса. Каждый элемент занимает 6 байтов памяти. В частности, элемент имеет адрес X+(100-1) 6 = X+594.
Поле Y имеет аналогичную структуру, последний элемент расположен по адресу Y+5994.
Запись RealAr(X) означает, что в данном случае поле X интерпретируется как переменная, имеющая тип RealAr. Поскольку описание RealAr определяет одномерный массив с элементами типа real, то элемент RealAr(X)[100] имеет тот же адрес, что и элемент . Следовательно, переменные c и d в приведенном выше примере получают одинаковые значения.
Элементы матрицы расположены в памяти по строкам.
Пример 2.
Type Rem = array[1..100,1..100] of real;
MatrixA = array[1..20,1..30] of real;
Var A : MatrixA; B : Rem;
c,d : real;
Begin ...............
c:=A[10,10];
d:=Rem(A)[10,10];
Переменные A и Rem(A) - это одно и то же поле памяти. Элементы матрицы A расположены в памяти согласно трафарета, определенного именем типа MatrixA, т.е.
a[1,1], a[1,2], ... , a[1,29], a[1,30],
a[2,1], a[2,2], ... , a[2,29], a[2,30],
..................................................
a[20,1], a[20,2], ... , a[20,29], a[20,30]
Следовательно, элемент имеет порядковый номер 9 30 + 10 = 280, его адрес равен A + (280-1)6 = A + 1674.
Расположение в памяти элементов матрицы Rem(A) определено именем типа Rem:
Rem(A)[1,1], Rem(A)[1,2], ..., Rem(A)[1,99], Rem(A)[1,100],
Rem(A)[2,1], Rem(A)[2,2], ..., Rem(A)[2,99], Rem(A)[2,100],
..............................................................
Rem(A)[100,1],Rem(A)[100,2],...,Rem(A)[100,99],Rem(A)[100,100]
Элемент Rem(A)[10,10] имеет порядковый номер 9 100 + 10 = 910, его адрес равен
A + (910-1)*6 = A + 5454.
Следовательно, переменным c и d в примере 2 будут присвоены различные значения.
Совпадение значений a[i,j] и Rem(A)[i,j] будет иметь место лишь в том случае, когда пределы изменения индексов фактической и наложенной матриц одни и те же. Естественно, при этих условиях процедура не сможет правильно обрабатывать матрицы разного размера.
Чтобы обеспечить в процедуре обработку матриц разного размера, в теле процедуры на фактическую матрицу накладывается фиктивный одномерный массив. Тогда при переходе от фактического к фиктивному (наложенному) массиву по индексам i, j матрицы вычисляется порядковый номер k одномерного массива, а при обратном переходе - по значению k вычисляются индексы i, j.
Пусть фактическая матрица A имеет объявление типа
Matrix = array[1..Mmax,1..Nmax] of real.
Тогда порядковый номер элемента a[i,j]: k = (i - 1) Nmax + j .
Наоборот, элемент с порядковым номером k имеет индексы
i = (k - 1) div Nmax + 1; j = k - (i - 1) Nmax.
Пример 3. Разработать процедуру, определяющую значение и местоположение максимального элемента для матриц разного размера.
Program MaxElem;
Const MmaxA = 30; NmaxA = 30;
MmaxB = 20; NmaxB = 40;
Type MatrixA = array[1..MmaxA,1..NmaxA] of real;
MatrixB = array[1..MmaxB,1..NmaxB] of real;
RealAr = array[1..(2*MaxInt) div SizeOf(real)] of real;
Var i,j, { параметры цикла }
ma,na,mb,nb, { размеры матриц A и B}
imaxA,jmaxA, { индексы макс.элемента }
imaxB,jmaxB : byte; { для матриц A и B }
Amax,Bmax : real; { значение макс.элемента }
A : MatrixA; B : MatrixB;
FileA,FileB : text;
{ ----------------------------------------------- }
Procedure ReadMatrix(Var F:text; Var C; Nmax:byte; Var m,n:byte);
{ Чтение матрицы из файла }
Var i,j : byte;
k : word;
R : real;
Begin
Reset(F);
Read(F,m,n);
For i:=1 to m do
For j:=1 to n do
Begin
Read(FileX,R);
k:=(i-1)*Nmax+j; RealAr(C)[k]:=R;
End;
Close(F);
End { ReadMatrix };
{ ----------------------------------------------- }
Procedure MaxMatrix(Var C; Nmax,m,n:byte; Var Cmax:real;
Var imax,jmax:byte);
{ Определение значения и местоположения макс.эл-та матрицы }
Var i,j : byte;
k : word;
Begin
Cmax:=RealAr(C)[1]; imax:=1; jmax:=1;
For i:=1 to m do
For j:=1 to n do
Begin
k:=(i-1)*Nmax+j;
If RealAr(C)[k]>Cmax then
Begin
Cmax:=RealAr(C)[k]; imax:=i; jmax:=j;
End;
End;
End { MaxMatrix };
{ ----------------------------------------------- }
Begin
Assign(FileA,'MatrixA.dat');
ReadMatrix(FileA,A,NmaxA,ma,na):
MaxMatrix(A,NmaxA,ma,na,Amax,imaxA,jmaxA);
Writeln('Amax= ',Amax:8:2,' imaxA= ',imaxA,
' jmaxA= ',jmaxA);
Assign(FileB,'MatrixB.dat');
ReadMatrix(FileB,B,NmaxB,mb,nb);
MaxMatrix(B,NmaxB,mb,nb,Bmax,imaxB,jmaxB);
Writeln('Bmax= ',Bmax:8:2,' imaxB= ',imaxB,
' jmaxB= ',jmaxB);
End.
В примере 3 для обработки матриц с разными именами типов применялся аппарат приведения типов. В следующем примере с этой же целью используются абсолютные переменные.
Пример 4. Разработать процедуру, определяющую значение и местоположение максимального элемента среди элементов, расположенных ниже главной диагонали квадратной матрицы.
Program MaxMatrix;
Const NmaxA = 30; NmaxB = 40;
Type MatrixA = array[1..NmaxA,1..NmaxA] of real;
MatrixB = array[1..NmaxB,1..NmaxB] of real;
RealAr = array[1..(2*MaxInt) div SizeOf(real)] of real;
Var i,j, { параметры цикла }
na,nb, { размеры матриц A и B }
imaxA, { индексы макс.элемента }
jmaxA, { для матрицы А }
imaxB, { индексы макс.элемента }
jmaxB : byte; { для матрицы B }
Amax,Bmax : real; { значение макс.элемента }
A : MatrixA; B : MatrixB;
FileA,FileB : text;
{ ----------------------------------------------- }
Procedure ReadMatrix(Var F:text; Var C; Nmax:byte;
Var n:byte);
{ Чтение матрицы из файла }
Var i,j : byte;
k : word;
R : real;
D : RealAr absolute C;
Begin
Reset(F); Read(F,n);
For i:=1 to n do
For j:=1 to n do
Begin
Read(F,R);
k:=(i-1)*Nmax+j; d[k]:=R;
End;
Close(F);
End { ReadMatrix };
{ ----------------------------------------------- }
Procedure MaxElem(Var C; Nmax, n:byte; Var max:real;
Var imax,jmax:byte);
{ Определение значения и местоположения максимального }
{ элемента матрицы ниже главной диагонали }
Var i,j : byte;
D : RealAr absolute C;
Begin
max:=d[Nmax+1]; imax:=2; jmax:=1; { первый элемент }
For i:=3 to n do { второй строки }
For j:=1 to i-1 do
Begin
k:=(i-1)*Nmax+j;
If d[k]>max then
Begin
max:=d[k]; imax:=i; jmax:=j;
End;
End;
End { MaxElem };
{ ----------------------------------------------- }
Begin
Assign(FileA,'MatrixA.dat');
ReadMatrix(FileA,A,NmaxA,na):
MaxMatrix(A,NmaxA,na,Amax,imaxA,jmaxA);
Writeln('Amax= ',Amax:8:2,' imaxA= ',imaxA,
' jmaxA= ',jmaxA);
Assign(FileB, 'MatrixB.dat');
ReadMatrix(FileB,B,NmaxB,nb):
MaxMatrix(B,NmaxB,nb,Bmax,imaxB,jmaxB);
Writeln('Bmax= ',Bmax:8:2,' imaxB= ',imaxB,
' jmaxB= ',jmaxB);
End.
О П Е Р А Т О Р В А Р И А Н Т А (О П Е Р А Т О Р В Ы Б О Р А)
Условный оператор выбирает одну из двух альтернатив. Если альтернатив более двух, удобно использовать оператор варианта (оператор Case).
Примечание. Слово «case» по-английски означает «случай».
Синтаксис оператора Case:
Выражение, входящее в состав оператора варианта, называют селектором. Оператор варианта состоит из селектора и списка операторов, с каждым из которых сопоставляется одна или несколько констант, относящихся к типу селектора. Тип селектора должен быть ординальным.
Оператор варианта выбирает для выполнения оператор, сопоставленный с текущим значением селектора. Если такая константа не обнаружена, выполняется ветвь Else, при отсутствии которой оператор варианта эквивалентен пустому оператору.
В списке констант допускается использование диапазонов.
Пример 1.
Var k : 1..10;
Begin
..........
Case k of
1 : y:=x+1;
2 : y:=sin(x);
3..5 : y:=sqrt(x);
6 : y:=exp(x);
7 : y:=sqr(x);
end;
Следует особо отметить, что в операторе варианта перед двоеточием стоит не метка, а константа ординального типа.
Пример 2.
Var ch : char;
Begin
Case ch of
'a' : Writeln('Первая ветвь');
'b','c','d' : Writeln('Вторая ветвь');
'p'..'t' : Writeln('Третья ветвь')
Else
Writeln('Альтернативная ветвь');
end;
Примечание. В соответствии с синтаксической диаграммой перед словом else в операторе Case, в отличие от условного оператора, может стоять точка с запятой. Следовательно, в предыдущем примере оператор Case можно записать в виде
Case ch of
'a' : Writeln('Первая ветвь');
'b','c','d' : Writeln('Вторая ветвь');
'p'..'t' : Writeln('Третья ветвь');
Else
Writeln('Альтернативная ветвь');
end;
М А С С И В Ы С И М В О Л О В
Строки, состоящие из одного символа, считаются константами типа char. Например, 'a', 'A', '1', '=' .
Строки, состоящие из n символов, считаются константами типа
array[1..n] of char.
По отношению к символьным массивам действуют в основном те же правила, что и по отношению к числовым массивам. В частности, присваивание A := B допустимо лишь в том случае, когда типы массивов A и B тождественны.
Пример 1.
Type Ar1 = array[1..10] of char;
Ar2 = array[1..10] of char;
Ar3 = Ar1;
Var A : Ar1; B : Ar2; C : Ar3;
Begin
......................
B:=A; C:=A;
Здесь оператор C:=A будет считаться корректным, а для оператора B:=A компилятор выдаст сообщение «Type mismatch», поскольку типы Ar1 и Ar2 не являются тождественными.
Тем не менее имеются и отличия в обработке символьных и числовых массивов.
В частности, символьному массиву можно присвоить значение строки символов, если количество символов в строке и объявленный размер символьного массива одинаковы. Например, для предыдущего примера правильным будет воспринят оператор A:=’0123456789’, а для операторов B:=’01234567’ и C:=’0123456789012’ будет выдано сообщение «Type mismatch».
Для символьных массивов допустимы также операции отношения. Такие операции выполняются слева направо до тех пор, пока не встретятся два неодинаковых символа. Если длины массивов различные, то более короткий дополняется символом #0.
Пример 2.
Var p : boolean;
A,B,C : array[1..8] of char;
Begin
A:='ABCDEFGH'; B:='ABCDXYZV'; C:=B;
p:=A<C;
В данном случае получим p = true.
Пример 3. Слова в тексте разделены одним или несколькими пробелами. Определить, сколько слов оканчиваются буквой 'а'.
Program Letter;
Const Nmax = 60;
Var i,k,n : integer;
Tex : array[1..Nmax] of char;
Begin
Read(n);
For i:=1 to n do { Ввод текста }
Read(Tex[i]); { по одному символу }
For i:=1 to n do { Вывод текста }
Write(Tex[i]); { по одному символу }
Writeln;
k:=0;
For i:=1 to n-1 do { если после буквы }
If (Tex[i]='a') and { следует пробел, то }
(Tex[i+1]=' ') then { это означает, что }
Inc(k); { данная буква является }
If Tex[n]='a' then { последней в слове }
Inc(k);
Writeln('k= ',k);
End.
Поскольку текст - это массив символов, то ввод и вывод такого текста осуществляется поэлементно, по одному символу.
Пример 4. Даны два слова одинаковой длины. Определить, состоят ли эти слова из одних и тех же букв. Например, 'СОСНА' = 'НАСОС', но 'СОСНА' 'НАНОС', так как в слове 'СОСНА' две буквы 'С', а в слове 'НАНОС' - только одна такая буква.
Обозначим заданные слова именами Slovo1 и Slovo2. Будем выбирать по одной букве из Slovo2 и последовательно сравнивать выбранную букву со всеми буквами в Slovo1. Если i-ая буква в Slovo2 равна j-ой букве в Slovo1, то j-ую букву первого слова заменяем на пробел (чтобы эта буква больше не анализировалась при наличии в Slovo2 повторяющихся букв). Если равенство Slovo1[j] = Slovo2[i] не обнаружено, дальнейшая проверка должна быть прекращена.
Обычно в программах не рекомендуется искажать исходные данные (в данном случае в процессе работы программы стираются буквы в Slovo1). Поэтому сравнение Slovo2 будет производиться с буферным (рабочим) словом SlovoBuf, в которое на стартовом участке программы копируется значение Slovo1.
Program Slovo;
Const n = 20;
Var i,j : byte;
Cond : boolean;
Slovo1,Slovo2,SlovoBuf : array[1..n] of char;
Begin
Ввод и печать Slovo1,Slovo2
SlovoBuf:=Slovo1;
For i:=1 to n do
Begin
Cond:=false;
For j:=1 to n do
If Slovo2[i]=SlovoBuf[j] then
Begin
SlovoBuf[j]:=' '; Cond:=true;
Break;
End;
If not Cond then
Break;
End;
If Cond then
Writeln('Слова имеют одинаковые буквы')
Else
Writeln('Слова имеют различные буквы');
End.
Здесь следует обратить внимание на то, что каждый оператор Break осуществляет выход лишь за пределы того цикла, в котором он сам находится.
С Т Р О К И
Обработка текста в виде массива символов сопряжена с рядом недостатков.
1. Символьный массив обрабатывается в цикле по одному элементу, вследствие чего программа становится громоздкой.
2. Cимвольному массиву можно присвоить значение строки символов лишь в том случае, когда длина строки и объявленный размер массива одинаковы.
Чтобы исключить указанные недостатки, в Турбо Паскале введен тип данных string. Переменная типа string в отличие от массива символов может принимать значения переменной длины. При объявлении такой переменной указывается ее максимальная длина.
Объявление строки имеет вид: