2011_Add_labs_ - Программирование на turbo pascal

advertisement
Контрольная работа №1: оператор if
Задание.
Разработать программу, определяющую попадание точки с координатами (X,Y) в
заштрихованную область рисунка. Результат поместить в булеву переменную.
Использовать рис. 4 из [2, с. 12].
Номер варианта рисунка для контрольной работы равен ((номер студента по списку в
журнале преподавателя) + 14 + (номер подхода к контрольной работе)) mod 30 +1.
Требования к организации системы программирования и программе:
- программу создавать в новом пустом каталоге с именем Kontr<# работы>,
- автосохранение файлов включить,
- контроль ошибок времени выполнении включить,
- компиляция на диск,
- структурированность текста и программы,
- осмысленные имена ,
- дружественный интерфейс.
Эти требования действуют во всех контрольных работах!
Работа 3.
Преобразование строки в число и обратно [8,9]
Задание.
Разработать программу, выполняющую:
- ввод строки, изображающей число в позиционной системе счисления со знаком или
без знака,
- преобразование этой строки в десятичное число целого или вещественного типа,
- вывод этого числа,
- преобразование десятичного числа в строковое представление,
- вывод этой строки.
Ограничения
Для ввода и вывода строк можно использовать тип строка или вводить и выводить
строки по символам. Для преобразования чисел из одной системы счисления в другую
можно использовать любой алгоритм (кроме табличного), но проще применить методы
«цифра за цифрой». Использовать библиотечные функции преобразования запрещено.
Отчет.
Индивидуальное задание.
Пример преобразования строки в число и наоборот.
Описание двух алгоритмов: 1)преобразования строки в число и 2) наоборот.
Граф-схемы этих двух алгоритмов.
Тексты программ со ссылками на номера элементов граф-схем.
Результаты прогона тестов (6 штук, включая крайние случаи).
Варианты
Вариант задания определяется по ассоциативной табл.1, где полужирным стилем
(содержимое клетки) приведен номер студента по списку, а заголовки столбцов и строк
определяют
1) тип входного числа, изображенного строкой – целый (напр., 17) или вещественный
(напр., 0,F),
2) систему счисления (двоичная и т.д.),
3) наличие символа знака у входной строки.
Например, если номер студента по списку 8 (пятая клетка в нижней строке табл. 1), то
его индивидуальное задание:
преобразовать строку, изображающую целое шестнадцатеричное число со знаком в
вещественное число и обратно, напр.: ‘-A1’  -17  ‘-A1’.
А если номер студент по списку = 9 (шестая клетка в предпоследней строке), то он
должен обработать строку, изображающую вещественное двоичное число без знака,
модуль которого меньше единицы, напр.: ‘0,011’  0.375  ‘0,011’.
Таблица 1
Система
счисления
Без знака
Со знаком
2
Варианты индивидуальных заданий
Тип данных
Целый
Вещественный
8
10
16
2
8
10
16
1
12
7
2
11
6
15
13
3
8
9
2
5
10
16
14
Контрольная работа №2: строка <--> число
Задание.
Разработать программу преобразования десятичного числа в строку, а затем
преобразования этой строки в число.
Номер варианта определяется по табл. 2..
Таблица 2
Система
счисления
Без знака
Со знаком
2
Варианты заданий контрольной работы
Тип данных
Целый
Вещественный
8
10
16
2
8
10
1
12
7
2
15
13
3
8
9
2
5
10
Контрольная работа №3: массивы
Элементы лексического анализа [8,6]
Контрольная работа №4: текстовые файлы
Рекурсии: определитель матрицы [8,6]
Графическое решение системы уравнений [8,6]
4. РАЗРАБОТКА МНОГОМОДУЛЬНОЙ ПРОГРАММЫ
Разработать программу, вычисляющую обратную матрицу по исходной с максимальной размерностью 10.
Программа должна иметь следующую структуру.
1. Ввод требуемой размерности.
16
14
16
11
6
2. Выбор пользователем варианта заполнения исходной матрицы:
1) ввод матрицы с клавиатуры с автоматической нумерацией
столбцов и строк;
2) заполнение матрицы с помощью генератора случайных чисел
по строкам сверху вниз, по элементам слева направо;
3) заполнение матрицы натуральным рядом чисел по строкам
сверху вниз, по элементам слева направо;
3. Вывод введенной или сгенерированной матрицы с нумерацией
строк и столбцов.
4. Получение обратной матрицы по алгоритму [9. С. 121].
5. Вывод обратной матрицы с нумерацией строк и столбцов.
6. Получение произведений прямой и обратной, обратной и прямой матриц.
7. Вывод произведений матриц с нумерацией строк и столбцов.
Требования по организации программы.
Действия 4 и 6 должны быть организованы как внутренние процедуры, действия 2 и 3 - как внешние. Генератор случайных чисел
требуется организовать по алгоритму [17. С. 25] в виде внешней
функции, используемой в процедуре 2. К начальному значению Х
необходимо прибавить дробную часть текущего времени (функция
TIME), чтобы псевдослучайные числа были более "случайными". Обмен данными между процедурами и главной программой должен быть
осуществлен только через заголовки процедур и функций. Максимальный размер матрицы должен задаваться в разделе констант.
- 60 -
Этап 1. Цель и средства. Цель - учебная, средства - языки
ГСА, Паскаль, операционная среда - ОС РВ СМ ЭВМ.
Этапы 2 и 3. В соответствии с требованиями по организации
программа должна иметь структуру, приведенную на рис.4.1.
-----------¬
¦ПСЕВДОСЛ ¦ - Внешняя функция получения псевдослучайных чисел
LT---------^
-+---------¬
¦ЗАПОЛНЕНИЕ¦ - Заполнение матрицы одним из трех способов по
LT---------- выбору пользователя (ввод с клавиатуры, запол^
нение случайными числами или натуральным рядом)
¦ --------¬
¦ ¦ ВЫВОД ¦ - Вывод матрицы с нумерацией строк и столбцов
¦ LT------¦ ^
-+--+--------¬
¦ ОБРАТ_МАТР ¦- Главная программа вычисления обратной матрицы
¦-----------¬¦
¦¦ОБРАТНАЯ ¦¦- Получение обратной матрицы
¦L-----------¦
¦-----------¬¦
¦¦УМНОЖ ¦¦- Вычисление произведений двух матриц
¦L-----------¦
¦
¦
L------------Рис.4.1. Структура многомодульной программы
Следуя идеологии модульного программирования, процедуру ЗАПОЛНЕНИЕ разобъем на три подпрограммы (рис. 4.2).
Этап 4. Разработка структур данных.
1. Так как для получения обратной матрицы задан алгоритм Гаусса, в котором требуется переставлять строки, примем, что матрица есть массив строк:
type
СТРОКА = array [1..10] of real;
- 61 -
--------------¬
¦ЗАПОЛНЕНИЕ ¦ - Процедура ЗАПОЛНЕНИЕ
¦------------¬¦
¦¦ВВОДМАТРИЦЫ¦¦ - Ввод матрицы с клавиатуры с автоматической
¦L------------¦ нумерацией строк и столбцов
¦------------¬¦
¦¦НАРУР_РЯД ¦¦ - Заполнение матрицы натуральным рядом
¦L------------¦
¦------------¬¦
¦¦SLUCH_РЯД ¦¦ - Заполнение матрицы псевдослучайными числами
¦L------------¦ с помощью функции ПСЕВДОСЛ
¦
¦
L-------------Рис. 4.2. Структура процедуры ЗАПОЛНЕНИЕ
ТИПМАТРИЦА = array [1..10] of СТРОКА;
var
МАТРИЦА: ТИПМАТРИЦА;
2. Так как по заданию требуется вводить матрицу, получать
обратную и находить произведение прямой на обратную и наоборот,
нам потребуется три матрицы:
var
МАТРИЦА,
(* введенная матрица
*)
ОБРАТМАТР,
(* обратная матрица
*)
ПРОИЗВ: ТИПМАТРИЦА; (* произведение двух матриц *)
3. Так как обратная матрица может не существовать, определим переменную СВОЙСТВО:
type
ТИПСВОЙСТВО = (ВЫРОЖДЕН,НЕВЫРОЖДЕН);
var
СВОЙСТВО: ТИПСВОЙСТВО;
4. Так как размер матрицы произволен в пределах 1..1О, введем
переменную
var РАЗМЕР: integer; ,
которую передадим в те процедуры, которые обрабатывают матрицу.
- 62 -
Этап 5. Задача разбивается на ряд элементарных подзадач, поэтому алгоритм в виде ГСА изображать не будем.
Этап 6. С учетом этих рассуждений организуем главную программу как последовательность обращений к процедурам в порядке,
определенном задачей (рис. 4.1). Дополнительно введем сообщения, идентифицирующие смысл вводимой матрицы. Параметры процедур определим в соответствии с назначением процедур.
Program ОБРАТ_МАТР (input,output);
const
MaxРАЗМЕР = 10;
type
ТИПСТРОКА = array [1..MaxРАЗМЕР] of real;
ТИПМАТРИЦА = array [1..MaxРАЗМЕР] of ТИПСТРОКА;
ТИПСВОЙСТВО = (ВЫРОЖДЕН,НЕВЫРОЖДЕН);
var
РАЗМЕР : integer;
МАТРИЦА,ОБРАТМАТР,ПРОИЗВЕД : ТИПМАТРИЦА:
СВОЙСТВО: ТИПСВОЙСТВО;
procedure ЗАПОЛНЕНИЕ (РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА); external;
procedure ВЫВОД (РАЗМЕР: integer;
МАТРИЦА: ТИПМАТРИЦА); external;
procedure УМНОЖ (РАЗМЕР: integer; A, B: ТИПМАТРИЦА;
var AB: ТИПМАТРИЦА);
begin
(* Умножаем A на B, результат в AB *)
end; (* УМНОЖ *)
procedure ОБРАТНАЯ (РАЗМЕР: integer; МАТРВХ: ТИПМАТРИЦА;
var X: ТИПМАТРИЦА;
var СВОЙСТВО: ТИПСВОЙСТВО);
begin
(* Получение обратной матрицы X по входной МАТРВХ *)
end; (* ОБРАТНАЯ *)
begin (* Main *)
writeln (' Преобразование матрицы в обратную ');
- 63 -
writeln (' Размер матрицы? (от 1 до 10): ');
readln(РАЗМЕР);
if РАЗМЕР < 2 then РАЗМЕР := 2;
if РАЗМЕР > 10 then РАЗМЕР := 10;
ЗАПОЛНЕНИЕ(РАЗМЕР, МАТРИЦА);
writeln(' Исходная матрица: ');
ВЫВОД(РАЗМЕР, МАТРИЦА);
write(' Для продолжения нажмите [Enter] '); readln;
ОБРАТНАЯ(РАЗМЕР, МАТРИЦА, ОБРАТМАТР, СВОЙСТВО);
if СВОЙСТВО = НЕВЫРОЖДЕН
then begin
writeln(' Обратная матрица: ');
ВЫВОД(РАЗМЕР, ОБРАТМАТР);
write(' Для продолжения нажмите [Enter] '); readln;
writeln(' Произведение прямой на обратную: ');
УМНОЖ(РАЗМЕР, МАТРИЦА, ОБРАТМАТР, ПРОИЗВЕД);
ВЫВОД(РАЗМЕР, ПРОИЗВЕД);
write(' Для продолжения нажмите [Enter] '); readln;
writeln(' Произведение обратной на прямую: ');
УМНОЖ(РАЗМЕР, ОБРАТМАТР, МАТРИЦА, ПРОИЗВЕД);
ВЫВОД(РАЗМЕР, ПРОИЗВЕД);
end
else writeln(' Матрица вырожденная ');
end.
В данном тексте внутренние процедуры записаны в виде пустых
процедур, имеющих только заголовок. Заметим, однако, что этот
текст можно компилировать (в среде ОС РВ), чтобы проверить синтаксис главной программы.
После определения входных и выходных параметров будем последовательно разрабатывать тексты процедур, т.е. спустимся вниз
на шаг и станем детализировать процедуры (принцип проектирования сверху вниз).
4.1. Процедура УМНОЖ
Каждый элемент произведения матриц равен сумме произведений
элементов соответствующей строки первого сомножителя на элементы столбца второго сомножителя (рис. 4.3).
- 64 -
Размер
AB[i,j] = A[i,k] * B[k,j]
k
j
j--->
-------------¬ --------T-T--¬ --------------¬
¦ k ---> ¦ ¦
¦ ¦k ¦ ¦
¦
+--------T-T-+ ¦
¦ ¦¦ ¦ i¦
--¬ ¦
i +--------+-+-+ ¦
+-+¦ ¦ ¦¦
L-- ¦
¦ A[i,k] ¦ ¦ B[k,j]+-+V ¦ V¦ AB[i,j] ¦
¦
¦ L-------+-+--- ¦
¦
L------------L-------------A
B
AB = A * B
Рис.4.3. Нахождение элемента произведения матриц
Получим:
procedure УМНОЖ (РАЗМЕР: integer; A, B: ТИПМАТРИЦА;
var AB: ТИПМАТРИЦА);
var
i, (* номер строки матрицы AB *)
j, (* номер элемента строки матрицы AB *)
k: (* номер перемножаемых элементов в строке *)
(* i матрицы A и столбце j матрицы B] *)
integer;
begin
for i := 1 to РАЗМЕР do
for j := 1 to РАЗМЕР do begin
AB[i,j] := 0;
for k := 1 to РАЗМЕР do
AB[i,j] := AB[i,j] + A[i,k] * B[k,j]
end;
end; (* УМНОЖ *)
4.2. Процедура ОБРАТНАЯ
По заданию предложено использовать алгоритм Гаусса. Возьмем
этот алгоритм [9, с.121] и запишем его на языке Паскаль: но
- 65 -
сначала определим переменные (они следуют из текста алгоритма),
обозначив их теми же именами, что и в алгоритме.
procedure ОБРАТНАЯ (РАЗМЕР: integer; (* n *)
МАТРВХ: ТИПМАТРИЦА;
var X: ТИПМАТРИЦА; (* обратная *)
var СВОЙСТВО: ТИПСВОЙСТВО);
var
A: ТИПМАТРИЦА; (* Исходная матрица, которая будет *)
(* Преобразована в обратную *)
j,
(* Номер обрабатываемого столбца A *)
i,
(* Номер элемента в строке *)
k,
(* Номера элементов *)
StrMax:
(* Номер строки с наибольшим по абсолютной *)
(* величине элементом в столбце j ниже строки j-1 *)
integer;
M: real; (* Наибольший по абсолютной величине элемент *)
СТРОКА: ТИПСТРОКА;
(* Рабочая строка для перестановки строк *)
begin
(* а теперь читаем текст и пишем программу *)
(* Во-первых, положите матрицу X равной матрице I *)
for i := 1 to РАЗМЕР do
for j := 1 to РАЗМЕР do
if i = j then X[i,j] := 1
else X[i,j] := 0;
(* в процессе вычислений матрица A будет в конце концов преобразована в I, матрица X, которая изначально была единичной,
станет обратной к матрице A *)
A: = МАТРВХ;
СВОЙСТВО := НЕВЫРОЖДЕН; (* Исходное значение *)
(* Для каждого столбца A, начиная с столбца 1 слева и кончая
столбцом n справа, выполним следующее: обозначим столбец, который будет обрабатываться на каждом этапе, символом j. *)
j := 1;
while (СВОЙСТВО=НЕВЫРОЖДЕН) and (j<=РАЗМЕР)
do begin
(* Пусть M = Max ¦Aij¦ есть наибольший по абсолютной
j<=i<=n
величине элемент в столбце j ниже строки j-1. *)
- 66 -
M := Abs(A[j,j]); StrMax := j
(* Номер строки, где лежит M *)
for i := j to РАЗМЕР do
if Abs(A[i,j]) > M
then begin
M := Abs(A[i,j]); StrMax := i;
end;
(* Если M равно нулю, то A - вырожденная матрица, и продолжать обращение не имеет смысла. *)
if M < 1E-37
then СВОЙСТВО := ВЫРОЖДЕН
(* В противном случае поменяйте местами в обеих матрицах A
и X строку j и строку, в которой находится M. *)
else begin
СТРОКА:=A[StrMax]; A[StrMax]:=A[j]; A[j]:=СТРОКА;
СТРОКА:=X[StrMax]; X[StrMax]:=X[j]; X[j]:=СТРОКА;
(* И наконец, разделите каждый элемент в строке j матриц A и
X на новое значение Ajj. *)
M := A[j,j];
for i := 1 to РАЗМЕР do begin
A[j,i] := A[j,i]/M;
X[j,i] := X[j,i]/M;
end;
(* Теперь для всех строк i, i<>j выполните все вычитания: *)
Aik = Aik - Aij*Ajk j <= k <= n,
Xik = Xik - Aij*Xjk 1 <= k <= n. *)
for i := 1 to РАЗМЕР do
if i <> j
then begin
M := A[i,j];
for k := j to РАЗМЕР do
A[i,k] := A[i,k] - M*A[j,k];
for k := 1 to РАЗМЕР do
X[i,k] := X[i,k] - M*X[j,k];
end;
end; (* else *)
j := j + 1; (* для каждого столбца A *)
end; (* while *)
end; (* ОБРАТНАЯ *)
- 67 -
4.3. Процедура ВЫВОД
По заданию требуется, чтобы процедура выводила матрицу с нумерацией строк и столбцов. Поэтому сначала выведем строку нумерации элементов в строках, затем будем выводить матрицу построчно. А перед выводом элементов выведем номер строки.
const
MaxРАЗМЕР = 10;
type
ТИПСТРОКА = array [1..MaxРАЗМЕР] of real;
ТИПМАТРИЦА = array [1..MaxРАЗМЕР] of ТИПСТРОКА;
procedure ВЫВОД (РАЗМЕР: integer;
МАТРИЦА: ТИПМАТРИЦА); external;
procedure ВЫВОД;
var
i,
(* номер строки *)
j: integer; (* номер элемента в строке *)
begin
for j := 0 to РАЗМЕР do write (j:7);
writeln;
for i := 1 to РАЗМЕР do begin
write(i:7); (* номер строки *)
for j := 1 to РАЗМЕР do write (МАТРИЦА[i,j]:7:3);
writeln
end
end; (* ВЫВОД *)
4.4. Процедура ЗАПОЛНЕНИЕ
Так как по заданию вариант заполнения исходной матрицы из
трех возможных выбирает пользователь, в теле процедуры ЗАПОЛНЕНИЕ выведем меню возможностей и затем оператором выбора обратимся к одной из трех процедур (рис. 4.2). Не забудем также,
что случайные числа генерируются внешней функцией и ей нужны
исходные данные, поэтому введем
- 68 -
type
НОМЕРВХОДА = (ПЕРВ, НЕПЕРВ);
При первом входе устанавливается исходное состояние и генерируется первое случайное число, при последующих вызовах за исходное значение X, Y принимается предыдущее случайное число.
function ПСЕВДОСЛ(var ВХОД: НОМЕРВХОДА;
var X,Y: (* старое и новое значения *)
real): real;
Теперь текст процедуры ЗАПОЛНЕНИЕ:
const
MaxРАЗМЕР = 10;
type
НОМЕРВХОДА = (ПЕРВ, НЕПЕРВ);
ТИПСТРОКА = array [1..MaxРАЗМЕР] of real;
ТИПМАТРИЦА = array [1..MaxРАЗМЕР] of ТИПСТРОКА;
function ПСЕВДОСЛ(var ВХОД: НОМЕРВХОДА;
var X, Y: real): real; external;
procedure ЗАПОЛНЕНИЕ (РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА); external;
procedure ЗАПОЛНЕНИЕ;
var
СПОСОБ: integer;
(* Номер варианта заполнения *)
procedure ВВОДМАТРИЦЫ(РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА);
begin
(* Ввод с клавиатуры *)
end; (* ВВОДМАТРИЦЫ *)
procedure НАТУР_РЯД(РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА);
begin
(* Заполнение натуральным рядом *)
end; (* НАТУР_РЯД *)
procedure SLUCH_РЯД(РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА);
begin
(* Заполнение случайным рядом чисел *)
end; (* SLUCH_РЯД *)
- 69 -
begin (* ЗАПОЛНЕНИЕ *)
writeln(' Выберите способ заполнения:':30);
writeln('С клавиатуры:
1');
writeln('Случайными числами:
2');
writeln('Натуральным рядом:
3');
write(' Введите номер пункта меню: ');
readln(СПОСОБ);
if (СПОСОБ < 1) or (СПОСОБ > 3)
then СПОСОБ := 2; (* Защита от ошибок пользователя *)
case СПОСОБ of
1: ВВОД_МАТРИЦЫ(РАЗМЕР,МАТРИЦА);
2: SLUCH_РЯД(РАЗМЕР,МАТРИЦА);
3: НАТУР_РЯД(РАЗМЕР,МАТРИЦА);
end;
end; (* ЗАПОЛНЕНИЕ *)
Теперь спустимся еще на один шаг вниз и запрограммируем вызываемые процедуры.
Процедура ВВОД_МАТРИЦЫ
По заданию при вводе матрицы с клавиатуры требуется автоматически нумеровать строки и столбцы, поэтому эту процедуру организуем по аналогии с процедурой ВЫВОД:
procedure ВВОДМАТРИЦЫ(РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА);
var
i, j: integer; (* Номер строки, номер элемента в строке *)
begin
writeln(' Введите матрицу: ',РАЗМЕР:1,'*',РАЗМЕР:1);
for j := 0 to РАЗМЕР do write (j:7);
writeln;
(* Нумерация элементов *)
for i := 1 to РАЗМЕР do begin
write(i:7,' '); (* Номер строки *)
for j := 1 to РАЗМЕР do read(МАТРИЦА[i,j]);
readln
end
end; (* ВВОДМАТРИЦЫ *)
- 70 -
Процедура НАТУР_РЯД
Заполняем матрицу по строкам сверху вниз, по элементам слева
направо, начиная с единицы (переменная n), с шагом 1: .
procedure НАТУР_РЯД(РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА);
var
i, j, n : integer;
begin
n := 1;
for i := 1 to РАЗМЕР do
for j := 1 to РАЗМЕР do begin
МАТРИЦА[i,j] := n;
n := n+ 1
end;
end; (* НАТУР_РЯД *)
Процедура SLUCH_РЯД
Эта процедура заполняет матрицу в таком же порядке, как и
предыдущая, но числа берутся не из n, а генерируются функцией
ПСЕВДОСЛ, следовательно, мы должны обеспечить интерфейс этой
функции, прежде чем ее вызвать: НОМВХОДА := ПЕРВ .
procedure SLUCH_РЯД(РАЗМЕР: integer;
var МАТРИЦА: ТИПМАТРИЦА);
var
i, j: integer;
x, y: real;
НОМВХОДА: НОМЕРВХОДА;
begin
НОМВХОДА := ПЕРВ;
for i := 1 to РАЗМЕР do
for j := 1 to РАЗМЕР do
МАТРИЦА[i,j] := ПСЕВДОСЛ(НОМВХОДА, x, y);
end; (* SLUCH_РЯД *)
- 71 -
А теперь спустимся еще на один шаг вниз и уточним текст
функции ПСЕВДОСЛ, алгоритм которой рекомендовано взять из [17].
Функция ПСЕВДОСЛ
В качестве начального значения выбираем Pi и добавляем дробную часть текущего времени.
type
НОМЕРВХОДА = (ПЕРВ, НЕПЕРВ);
function ПСЕВДОСЛ(var ВХОД: НОМЕРВХОДА;
var X, Y: real): real; external;
function ПСЕВДОСЛ;
var
z : real;
begin
if ВХОД = ПЕРВ
then begin
X := 3.141593 + TIME - Trunc(TIME);
if X > 4.0 then X := X - 1.0;
Y := 0.2 * X;
ВХОД := НЕПЕРВ;
end;
z := X + Y;
Y := X;
if z > 4.0 then z := z - 4.0;
X := z;
ПСЕВДОСЛ := 0.25 * z;
end; (* ПСЕВДОСЛ *)
Download