Учебник по программированию.

Первые шаги. Язык программирования PascalABC.

Предыдущий параграф Назад в содержание Следующий параграф


Глава III. Дополнительные сведения к пройденному.


Мы немало изучили, написали достаточно серьёзные программы, однако «предела совершенству не существует». Материал в предыдущих параграфах давался порциями, которые может воспринять неподготовленный человек. Для того что бы двигаться дальше, нам необходимо узнать дополнительные нюансы к уже пройденному материалу.


§14. Сведения по различным темам.

Цикл For downto do.

Мы уже знакомы с циклом For to do. В этом цикле переменная счётчик, при каждом прохождении цикла, увеличивается на единицу, пока не достигнет определённого значения. Так же в языке Pascal есть цикл For down to, в котором переменная-счётчик уменьшается на единицу, при каждом проходе цикла. Принципы использования данного цикла такие же, разница лишь в том, что переменная-счётчик уменьшается, а не увеличивается. Пример:


var i:integer;

begin

  For i:=10 downto 0 do

   write(i:3);

end.

_________________________________

10  9  8  7  6  5  4  3  2  1  0



Процедуры Halt и Sleep.

procedure Halt; завершает работу программы. Пример:


var c:char;

begin

  while true do

    begin

     writeln('Для завершения работы программы введите 1');

     readln(c);

     if c='1' then halt;

     writeln('Программа продолжила работу.');

    end;

end.

___________________________________________________________

Для завершения работы программы введите 1

4

Программа продолжила работу.

Для завершения работы программы введите 1

w

Программа продолжила работу.

Для завершения работы программы введите 1

e

Программа продолжила работу.

Для завершения работы программы введите 1

1


В параграфе, где мы изучали циклы, непрерывная работа программы была реализована с помощью цикла While to do, в условии мы проверяли значение переменной c. После выхода из цикла программа завершалась автоматически, т.к. далее не было больше ни строчки кода. Непрерывную работу программы можно организовать и с помощью константы True. В таком случае мы никогда не сможем выйти из цикла While to do, т.к. эта константа никогда не изменится. Для завершения работы программы как раз можно использовать процедуру Halt. Вызвать её можно в любом месте программы, где вам удобно.

procedure Sleep(ms: integer); делает паузу на ms миллисекунд. Одна миллисекунда это 0.001 секунда. Поэтому, что бы сделать паузу на одну секунду, необходима пауза в 1000 миллисекунд. Пример:


var i:integer;

begin

  For i:=10 downto 0 do

   begin

    if i=0 then write('  Пуск!') else write(i:3);

    sleep(1000);

   end;

end.

___________________________________________________

10  9  8  7  6  5  4  3  2  1  Пуск!


В данном примере каждая новая цифра появляется через одну секунду, после появления предыдущей.


Математические функции.

function Abs(x: Real):Real; возвращает модуль числа x. x число любого типа, целого или вещественного. Тип возвращаемого значения такой же как и у переменной x.

function Round(x: real): integer; возвращает x, округленное до ближайшего целого.

function Int(x: real): real; возвращает целую часть числа x.

function Frac(x: real): real; возвращает дробную часть числа x.

Pi возвращает значение Пи с точностью числа типа real. Примечание: в TurboPascal Pi функция, которая вызывается без передаваемых параметров. В PascalABC.NET Pi именованная константа. Однако синтаксис от этого не меняется. Там и там достаточно написать просто слово Pi.

function Sqr(x: real): real; возвращает квадрат числа x. Другими словами возводит в квадрат или как принято записывать в математике .

function Sqrt(x: real): real; возвращает квадратный корень числа x ().

function Power(x,y: real): real; возвращает x в степени y.

function Exp(x: real): real; возвращает экспоненту числа x ().

function Ln(x: real): real; возвращает натуральный логарифм числа x ().

Пример использования математических функций:


var x:real;

begin

  x:=-3.56;

  writeln('x = ',x);

  writeln('abs(x) = ',abs(x));

  writeln('round(x) = ',round(x));

  writeln('int(x) = ',int(x));

  writeln('frac(x) = ',frac(x));

  writeln('Pi = ',Pi);

  writeln('sqr(6) = ',sqr(6));

  writeln('sqrt(36) = ',sqrt(36));

  writeln('Power(27,1/3) = ',Power(27,1/3));

  writeln('exp(1) = ',exp(1));

  writeln('ln(2.718) = ',ln(2.718));

