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

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

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


§6. Оператор безусловного перехода. Циклы. Блок-схемы.

Оператор безусловного перехода.

Иногда возникает необходимость перепрыгнуть из одного места программы в другое. Для этого в Pascal есть оператор безусловного перехода GoTo (идти в). В любом месте программы можно поставить метку и с помощью оператора GoTo заставить программу перепрыгнуть в это место. После метки в теле программы ставится двоеточие. Саму метку необходимо описать в разделе объявления меток после слова Label (метка). Пример:


Program UslovniyPerehod;

Label L,L1,L2;

Begin

  GoTo L1;

  L:GoTo L2;

  L1:writeln('Перешли на метку L1');

  GoTo L;

  L2:writeln('Перешли на метку L2');

end.

____________________________________

Перешли на метку L1

Перешли на метку L2


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


Program ProstKalkulator;

Label L;

Var a,b:real;

Begin

  L:Writeln('Введите два числа для сложения:');

  read(a,b);

  Writeln(a,'+',b,'=',a+b);

  Write('Для повторения программы введите 1, ');

  Writeln('для выхода любую другую цифру.');

  read(a);

  If a=1 then goto L;

end.

________________________________________________________________________

Введите два числа для сложения:

3

4

3+4=7

Для повторения программы введите 1, для выхода любую другую цифру.

1

Введите два числа для сложения:

5

4

5+4=9

Для повторения программы введите 1, для выхода любую другую цифру.

5


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

Тем не менее ни кто не запрещает вам использовать этот оператор. В каких-то случаях он может оказаться просто незаменим.


Циклы.

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

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

Счётный цикл.

Рассмотрим первый цикл. Выглядит он следующим образом:


  For x:=1 to 3 do

     ...............;


Вместо точек должен находиться код, который необходимо повторять. Как работает этот цикл? Попробуем перевести эту строчку на русский язык: «Для x равной 1 до 3 делать ….». Далее приведём словесное описание того, как работает такой цикл:

  • Вначале переменной х присваевается значение 1.
  • Затем идёт сравнение, если х меньше или равно числу после слова to, то код цикла выполняется.
  • Затем переменная х увеличивается на единицу и снова идёт сравнение с числом после to. Если х меньше или равно ему, то  код цикла выполняется снова.
  • Затем переменная х снова увеличивается на единицу и всё повторяется до тех пор, пока х не станет больше числа после слова to.

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


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

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

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



For x:=1 to 3 do

   ...............;


Можно по-другому: присвоить значение 2 и делать до 4:


For x:=2 to 4 do

   ...............;


Здесь стоит отметить следующие нюансы. Переменная х должна быть типа byte или любого другого типа, который может содержать в себе только целые переменные. Об этих типах речь пойдёт в отдельном параграфе. Имя переменной может быть любым. Переменную х можно использовать в любом месте программы, а так же и внутри цикла. Однако менять переменную внутри цикла нельзя, можно использовать только её значение. Если код цикла состоит не из одной строчки, а из нескольких, то их необходимо выделить словами  begin и end:


For x:=2 to 4 do

  begin

    ...............;

    ...............;

    ...............;

  end;


Так же вместо констант 1 и 3 можно использовать имена констант или переменные, но только типа целых чисел.

Далее пример программы:


Program ScetniyCikl;

var x,y,z:byte;

begin

y:=1;

z:=3;

for x:=y to z do

  begin

   write('x=');

   write(x);

   writeln(' ');

  end

end.

___________________

x=1

x=2

x=3


Обратите внимание, что для удобства чтения перед словами begin и end есть небольшой отступ, а перед строчками кода отступ немного больше. Дело в том, что внутри одного цикла может быть другой цикл, а внутри другого может быть третий и т.д. Что бы  было наглядно видно, где начинается и заканчивается один цикл, а где другой, их выделяют отступами. Это, как было уже сказано, и есть хороший тон программирования. Например, код может выглядеть следующим образом:


For i:=1 to 3 do

   begin

     ...............;

     For g:=1 to 3 do

       begin

         ...............;

         ...............;

       end;

     ...............;

     ...............;

   end;


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


