Задачник-практикум по основам программирования. Учебное пособие по курсу «Информатика»
.pdf{A, B-входные параметры MA, MG-выходные параметры}
begin
MA:=(A+B)/2;
MG:=sqrt(A*B)
end;
var A, B, C: real;
MA1, MA2, MA3, MG1, MG2, MG3: real; begin
writeln(’Введите три числа’); readln(A, B, C);
Mean(A, B, MA1, MG1);
Mean(A, C, MA2, MG2);
Mean(B, C, MA3, MG3); writeln(MA1, MG1); writeln(MA2, MG2); writeln(MA3, MG3)
end.
Пример 6.2. Описать функцию sign(x), вычисляющую знак числа x. Используя эту функцию, вычислить значение выражения sign(a)+ sign(b), где a и b даны.
−1, x < 0 sign(x) = 0, x = 0
1, x > 0
program Sub_2_1;
function Sign(x: real): integer; begin
if x<0 then
Sign:=-1
else if x>0 then
Sign:=1 else
Sign:=0
end;
{программа} var a, b: real;
91
begin
writeln(’Введите два числа’); readln(a, b); writeln(Sign(a)+Sign(b))
end.
Для того чтобы функция вернула значение, веетеле необходимо имени функции присвоить значение результата.
Имя функции в этом контексте ведет себя как обычная переменная. Для сравнения можно реализовать вычисление Sign в виде процедуры. program Sub_2_2;
procedure CalcSign(x: real; var sign: integer); begin
if x<0 then sign:=-1
else if x>0 then sign:=1
else sign:=0 end;
var a, b: real; s1,s2: integer; begin
writeln(’Введите два числа’); readln(a, b);
Calcsign(a,s1);
Calcsign(b,s2);
writeln(s1+s2)
end.
Пример 6.3. Описать функцию вычисления xn, где x – вещественное, а n – целое положительное число. Используя эту функцию, вычислить значение выражения (1.17 + 1.312) ∙ 25.
program Sub_3_1;
function Power(x: real; n: integer): real; var i: integer; P: real;
begin
P:=1;
for i:=1 to n do
P:=P*x;
Power:=P
92
end;
var y: real; begin
y:= (Power(1.1,7)+Power(1.3,12))*Power(2,5); writeln(y)
end.
Примечание. Имя функции нельзя использовать в правой части оператора присваивания в качестве значения этой переменной. Без вспомогательной ло- кальной переменной P при описании функции Power обойтись нельзя, так как оператор Power:=Power*x содержит синтаксическую ошибку (недопустимый вызов функции).
Упражнения
1)Вычислить значение выражения (1.17 + 1.312) ∙ 25, не используя в программе ни одной переменной.
2)Описать процедуру вычисления xn, где x – вещественное, а n – це-
лое положительное число. Используя эту процедуру, вычислить значение выражения (1.17+1.312)∙25.
Переменная Result
В PascalABC, FreePascal и Delphi в теле функции неявно определена переменная Result, представляющая собой результат функции. Ее можно использовать как в левой, так и в правой части оператора присваивания.
Использование переменной Result рассматривается в Примере 6.4.
Пример 6.4. Описать функцию вычисления n!, где n – целое поло- жительное число.
function Fact(n: integer): real; var i: integer;
begin Result:=1;
for i:=1 to n do
Result:=Result*i
end;
Упражнения
1) Вычислить значение выражения y = (9!+7!)/(6!–3!), используя функцию Fact.
93
2)Описать функцию вычисления n!, не используя переменную
Result.
3)Описать процедуру вычисления n!, где n – целое положительное число. Используя эту процедуру, вычислить значение выражения y = (4!+3!)/(5!–4!).
n
4) Описать функцию вычисления ∑i2 , где k и n – целые положи-
i=k
тельные числа, используя переменную Result и не используя ее.
Пример 6.5. Описать процедуру Swap(x, y) обмена значениями переменных x и y.
Передача по ссылке используется для выходных параметров, а по зна- чению – для входных. Параметры x и y являются одновременно входными и выходными. Поэтому они передаются как выходные по ссылке.
procedure Swap(var x, y: real); var z: real;
begin z:=x; x:=y; y:=z
end;
Упражнения
1)Составить программу для проверки работы процедуры Swap.
Можно ли при вызове процедуры вместо формальных параметров x и y
подставить в качестве фактических а) переменные, б) константы, в) выражения. Почему?
2)Составить процедуру Swap(x,y,z) обмена значениями перемен- ных x, y и z местами следующим образом: x в y, y в z, z в x.
Пример 6.6. Дана последовательность из n целых чисел. Определить порядковый номер и значение числа, имеющего максимальную сумму цифр.
Основу решения задачи составляет алгоритм поиска максимального числа и его номера в последовательности целых чисел. При этом будут сравниваться не сами числа, а суммы цифр чисел. Если ввести новую опе- рацию – вычисление суммы цифр целого числа Sum_C(a), то программа будет выглядеть так:
94
program Sub_6;
var n, a, i, max, maxS, nmax, S: integer; begin
write(’Введите количество чисел ’); readln(n);
writeln(’Введите ’,n,’ целых чисел’); read(a);
maxS:=Sum_C(a); nmax:=1; max:=a; for i:=2 to n do begin
read(a); S:=Sum_C(a); if S>maxS then begin
maxS:=S;
nmax:=i;
max:=a end
end;
writeln(’число=’,a,’ его номер=’,nmax, ’ сумма цифр числа=’,maxS)
end.
Анализ текста показывает, что программа была бы синтаксически правильной, если бы была определена функция Sum_C. Функция должна быть описана в разделе описаний в виде:
function Sum_C(a: integer):integer; var S: integer;
begin a:=abs(a); S:=0;
while a<>0 do begin
S:=S + a mod 10; a:=a div 10
end; Sum_C:=S
end;
95
Упражнения
1)Будет ли работать программа, если текст функции Sum_C распо-
ложен после текста основной программы? Проверить работу программы.
2)Изменить программу: определить порядковый номер и значение числа, имеющего минимальное произведение цифр.
Пример 6.7. Дана последовательность символов, заканчивающаяся точкой. Последовательность представляет текст, состоящий из слов, разде- ленных пробелами и запятыми. Вывести каждое второе (с четным номером) слово. В тексте могут встречаться подряд несколько пробелов. Пробелы могут стоять перед первым словом, до и после запятых, перед точкой.
Для решения задачи удобно предположить, что есть действия:
–пропустить символы-разделители (пробел и запятая);
–выдать слово;
–пропустить слово.
Два последних действия считывают слово посимвольно и отличаются только тем, что одно из них выводит считанные символы, а другое – нет. Каждое из этих трех действий завершает свою работу на символе, который уже не относится в этом действии к анализируемым символам. Этот символ нужно передать для дальнейшей обработки следующему действию.
program Sub_7; var c:char;
chetn_word:boolean; {признак выдачи слова} begin
writeln(’Введите текст, заканчивающийся точкой’); read(c);
chetn_word:=false; while c<>’.’ do begin
c:=Skip_Prob(c); {пропустить разделители} if c<>’.’ then
begin
Words(c, chetn_word); {выдать или пропустить
слово}
if c<>’.’ then chetn_word:=not chetn_word
end end
end.
96
Действие Skip_Prob (пропустить разделители) по синтаксису вызова должно быть функцией.
function Skip_Prob(c:char): char; begin
while (c=’ ’) or (c=’,’) do read(c);
Skip_prob:=c end;
Действия Words (выдать или пропустить слово) по синтаксису вызова должно быть процедурой.
procedure Words(var ch:char; flag:boolean); begin
repeat
if flag then write(ch);
read(ch)
until (ch=’ ’) or (ch=’,’) or (ch=’.’); if flag then
writeln
end;
Упражнения
1)Важен ли порядок описания подпрограмм: процедуры Words и
функции Skip_Prob? Проверить работу программы.
2)Изменить программу, чтобы вывести все слова с нечетными номе-
рами.
Пример 6.8. Построить график функции f(x) на отрезке [a, b]. Считать, что функция на отрезке определена и непрерывна. При построении графика использовать такой масштаб, чтобы отрезок [a, b] занимал все графическое окно по ширине. Точки, соответствующие наибольшему (ymax) и наимень- шему (ymin) значениям функции, должны располагаться соответственно в верхней и нижней части графического окна.
Если значение x = 0 принадлежит отрезку [a, b], то изобразить на графике ось OY. Если отрезок [ymin, ymax] содержит значение 0, то изобра- зить на графике ось OX.
Наибольшую трудность при построении графика вызывает его мас- штабирование в границах графического окна. Координатные оси графи-
97
ческого окна направлены слева – направо (ось OX) и сверху – вниз (ось OY). Графические координаты принимают только целые неотрицательные значения. Максимальные значения графических координат определяются размерами графического окна (шириной и высотой). Точка в левом верх- нем углу графического окна имеет графические координаты (0, 0). Точка в правом нижнем углу – графические координаты (W, H), где W – ширина графического окна; H – высота графического окна.
Для определения графических координат можно воспользоваться следующими формулами преобразования:
xгр= round ( x0 +( x – a )*Mx),
где x [a, b], Mx=( xw – x0 )/( b – a ),
x0, xw – графические координаты границы рисунка графика;
yгр= round( y0+( ymax – y )*My ),
где y [ ymin, ymax], My=( yH – y0 )/( ymax – ymin ),
y0 , yH – графические координаты границы рисунка графика;
round (X) – функция округления вещественного X до ближайшего целого
(см. Приложение А).
Координаты x0, xw, y0, yH могут быть установлены равными соответс- твенно 0, W, 0, H – в этом случае график займет все графическое окно. Можно установить значения x0, xw, y0, yH такими, чтобы вокруг графика были отступы определенного размера.
В состав стандартных средств языка Паскаль не входят операторы для работы с графикой. В каждой реализации транслятора для этого предна- значена специальная библиотека, содержащая процедуры и функции для работы с графическим окном. Для использования средств соответствующей библиотеки необходимо в начале программы выполнить ее подключение следующим образом:
uses имя библиотеки;
Например, в системе PascalABC библиотека графики GraphABC подключается так:
uses GraphABC;
Описание некоторых, часто используемых, процедур и функций, входящих в библиотеку GraphABC, приведено в Приложении Б. За более подробной информацией следует обратиться к справке по PascalABC.
program Sub_8; uses GraphABC; var a, b: real; n: integer;
98
function F(x:real):real; begin
F:=x*x-4*abs(x)+3 end;
procedure MaxMin(a, b, h: real; var yMin, yMax: real);
var x,y:real; begin
yMin:=F(a); yMax:=yMin; x:=a;
while x<b+h/2 do begin
y:=F(x);
if y < yMin then yMin:=y;
if y > yMax then yMax:=y;
x:=x+h end
end;
procedure GrFunc(a,b:real;n:integer); var yMin,yMax: real;
x,y,h,Mx,My: real; xe,ye,xep,yep,ox,oy, xemin,yemin,xemax,yemax,i: integer;
function prx(x:real):integer; begin
prx:=round(xemin+(x-a)*Mx) end;
function pry(y:real):integer; begin
pry:=round(yemin+(yMax-y)*My) end;
begin
h:=(b-a)/n; MaxMin(a,b,h,yMin,yMax); xemin:=0; xemax:=WindowWidth; yemin:=0; yemax:=WindowHeight; Mx:=(xemax-xemin)/(b-a);
99
My:=(yemax-yemin)/(ymax-ymin); x:=a;y:=f(a);
xep:=prx(x); yep:=pry(y); for i:=1 to n do
begin
x:=x+h; y:=f(x); xe:=prx(x); ye:=pry(y); Line(xep,yep,xe,ye); xep:=xe; yep:=ye
end;
{ Выводятся оси }
if yMin*yMax < 0 then begin
oy:=pry(0);
Line(xemin,oy,xemax,oy); TextOut( xemax-15,oy+10,’Ox’);
end;
if a*b < 0 then begin
ox:=prx(0);
Line(ox,yemin,ox,yemax); TextOut( ox+10,yemin+15,’Oy’);
end;
end; begin
n:=100;
write (‘Введите концы отрезка a..b ‘); readln(a,b);
GrFunc(a,b,n)
end.
Замечание 1. В системе PascalABC графическое окно выводится как дочернее окно. При этом остаются доступными средства консольного ввода- вывода информации. Для переключения между окнами следует использо- вать клавишу F6 или соответствующие команды меню.
Замечание 2. В процедуре GrFunc используются две вспомогательные функции prx и pry – выполняющие преобразование координат в графичес- кие. Они описаны как локальные, так как их использование вне процедуры GrFunc не имеет смысла. При этом, чтобы не усложнять список параметров
100