end.

__________________________________

x = -3.56

abs(x) = 3.56

round(x) = -4

int(x) = -3

frac(x) = -0.56

Pi = 3.14159265358979

sqr(6) = 36

sqrt(36) = 6

Power(27,1/3) = 3

exp(1) = 2.71828182845905

ln(2.718) = 0.999896315728952


Тригонометрические функции.

function Cos(x: real): real; возвращает косинус числа x ().

function Sin(x: real): real; возвращает синус числа x ().

function ArcTan(x: real): real; возвращает арктангенс числа x ().

Во всех тригонометрических функциях угол x должен быть выражен в радианах.

Пример:

begin

  writeln('cos(Pi/2) = ',cos(pi/2):4:3);

  writeln('sin(Pi/2) = ',sin(pi/2):4:3);

  writeln('arctan(1) = ',arctan(1):4:3);

end.

________________________________________

cos(Pi/2) = 0.000

sin(Pi/2) = 1.000

arctan(1) = 0.785


Все вышеприведенные дополнительные процедуры и функции можно использовать как в TurboPascal, так и в PascalABC.NET. Плюс к этим математическим и тригонометрическим функциям в PascalABC.NET есть и другие, с которыми вы можете ознакомиться в разделе справки: «Справочник по языку->Системные процедуры, процедуры, функции, типы и константы->Математические процедуры и функции».

Для тех, кто обучается в TurboPascal, следует написать следующее: в TurboPascal нет функции возведения в степень, можно возвести только в квадрат. Так же нельзя извлечь ни квадратный корень, ни какой-либо другой. Так же нет функции арксинуса, арккосинуса, тангенса и котангенса. Однако все это можно сделать, используя эти функции, немного поразмыслив мозгами.

Далее будет приведена методика разработки своих, вышеперечисленных недостающих в TurboPascal функций. В конце параграфа в задачах для самостоятельного решения будет предложено написать код этих подпрограмм.

Возведение в степень. Допустим необходимо возвести число с в степень х, после чего должно получиться число b (). Это же число можно получить, если возвести число в степень y (). x и y можно представить через логарифм: ; . Из свойства логарифмов можно получить следующее равенство: . Из всего вышесказанного получаем, что . Код программы будет выглядеть следующим образом:


var x,b,c:real;

begin

  x:=2;c:=4;

  b:=exp(x*ln(c));

  writeln(c,' в степени ',x,' равно ',b);

end.

_________________________________________

4 в степени 2 равно 16


Извлечение корня. Известно, что квадратный корень это не что иное, как степень . Соответственно, что бы извлечь кубический корень, необходимо возвести в степень равную . И так далее. Пример:


var x,b,c:real;

begin

  x:=1/3;c:=27;

  b:=exp(x*ln(c));

  writeln(c,' в степени ',x,' равно ',b);

end

_________________________________________

27 в степени 0.333333333333333 равно 3


Тригонометрические функции. Тангенс и котангенс находятся из следующих выражений: ; .

Арксинус, арккосинус, арктангенс и арккотангенс это сам угол, т.е. его можно найти с помощью функции arctan. Для этого достаточно перевести синус и косинус в тангенс. Если известен только синус или только косинус, то используется следующая тригонометрическая формула: Отсюда

Получаем: ; ; .

Думаю, что вам не составит труда перевести данные формулы в код.

  

Создание переменных в теле программы.

До сих пор мы объявляли переменные в разделе описания переменных. При таком подходе переменная создаётся в начале работы программы и существует, пока программа не завершит свою работу. Если переменная создана в разделе описания переменных в подпрограмме, то переменная будет существовать, пока работает подпрограмма. Такой принцип действует в старом TurboPascal.

В других языках, например в C++, переменная создаётся прямо в теле программы, а затем, когда она уже будет не нужна, её можно уничтожить. При таком подходе переменная не будет занимать место в памяти компьютера на протяжении работы всей программы. Соответственно, ресурсы компьютера будут использоваться более рационально.

Так как язык PascalABC.NET был создан для обучения, и ориентирован на программирования на платформе .NET, то эту возможность ввели и в него.

