- •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
- •Использование сопроцессора
3. Вывод одномерного массива на экран.
Для компактности изображения массива на экране в каждой строке экрана целесообразно печатать несколько элементов массива.
Пусть формат вывода элемента массива имеет вид 8:2. Устанавливая между числами два пробела, в одной строке экрана можно разместить 8 чисел (строка экрана содержит 80 позиций). Тогда программа вывода может иметь вид:
Const Nmax = 500;
Type Ar = array[1..Nmax] of real;
Var k : byte;
i,n : word;
X : Ar;
Begin
.....................
k:=0;
For i:=1 to n do
Begin
k:=k+1;
If k<8 then
Write(x[i]:8:2,' ')
Else
Begin
k:=0; Writeln(x[i]:8:2);
End;
End;
If k>0 then Writeln;
Переменная k - это счетчик количества чисел, выводимых в одну строку экрана. Пока k < 8, работает процедура Write, размещая очередные элементы массива в одной и той же строке экрана. При k = 8 после вывода числа производится переход на следующую строку экрана, при этом счетчику k присваивается нулевое значение.
Предположим, что в массиве X количество элементов не кратно 8. Тогда вывод последнего элемента будет осуществлен процедурой Write, следовательно, не будет произведен переход на новую строку экрана. Если в программе после вывода массива X выполняется еще вывод хотя бы одного числа, то это число будет размещено в той же строке экрана, где расположен элемент , что по крайней мере неэстетично. Для предотвращения такой ситуации в вышеприведенной программе записан оператор "If k > 0 then Writeln".
В дальнейшем для увеличения и уменьшения значения целой переменной будем использовать процедуры Inc и Dec (инкремент и декремент), создающие эффективные машинные коды.
Inc(k) эквивалентно k:=k+1;
Inc(k,m) эквивалентно k:=k+m;
Dec(k) эквивалентно k:=k-1;
Dec(k,m) эквивалентно k:=k-m.
В частности, Inc(k) работает примерно на 30 % быстрее, чем k := k+1.
Примеры обработки одномерных массивов
Пример 1. Вычислить среднее арифметическое значение элементов массива .
Program MiddleAr;
Const Nmax = 500;
Type Ar = array[1..Nmax] of real;
Var i, { параметр цикла }
n : word; { кол-во элементов массива }
S : real; { среднее арифметическое значение }
X : Ar; { исходный массив }
Begin
Ввод и печать n, X
S:=0;
For i:=1 to n do
S:=S+x[i];
S:=S/n;
Печать S
End.
При старте программы выделяется память для всех переменных, описанных в разделе Var, т.е. каждому имени переменной ставится в соответствие адрес конкретного поля памяти. Эти поля памяти, как правило, не обнуляются, они могут быть заполнены случайными последовательностями битов. Поэтому в программе MiddleAr перед накоплением в переменной S суммы элементов массива X производится обнуление этой переменной оператором S := 0 .
Следует обратить внимание еще на одно обстоятельство. Массиву Х в программе выделяется память, необходимая для размещения 500 элементов. В принципе в программе можно было бы написать:
For i:=1 to Nmax do
S:=S+x[i];
S:=S/Nmax;
Однако это означало бы, что программа может обрабатывать лишь массив, содержащий 500 элементов, но не 499 или 100. Поэтому для обеспечения универсальности работы программы обработке подвергается текущее количество элементов n в предположении, что .
Пример 2. Вычислить среднее арифметическое значение положительных элементов массива .
Program MiddlePos;
Const Nmax = 500;
Type Ar = array[1..Nmax] of real;
Var i, { параметр цикла }
k, { кол-во положительных элементов массива }
n : word; { общее кол-во элементов массива }
S : real; { среднее арифметическое значение }
X : Ar; { исходный массив }
Begin
Ввод и печать n, X
S:=0; k:=0;
For i:=1 to n do
If x[i]>0 then
Begin
S:=S+x[i]; Inc(k)
End;
If k>0 then { блокировка деления на нуль }
S:=S/n;
Печать S
End.
В частном случае в массиве X может не быть ни одного положительного элемента (k=0). Тогда при отсутствии оператора «If x[i]>0 then» было бы прерывание программы с сообщением «Zero divide» («Деление на нуль»).
Пример 3. Определить .
Program MaxElem;
Const Nmax = 500;
Type Ar = array[1..Nmax] of integer;
Var i, n : word;
Xmax : integer;
X : Ar;
Begin
Ввод и печать n,X
Xmax:=x[1];
For i:=2 to n do
If x[i]>Xmax then
Xmax:=x[i];
Печать Xmax
End.
Пример 4. Обменять местами максимальный и минимальный элементы массива X.
Здесь требуется найти не только значения переменных Xmax и Xmin, но и положение (индексы) соответствующих им элементов в массиве X (значения переменных imax и imin).
Вариант 1.
Program Exchange;
Const Nmax = 500;
Type Ar = array[1..Nmax] of integer;
Var i,n,imax,imin : word;
Xmax,Xmin : integer;
X : Ar;
Begin
Ввод и печать n,X
Xmax:=x[1]; Xmin:=x[1];
imax:=1; imin:=1;
For i:=2 to n do
Begin
If x[i]>Xmax then
Begin
Xmax:=x[i]; imax:=i
End;
If x[i]<Xmin then
Begin
Xmin:=x[i]; imin:=i
End;
End;
x[imax]:=Xmin; x[imin]:=Xmax;
Печать X
End.
В каждом цикле элемент сравнивается со значениями переменных Xmax и Xmin. В то же время очевидно, что если выполняется условие > Xmax, то проверка отношения < Xmin является излишней. Указанное замечание учтено в варианте 2.
Вариант 2 (фрагмент).
For i:=2 to n do
If x[i]>Xmax then
Begin
Xmax:=x[i]; imax:=i
End
Else
If x[i]<Xmin then
Begin
Xmin:=x[i]; imin:=i
End;
При обмене значений элементов x[imax] и x[imin] использовано то обстоятельство, что после окончания обработки массива известны не только значения индексов imax и imin, но и численные значения переменных Xmax и Xmin. Обмен в данном случае осуществляется по такой схеме:
Примечание. Было бы совершенно неправильно выполнять обмен максимального и минимального элементов массива X операторами
R := Xmax; Xmax := Xmin; Xmin:= R;
(R - переменная типа real), так как здесь обмениваются значения переменных Xmax и Xmin, а не значения элементов массива X с индексами imax и imin.
Пример 5. В массиве X найти значение и положение первого отрицательного элемента.
Решение рассматриваемой задачи выполнено в двух вариантах.
Вариант 1.
Program NegElem;
Const Nmax = 500;
Type Ar = array[1..Nmax] of integer;
Var i,n,ineg : word;
Xneg : integer;
X : Ar;
Begin
Ввод и печать n,X
ineg:=0;
For i:=1 to n do
If x[i]<0 then
Begin
Xneg:=x[i]; ineg:=i;
Break
End;
Writeln('ineg= ',ineg);
If ineg>0 then
Writeln('Xneg= ',Xneg);
End.
В программе последовательно просматриваются элементы массива X и, как только обнаруживается отрицательный элемент, в переменных Xneg, ineg запоминаются значение и индекс этого элемента, после чего с помощью процедуры Break производится принудительный выход за пределы цикла.
Если в массиве X нет ни одного отрицательного элемента, в программе будет отпечатано ineg = 0, в противном случае - конкретные значения ineg, Xneg.
Примечание. Процедура Break эквивалентна оператору Goto Met, где Met – метка после окончания цикла For.
Вариант 2 (фрагмент).
ineg:=0; i:=1;
While (i<=n) and (ineg=0) do
If x[i]<0 then
Begin
Xneg:=x[i]; ineg:=i;
End
Else
Inc(i);
Writeln('ineg= ',ineg);
If ineg>0 then
Writeln('Xneg= ',Xneg:12);
Вариант 1 работает примерно в 2 раза быстрее (отсутствие проверки ineg = 0 в каждом цикле).
Пример 6. В массиве X определить местоположение последнего положительного элемента.
Вариант 1.
Program PosElem;
Const Nmax = 500;
Type Ar = array[1..Nmax] of integer;
Var i,n,ipos : word;
X : Ar;
Begin
Ввод и печать n,X
ipos:=0;
For i:=1 to n do
If x[i]>0 then
ipos:=i;
Writeln('ipos= ',ipos);
End.
В программе просматриваются все элементы массива X, что нерационально с точки зрения затрат машинного времени. Более эффективной является программа варианта 2, в которой просмотр массива X осуществляется справа налево до обнаружения ближайшего положительного элемента.
Вариант 2 (фрагмент).
ipos:=0;
For i:=n downto 1 do
If x[i]>0 then
Begin
ipos:=i; Break
End;
Writeln('ipos= ',ipos);
Пример 7. Вычисление значения полинома.
Полином (многочлен)
целесообразно всегда вычислять по схеме Горнера:
.
Схема Горнера обладает следующими преимуществами по сравнению с обычной записью полинома:
- меньшее количество операций умножения;
- меньшая погрешность вычислений;
- удобство реализации вычислений в виде цикла.
Для вычисления полинома по обычной схеме требуется операций умножения, по схеме Горнера - таких операций.
Вещественные числа, являющиеся в реальных задачах результатами измерения каких-либо величин, всегда обладают определенной погрешностью. Следовательно, результат обработки таких чисел также содержит в себе некоторую погрешность.
В теории ошибок доказывается, что погрешность произведения равна сумме погрешностей сомножителей. Поэтому схема Горнера, требующая вдвое меньше операций умножения по сравнению с обычной схемой, обеспечивает более высокую точность вычислений.
Вычисление значения полинома по схеме Горнера легко организовать в цикле, если представить коэффициенты полинома как массив.
Вычисления в программе организуются по следующей методике:
P := a[n]
P := P * x + a[n-1]
P := P * x + a[n-2]
...................
P := P * x + a[1]
P := P * x + a[0]
Program Gorner;
Const Nmax = 400;
Type Koef = array[0..Nmax] of real;
Var i,n : integer;
P,x : real;
A : Koef;
Begin
Ввод и печать n,A,x
P := a[n];
For i:=n-1 downto 0 do
P:=P*x+a[i];
Печать P
End.
Конкретную запись полинома, заданного в виде явного выражения, также рекомендуется вычислять по схеме Горнера. Например, полином
по схеме Горнера имеет вид:
.
Пример 8. Расположить элементы массива в обратном порядке.
При выполнении заданного преобразования нужно произвести обмен значений элементов и , и , и и так далее до достижения "середины" массива .
Вариант 1.
Program BackOrder;
Const Nmax = 500;
Type Ar = array[1..Nmax] of real;
Var i,n : integer;
R : real;
X : Ar;
Begin
Ввод и печать n, X
For i:=1 to n div 2 do
Begin
R:=x[i]; x[i]:=x[n-i+1]; x[n-i+1]:=R
End;
Печать массива X
End.
Вариант 2 (фрагмент).
i:=1; j:=n;
While i<j do
Begin
R:=x[i]; x[i]:=x[j]; x[j]:=R;
Inc(i); Dec(j);
End;
Оба варианта примера 8 равнозначны с точки зрения эффективности вычислений, но вариант 2 более нагляден. Второй вариант более удобен также в случае, когда требуется выполнить перестановку не всего массива, а подмассива, например, с номера n1 до номера n2. Тогда перед циклом записываются операторы i:=n1 и j:=n2, остальная часть программы не изменяется.
Вариант 3. Использование буферного массива.
Program BackOrder3;
Const Nmax = 500;
Type Ar = array[1..Nmax] of real;
Var i,n : integer;
X,Y : Ar;
Begin
Ввод и печать n, X
For i:=1 to n do
y[n-i+1]:=x[i];
X:=Y;
Печать массива X
End.
Оператор X:=Y в варианте 3 допустим, поскольку массивы X иY описаны одним и тем же именем типа. При этом производится пересылка всего поля Y в поле X, т.е. Nmax элементов в соответствии с объявлением типа данного массива.
Недостаток варианта 3 вполне очевиден – это использование буферного массива.
О Г Р А Н И Ч Е Н И Я В И С П О Л Ь З О В А Н И И
О П Е Р А Т О Р А F O R
Ограничения в использовании оператора цикла с параметром естественным образом вытекают из приведенного ранее описания этого оператора. Рассмотрим еще раз по пунктам описание оператора For и вытекающие из этого следствия.