Циклы с условием.

Двигаемся дальше. Рассмотрим циклы с условием. Эти циклы повторяются в зависимости от какого-то условия. Если условие верно, то цикл повторяется, если нет, то происходит выход из цикла. Разница этих двух циклов заключается в том, что в одном проверка условия происходит перед кодом цикла, в другом после кода цикла.

Рассмотрим оба цикла по отдельности. В начале цикл, в котором условие проверяется перед кодом цикла. В общем виде он выглядят следующем образом: While условие do ………….;

По-русски «Пока условие делать………;»

Далее не буду словесно описывать работу данного цикал, а сразу приведу блок-схему:



Далее пример программы и блок схема данной программы:


Program CiklSUsl;

var x:byte;

begin

x:=1;

while x<=3 do

  begin

   writeln('x=',x);

   x:=x+1;

  end

end.

_____________________

x=1

x=2

x=3


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

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

В начале параграфа мы рассматривали оператор безусловного перехода GoTo, и было сказано, что его использование нежелательно. Приведу пример программы, которая идентична программе ProstKalkulator, но без использования оператора безусловного перехода:


Program ProstKalkulator_1;

Var a,b,c:real;

Begin

  c:=1;

  while c=1 do

   begin

    Writeln('Введите два числа для сложения:');

    read(a,b);

    Writeln(a,'+',b,'=',a+b);

    Write('Для повторения программы введите 1,);

    Writeln(' для выхода любую другую цифру.');

    read(c);

   end

end.

_________________________________________________________________________

Введите два числа для сложения:

35

23

35+23=58

Для повторения программы введите 1, для выхода любую другую цифру.

1

Введите два числа для сложения:

45

56

45+56=101

Для повторения программы введите 1, для выхода любую другую цифру.

4


В чём здесь преимущество перед оператором GoTo. Здесь наглядно видно, где начинается и где заканчивается цикл. Допустим цикл состоял бы из нескольких десятков строк, тогда с оператором  GoTo было бы менее понятно как работает программа.

Далее рассмотрим последний оставшийся цикл с условием. В общем виде он выглядит следующим образом:

Repeat ……… until условие;

По-русски «Повторять ……….. до тех пор пока не станет условие;».

Блок-схема алгоритма:


Обратите внимание, что проверка условия происходит в конце цикла, т.е. один раз (самый первый) код цикла будет выполнен в любом случае. Так же стоит отметить, что код цикла повторяется, если условие ложно, т.е. код цикла повторяется до тех пор, пока условие не станет верным. Так же как и в предыдущем цикле переменные, которые участвуют в условии можно и нужно менять внутри цикла.

Далее пример программы:


Program CiklSUsl_1;

var x:byte;

begin

x:=0;

repeat

  x:=x+1;

  writeln('x=',x);

until x>=3;

end.

__________________

x=1

x=2

x=3


Как видно из результата, эта программа идентична программе CilkSUsl и программе ScetniyCikl. Однако задача здесь решена с помощью другого алгоритма. В некоторых случаях задачу можно решить с помощью любого из трёх циклов, однако в более сложном случае может подойти только один. Если вы попытаетесь решить задачу неподходящим циклом, то обречёте себя на лишние хлопоты при отладке программы.

Если внимательно изучить программу CilkSUsl_1, то вы увидите, что между словами repeat и until нет слов begin и end, хотя и используется несколько строчек кода. Дело в том, что в данном цикле слова repeat и until сами выполняют функцию слов begin и end.

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


Выход из цикла не по условию.

Для немедленного выхода из цикла существуют следующие процедуры:

Break реализует немедленный выход из цикла, действие процедуры заключается в передаче управления     оператору, стоящему сразу за концом циклического оператора;

Continue обеспечивает досрочное завершение очередного прохода цикла, передаёт управление в самый конец циклического оператора.

Данные процедуры можно использовать не только в циклах с условием, но и в счётном цикле.

Теперь пример программы, в которой используется цикл с условием, и где условие ни когда не станет правдой. Выход из цикла здесь реализован с помощью процедур Break и Continue. Можете поэкспериментировать с данной программой, и вам станет яснее, как работаю процедуры Break и Continue.


Program DosVihod;

{---------------------------------

Программа демонстрирует

досрочное завершение прохода цикла

и досрочный полный выход из цикла.

---------------------------------}

Var c:byte;

Begin

  c:=4;//Инициализация переменной.

  While c<>3 do

   begin

     writeln('Цикл начал свою работу.');

     Writeln('Если хотите выйти из цикла введите 1');

     Writeln('Если хотите завершить проход цикла введите 2');

     Write('Если хотите продолжить нормальный проход введите любую');

     Writeln(' другую цифру');

     readln(c);

     If c=1 then break;//Выходим из цикла.

     If c=2 then

       begin

         writeln('Цикл не совершил полный проход.');

         Writeln;//вставили пустую строку.

         continue;//Завершаем проход цикла.

       end

     c:=4;//Что бы цикл повторился снова, если пользователь ввёл цифру 3.

     writeln('Цикл полностью совершил проход.');

     Writeln;//вставили пустую строку.

   end;

writeln;//вставили пустую строку.

Writeln ('Конец программы.');

end.

_________________________________________________________________________

Цикл начал свою работу.

Если хотите выйти из цикла введите 1

Если хотите завершить проход цикла введите 2

Если хотите продолжить нормальный проход введите любую другую цифру

3

Цикл полностью совершил проход.


Цикл начал свою работу.

Если хотите выйти из цикла введите 1

Если хотите завершить проход цикла введите 2

Если хотите продолжить нормальный проход введите любую другую цифру

2

Цикл не совершил полный проход.


Цикл начал свою работу.

Если хотите выйти из цикла введите 1

Если хотите завершить проход цикла введите 2

Если хотите продолжить нормальный проход введите любую другую цифру

1


Конец программы.


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


Задачи:

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

1. Вывести на экран ряд целых чисел от 1 до 50 в виде таблицы. Причём числа должны идти последовательно друг за другом через пробел по десять в каждой строчке.

2. Написать программу калькулятор, которая будет выполнять сложение, вычитание, умножение и деление двух чисел. Причём, выполнив одно действие, необходимо, что бы для выполнения ещё одного действия программу не нужно было бы запускать заново.

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

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


Решение:

1.

Program VivodChisel;

{Программа для вывода ряда целых чисел в виде таблицы.}

Var k,//Переменная для формирования строк.

    g,//Переменная для формирования столбцов.

    x//Переменная для хранения числа, которое выводим на экран.

    :byte;

Begin

  x:=1; //Начальное значение числа.

  for k:=1 to 5 do //Формируем строчки.

   begin

     for g:=1 to 10 do //Формируем столбцы.

       begin

         write(x:3);//Выводим число на экран.

         x:=x+1;//Увеличиваем число на единицу.

       end

     writeln;//Переходим на следующую строчку. 

   end

end.

_______________________________________________________________

  1  2  3  4  5  6  7  8  9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50


2.

Program Calculyator;

{Программа производит сложение, вычитание, умножение и деление двух чисел.}

Label l;//Метка для возврата на начало программы.

Var x,y:real;//Два числа для проведения операций.

    c:byte;//Переменная для принятия решений.

Begin

  {Вводим два числа.}

  l:Writeln('Введите два числа');

  Readln(x,y);

  {Предлагаем пользователю выбрать операцию.}

  Writeln('Введите номер операции согласно следующего списка:');

  Writeln('Сложение  - 1');

  Writeln('Вычитание - 2');

  Writeln('Умножение - 3');

  Writeln('Деление   - 4');

  {Считываем номер необходимой операции.}

  Readln(c);

  {В зависимости от выбранной пользователем операции производим

   вычисления.}

  If c=1 then Writeln(x,'+',y,'=',x+y);

  If c=2 then Writeln(x,'-',y,'=',x-y);

  If c=3 then Writeln(x,'*',y,'=',x*y);

  If c=4 then Writeln(x,'/',y,'=',x/y);

  {Если пользователь ввёл неверно номер операции выдаём сообщение об

   этом.}

  If (c<>1)and(c<>2)and(c<>3)and(c<>4) then

    writeln('Вы ввели не правильный номер операции');

  {Предлагаем пользователю выбор продолжить работу или завершить.}

  Write ('Для продолжения работы введите 1,');

  Writeln(' для выхода из программы - другую цифру');

  Read(c);

  Writeln;//Пустая строка.

  {Если пользователь решил продолжить переходим на начало программы.}

  If c=1 then goto l;

  {Если пользователь решил завершить работу выводим сообщение

  о завершении работы программы}

  Writeln('Программ завершила свою работу.');

end.

_________________________________________________________________________

Введите два числа

4

3.5

Введите номер операции согласно следующего списка:

Сложение  - 1

Вычитание - 2

Умножение - 3

Деление   - 4

3

4*3.5=14

Для продолжения работы введите 1, для выхода из программы - другую цифру

1


Введите два числа

5.67

34

Введите номер операции согласно следующего списка:

Сложение  - 1

Вычитание - 2

Умножение - 3

Деление   - 4

4

5.67/34=0.166764705882353

Для продолжения работы введите 1, для выхода из программы - другую цифру

5


Программ завершила свою работу


3. Примечание: факториал числа это произведение целых чисел от одного до этого числа. При записи факториала перед числом ставиться восклицательный знак. Например: . Так как факториалы даже небольших чисел имеют достаточно большие значения, то необходимо для их хранения использовать тип Real.


Program Factorial;

{Программа вычисляет факториал числа.}

Var F:real;//Переменная хранит в себе произведение чисел.

    k,//Переменная для организации счётного цикла для вычисления

      //факториала.

    c,//Переменная для ввода выбора пользователя.

    x//Переменная для ввода числа, факториал которого будет вычисляться.

    :Byte;

Begin

  c:=1;//Начальное значения переменной, что бы цикл прошёл первый раз.

  While c=1 do

   begin

{Предлагаем пользователю ввести число факториал которого будет вычислен.}

     Writeln('Введите целое число.');

     read(x);

     F:=1;//Начальное значение Факториала равно единице.

     For k:=1 to x do F:=F*k;//Вычисляем факториал.

     Writeln('!',x,'=',F);//Выводим на экран результат.

     {Предлагаем пользователю выбор продолжить работу или завершить.}

     Write('Для продолжения работы введите 1 для выхода - любую ');

     Writeln('цифру.');

     Read(c);

   end;

end.

_________________________________________________________________________

2

!2=2

Для продолжения работы введите 1 для выхода - любую цифру.

1

Введите целое число.

3

!3=6

Для продолжения работы введите 1 для выхода - любую цифру.

1

Введите целое число.

6

!6=720

Для продолжения работы введите 1 для выхода - любую цифру.

2



4.

Var x,//Переменная для перебора значений x.

    y,//Переменная для перебора значений y.

    s,//Переменная для счёта количества вариантов, счётчик вариантов.

    A//Переменная для ввода значения числа А.

    :byte;

Begin

  Writeln('Введите число А');

  Read(A);

  s:=0;//Начальное значение.

  {Цикл перебора значений.}

  For x:=0 to 255 do

    begin

      For y:=0 to 255 do

        begin

          if (4*x+2*y+5)=A then

            begin    //Если выражение верное, то

              s:=s+1;//увеличиаем счётчик вариантов

              Writeln('x=',x:2,'  y=',y:2);//и выводим значения

                                           //неизвестных.

            end

        end;

    end;

                    //Сообщение если вариантов нет.

  If s=0 then writeln('Не найдено ни одного варианта неизвестных.')

                    //Сообщение о количестве найденных вариантов.

   else writeln('Всего найдено ',s,' вариантов значений неизвестных.');

end.

_________________________________________________________________________

Введите число А

45

x= 0  y=20

x= 1  y=18

x= 2  y=16

x= 3  y=14

x= 4  y=12

x= 5  y=10

x= 6  y= 8

x= 7  y= 6

x= 8  y= 4

x= 9  y= 2

x=10  y= 0

Всего найдено 11 вариантов значений неизвестных.




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