Для того, что бы создать переменную в теле программы, так же используется слово var. Пример:


begin

  var s:string;

  s:='Привет всем!';

  Writeln(s);

end.

_____________________

Привет всем!


Такая переменная, созданная в теле программы, существует в том блоке кода, который заключён словами begin и end. После выхода из блока переменная уничтожается. В следующем примере переменную iTemp, созданную внутри цикла, нельзя использовать вне цикла:


Var i:integer;

begin

  For i:=1 to 5 do

    begin

      var iTemp:integer;

      iTemp:=i+5;

      write(iTemp,'  ');

    end;

//Следующая строка приведёт к ошибке "Неизвестное имя 'iTemp'"

//writeln(iTemp); 

end.

_______________________________________________________________

6  7  8  9  10 


Так же в цикле for to do переменную счётчик можно объявить после слова for. При этом после завершении цикла данная переменная будет уничтожена.


begin

  For var i:=1 to 5 do

    begin

      write(i,'  ');

    end;

//Следующая строка приведёт к ошибке "Неизвестное имя 'i'"

//writeln(i); 

end.


Ещё одно замечание: если вы создали переменную в разделе описания переменных, то вы не можете создать переменную в  теле программы с таким же именем. То же самое относится и к телу подпрограммы. Говоря другими словами, у каждого блока может быть раздел описания переменных, при этом если там уже есть переменная с определённым именем, то вы не можете создать внутри этого блока переменную с таким же именем. Пример:


Var s:string;

begin

  s:='Я - глобальная переменная';

//var s:string; - ошибка.

end.


Ещё раз повторюсь, создавать переменную в теле программы или подпрограммы можно в PascalABC.NET. В TurboPascal создавать переменные внутри блока нельзя, только в разделе описания переменных.


Идентификаторы.

До сих пор мы использовали следующие словосочетания: имя переменной, имя константы, имя процедуры или имя функции. В разделе справки или литературе вы встретите слово идентификатор. Идентификатор это имя переменной, константы или подпрограммы. Другими словами это любое имя, которое вы даёте чему-либо.

В любом языке программирования есть зарезервированные слова, которые имеют определённое назначение и которые нельзя использовать в качестве идентификаторов. Эти слова ещё называют ключевыми. Далее приведён список зарезервированных слов в PascalABC.NET:


and array as begin case class const constructor destructor div do downto else end event except file final finalization finally for foreach function goto if implementation in inherited initialization interface is label lock mod nil not of operator or procedure program property raise record repeat set shl shr sizeof template then to try type typeof until uses using var where while with xor


Любое другое сочетание латинских букв или цифр, начинающееся с буквы, считается идентификатором и может использоваться для имён переменных, констант или подпрограмм.

Символ «_» тоже можно использовать при составлении идентификатора, причём в данной ситуации он считается буквой. Т.е. с этого символа можно начать идентификатор, например: «_Number». Так же этим символом удобно пользоваться вместо пробела, если идентификатор состоит как бы из двух слов. Т.к. в идентификаторах нельзя использовать пробел, то можно эти слова разделить этим символом, например: imya_fayla.

Со многими зарезервированными словами вы уже знакомы, некоторые ещё предстоит узнать. Однако специально запоминать их нет необходимости. Если вы назовёте какую-либо переменную зарезервированным словом, то вероятнее всего при компиляции появится сообщение об ошибке, и вы измените название переменной (идентификатор). К тому же все зарезервированные слова автоматически выделяются жирным шрифтом.

Ещё два нюанса. Количество символов в идентификаторе может быть любым. И как было уже сказано, в языка Pascal регистр букв не имеет значение, т.е. если вы напишите в одной строчке Name, в другой name, то вы напишите один и тот же идентификатор.

Далее речь пойдёт о том, как нужно формировать идентификаторы.

Во время работы над программой, вы хорошо представляете себе назначение той или иной переменной, поэтому имя переменной особо не имеет значения. Однако, когда проходит время и вы смотрите на свою же собственную программу, то в ней ничего понятно не будет. Поэтому идентификаторы в программе должны быть осмысленными. Например, если вам необходимо в переменной хранить имя человека, то идентификатор должен быть, например, следующим: name_of_man. Если вы не знаете английский язык, то можно написать по-русски, но латинскими символами, например: Imya_cheloveka.

Написание русских слов буквами латинского алфавита называется транслитерацией. Существует множество их разновидностей. Существуют даже госты транслитерации для написания русских имён. Однако «в быту» они не очень удобны. Единственного всеобще-принятого правила транслитерации не существует. Тем не менее, думаю что любой, кто знает английский алфавит, может интуитивно написать любое русское слово латинскими буквами. В этом нет ничего сложного. Тем более, что в нашем случае нам необходимо, что бы нас понял наш товарищ по команде или мы сами, спустя какое-то время.

Плюс ко всему можно добавить, что если имя переменной состоит из двух слов, то их можно не только разделить знаком подчёркивания, но и написать их слитно, но с большой буквы каждое. Например: NameOfMan. Изначально способ с символом подчёркивания использовался в языке C, а второй способ с заглавными буквами в языке Pascal. Лично мне больше симпатичен первый способ с символом подчёркивания, т.к. слова в таком случае читаются отчётливей.

Ещё одно правило, неофициально принятое среди программистов. В цикле For to do для имени переменной счётчика используется буква i. Во всех предыдущих примерах так и было сделано. Если внутри этого цикла встретиться ещё цикл For to do, то для него используется буква j. Если внутри второго цикла будет снова находиться цикл For to do, то буква k. И так далее по алфавиту (i,j,k,l,m,n,o…). Например, имеем двумерный массив целых чисел, тогда программа формирования этого массива будет выглядеть следующим образом:


var m:array [1..10,1..5] of integer;

begin

  for var i:=1 to 10 do

    for var j:=1 to 5 do m[i,j]:=random(1,100);

end.



Венгерская нотация.

В этом подразделе поговорим о том, как формируются идентификаторы. В принципе, идентификатор может быть любым, компилятор не выдаст ошибки, какой бы идентификатор вы бы не придумали. Однако существуют определённые правила формирования идентификаторов, принятые среди программистов. Эти правила описаны в «Венгерской нотации».

Конечно, вы можете не придерживаться данным правилам. Однако если вы будете работать в команде, то понимать чужой код легче, если идентификаторы сформированы по определённым правилам. Т.е. в любом случае, в любой команде рано или поздно появятся определённые правила. Не легче ли сразу воспользоваться уже готовыми?

Венгерская нотация соглашение, принятое среди программистов, о правилах именования идентификаторов в коде программ. Эти правила предложил сотрудник компании Microsoft Чарльз Симони, в те далёкие времена, когда писались первые версии MS-DOS. В дальнейшем эти правила стали внутренним стандартом Microsoft. Родом Чарльз Симони был из Венгрии, отсюда и название нотации.

Суть нотации заключается в том, что при формировании идентификатора перед именем переменной ставится префикс. Префикс один или несколько символов, указывающие на тип переменной, или несущие определённый смысл. Далее в таблице приведу самые распространённые префиксы, которыми вы уже можете пользоваться. Более полный список вы можете найти в Википедии, или на каком-либо другом сайте, набрав в поисковике «Венгерская нотация».


Префиксы, обозначающие тип переменной:

Префикс

Сокращение от

Смысл

Пример

s, str

string

строка

sName

i

int

целочисленная переменная

iLevayaStorona

r

real

переменная вещественного типа

rOtnosheniye

l

long

длинное целое

lFactorial

b

boolean

булева переменная

bKnopka

a

array

массив

aSpisok

g_

global

глобальная переменная

g_aSpisok


Префиксы, обозначающие назначение переменных.

Префикс

Сокращение от

Смысл

Пример

i

index

Индекс

iIndex

d

delta

Разница между значениями

dAB

n

number

Число, количество чего либо

nFructi

c

counter

Счётчик

сNajatie

cur

current

Текущее значение

curKol


Инициализация переменных.

В одном из первых параграфов было сказано, что необходимо переменным присваивать начальные значения, инициализировать. Дело в том, что когда вы объявляете переменную, под неё выделяется определённая память в компьютере, если в этой памяти уже содержалась какая-то информация, то ваша переменная её «унаследует». В PascalABC.NET вновь созданным переменным автоматически присваивается начальное нулевое значение. Однако, если вы работаете в какой-либо другой среде разработки, и вы не уверенны, что начальные нулевые значения присваиваются автоматически, то присваивайте их вручную, иначе можете получить неверный результат.

В PascalABC.NET начальное значение переменной можно присвоить в разделе описания переменных. При этом тип переменной не указывается. Тип переменной определяется автоматически. Пример:


Var s:='Привет всем!';

    i:=5;

begin

  writeln(s);

  writeln(5);

end.

_____________________

Привет всем!

5


Однако надо быть внимательным, т.к. присвоенный тип может не соответствовать тому, что нужно вам. Например, в данном примере переменной i был присвоен тип integer, а вам возможно нужен был тип LongInt.

Для того, что бы не произошло недорозумения инициализировать переменную в PascalABC.NET можно следующим образом:


  var i:LongInt:=5;


Если для обучения вы используете PascalABC.NET, то рекомендую указывать тип и начальное значение переменным именно таким образом.


В данном параграфе мы изучили цикл For downto do, процедуры Halt и Sleep, ряд готовых математических функций, а так же рассмотрели методику создания некоторых функций, которых нет в TurboPascal. Рассмотрели вопросы о возможности создания переменной в теле блока программы и об инициализации переменных при объявлении. Так же изучили вопрос об идентификаторах и Венгерской нотации.


Задачи.

1. Используя функции Fruc и Int, округлить вещественное число до сотых.

2. Имеем следующую функцию . Вывести на экран значения округлённые до целого значения, при равном 10,9,8.. 0. Для получения значений использовать цикл For downto do.

3. На основе функций ln и exp cоздать функцию, которая возвращает число, возведённое в степень. Первым параметром должно быть число, которое надо возвести, вторым параметром степень, в которую нужно возвести. Создать программу, демонстрирующую работу этой функции. Методика создания данной функции была приведена в данном параграфе.

4. Создать следующие тригонометрические функции на основе пройденных: tan, ctan, arcctan, arcsin, arccos. Привести пример их использования. Методика их создания была приведена в данном параграфе.

5. Придумать идентификаторы следующим переменным:

  • переменная для хранения временного значения целого числа;
  • переменная для хранения текущего значения температуры;
  • переменная для счёта количества нажатий.


Решение.

1.

var r:real;

begin

  r:=pi;

  writeln('До округления r=',r);

  r:=int(r)+round(frac(r)*1000)/1000;

  writeln('После округления r=',r);

end.

_____________________________________

До округления r=3.14159265358979

После округления r=3.142


2.

var i:integer;

    y:real;

begin

  writeln('  x     y');

  for i:=10 downto 0 do

      writeln(i:3,round(2.34*i*i*i+4.1*i*i-3.2*i-3.6):6);

end.

_________________________________________________________

  x     y

10  2714

  9  2006

  8  1431

  7   978

  6   630

  5   375

  4   199

  3    87

  2    25

  1     0

  0    -4


3.

function stepen(r,x:real):real;

begin

  stepen:=exp(x*ln(r));

end;

begin

  writeln('27 в степени 1/3 равно ',stepen(27,1/3));

end.

____________________________________________________

27 в степени 1/3 равно 3

4.

Program Trigonometriya;

function tan(r:real):real;

begin

  tan:=sin(r)/cos(r);

end;

function ctan(r:real):real;

begin

  ctan:=cos(r)/sin(r);

end;

function arcctan(r:real):real;

begin

  arcctan:=arctan(1/r);

end;

function arcsin(r:real):real;

begin

  arcsin:=arctan(r/sqrt(1-r*r));

end;

function arccos(r:real):real;

begin

  arccos:=arctan(sqrt(1-r*r)/r);

end;

begin

  writeln('tan(pi/4) = ',tan(pi/4));

  writeln('ctan(pi*3/4) = ',ctan(pi*3/4));

  writeln('arcctan(pi) = ',arcctan(pi));

  writeln('arcsin(0) = ',arcsin(0));

  writeln('arccos(1) = ',arccos(1));

end.

__________________________________________

tan(pi/4) = 1

ctan(pi*3/4) = -1

arcctan(pi) = 0.308169071115985

arcsin(0) = 0

arccos(1) = 0


5.

  • iTemp;
  • curTemperature;
  • cKnopka.




Предыдущий параграф Назад в содержание Следующий параграф