Персональная страничка
Диканева Тараса
Викторовича

Главная \ Преподавательское \ Программирование для начинающих

3. Цикл с параметром (for)

Предыдущий раздел:

Следующий раздел:

3.1. Цикл for

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

В варианте (а) если «условие» истинно выполняются «операторы». После этого снова проверяется «условие» и, если оно по прежнему истинно, то снова выполняются операторы и так далее, пока условие не станет ложным. Вариант (б) подобен варианту (а), отличие только в том, что сначала выполняются «операторы», а только затем делается проверка условия, на основе которой мы решаем, нужно ли повторять их выполнение.

Блок-схемы циклов

Рис. 1. Блок-схемы циклов.

В языке Паскаль существует несколько вариантов организации циклов. Рассмотрим один из них – так называемый цикл с параметром или цикл for. Чтобы записать его нам потребуется переменная целого типа, например:

  var
    i: integer;

Схема его записи выглядит следующим образом:

  for i := <начальное значение> to <конечное значение> do
  begin
    <операторы>
  end;

Здесь i – так называемая переменная-счетчик (разумеется, ее не обязательно называть именно i, это может быть любая переменная целого типа). Начальное и конечное значение это любые выражения, имеющее значение целого типа. Когда оператор цикла начинает работу переменная счетчик принимает начальное значение, затем выполняются <операторы>, после этого счетчик увеличивается на единицу, и снова выполняются операторы. Процесс повторяется, пока счетчик не окажется больше конечного значения. Например, если начальное значение 2, а конечное 3, то <операторы> будут выполнены 2 раза. Область между словами begin и end, где располагаются повторяющие в цикле операторы, называется телом цикла.

На рис. 2 показана блок-схема работы этого цикла.

Блок-схема работы цикла for

Рис. 2. Схема работы цикла с параметром (for).

Пример 1: Напечатать слово Hello на экране 100 раз.

Один раз слово Hello можно напечатать с помощью процедуры

  writeln('Hello');

Чтобы напечатать его 100 раз, надо эту инструкцию поместить внутрь оператора цикла, который выполнится нужное количество раз. А именно:

  for n := 1 to 100 do
  begin
    writeln('Hello');
  end;

Переменной счетчику n будет присвоено начальное значение 1. Затем Hello будет напечатано 1-й раз. Счетчик увеличится на 1 и Hello напечатается 2-й раз и т.д.

Перечислим в одном месте все правила, касающиеся работы цикла с параметром:

1) Переменная-счетчик должна быть обязательно целого типа (например, integer).

2) Начальное и конечное значения задаются выражениями, значение которых также имеет целый тип.

Нельзя, например, записать цикл

  for x := 0 to 2*Pi do …

Но можно, например:

  for k := 2*round(n*1000) to trunc(2*pi)+1 do …

3) Если конечное значение меньше начального цикл не выполнится ни разу.

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

5) Если в теле цикла содержится всего один оператор, то слова begin и end, ограничивающие тело цикла можно опустить. Такая ситуация у нас была в примере 1. Там можно было написать:

  for n := 1 to 100 do
    writeln('Hello');

6) Важное стилистическое правило: хотя это и не запрещено, не следует в теле цикла использовать какие-либо операторы, меняющие значения переменной-счетчика. В частности нельзя ей ничего присваивать. Нарушение этого правила ведет к увеличению вероятности сделать трудно обнаруживаемую ошибку. Соблюдение – никак не ограничивает ваши возможности.

7) Тело цикла может содержать любые операторы. Следовательно, туда можно поместить другой оператор цикла. Переменные-счетчики в этом случае у циклов должны быть разные. Если их сделать одинаковыми это нарушит предыдущее правило – внутренний цикл изменит значение переменной-счетчика внешнего.

8) Еще одно стилистическое правило: все операторы тела цикла должны быть дополнительно сдвинуты на 2-3 пробела вправо (см. запись программы в примере 1 и последующих примеров ниже по тексту).
Итак, одни и те же действия мы можем выполнять сколько угодно раз, но что полезного это дает? Печатать 100 раз Hello не очень важное приложение. Чтобы сделать что-то полезное, надо чтобы действия на каждом шаге цикла чем-то различались. Первый способ добиться этого состоит в использовании переменной счетчика, которая на каждом шаге принимает различные значения.

Пример 2: Напечатать все целые числа в диапазоне от 5 до 25.

  for i := 5 to 25 do
    writeln(i);

Как видно, в данном примере на каждом шаге печатаются разные числа.
Используем эту возможность для чего-то более полезного.

Пример 3: Табуляция функций.

Под табуляцией функций подразумевается составление таблицы значений функции для некоторого диапазона значений аргумента. Пусть требуется N значений функции f(x) в диапазоне от Xmin до Xmax. Рассматривая переменную-счетчик как номер аргумента функции, составим выражение, позволяющее по номеру получить значение аргумента:

x := Xmin + (Xmax — Xmin)*(i-1)/(N-1).

Убедитесь, что действительно первое значение аргумента (при i = 1) составляет x = Xmin, а N-е (i = N) – x = Xmax. Вычисляя на каждом шаге значение аргумента, можем тут же вычислить функцию и составить требуемую таблицу.

  for i := 1 to N do
  begin
    x := Xmin+(Xmax-Xmin)*(i-1)/(N-1);
    y := f(x);
    writeln(x, '  ', y);
  end;

Вместо f(x) в приведенной программе следует подставить любое выражение, составленное по правилам языка Паскаль.

Следующий раздел:

Предыдущий раздел:

9 комментариев

  1. Илья

    Заменю я впримере «Hello» на «Привет, Медвед!». Русский язык у них там настроен, пусть порадуются ;)

  2. Дмитрий

    Тарас Викторович, почему при вводе данных в программу по схеме:
    program Task3;
    var
    i:integer;
    for i:=1 to 100 do
    begin
    writeln(‘Hello’);
    end.
    в 4 строке возникает ошибка «Ожидался идентификатор, а при помещении begin на 4 строку все выполняется:
    program Task3;
    var
    i:integer;
    begin
    for i:=1 to 100 do
    writeln(‘Hello’);
    end.

  3. Taras

    После слова var идет раздел описания переменных. Там нельзя писать for i:=…
    begin как раз и показывает, что с этого места начинается исполняемая часть программы, где и пишутся все подобные команды.

  4. Денис

    Тарас Викторович! Вопрос по этой теме 3.1! Написал программу:

    var
    y,x: real;
    n,i:integer;
    begin
    writeln(‘n= ‘);
    readln (n);
    for i:= 1 to n do begin
    x := 1+(i-1)*(i-1)/(i-1);
    y := x*2;
    writeln(x, ‘ ‘, y);
    end;
    end.

    Почему в решении,Паскаль пишет ответ и вот это(NaN)? Что это?

    n=
    5
    NaN NaN
    2 4
    3 6
    4 8
    5 10

  5. Гуля

    Денис, потому что у тебя неопределенность 0/0 получается при i=1

  6. Сашок

    Спасибо! Вам Тарас!

  7. Федор

    Тарас Викторович, разве не правильней будет вычислить приращение аргумента deltaX за пределами цикла и потом в функцию подставлять X:= X+deltaX, c точки зрения быстродействия программы?

  8. Taras

    С точки зрения быстродействия, согласен.

  9. Марина

    Помогите! Напишите комментарии к каждой строке, пожалуйста!

    program coursework;
    uses crt;

    type
    massiv=array [1..100] of char;
    var
    A:massiv;
    i,j:integer;
    key:byte;

    procedure outcome(var A:massiv; var i:integer; var j:integer);
    var
    small,big:integer;
    begin
    sleep(50);
    clrscr;
    small:=0;
    big:=0;
    for i:=1 to j do
    begin
    if A[i]=upcase(A[i]) then big:=big+1
    else if A[i]=lowercase(A[i]) then small:=small+1
    else continue;
    end;
    if small>big then
    begin
    writeln(‘Больше символов малого регистра, преобразованный текст имеет вид:’);
    writeln;
    for i:=1 to j do
    begin
    if A[i]=upcase(A[i]) then begin A[i]:=lowercase(A[i]); write(A[i]); end
    else write(A[i]);
    end;
    end
    else if small<big then
    begin
    writeln('Пsfреобразованный текст имеет вид:');
    writeln;
    for i:=1 to j do
    begin
    if A[i]=lowercase(A[i]) then begin A[i]:=upcase(A[i]); write(A[i]); end
    else write(A[i]);
    end;
    end
    else
    begin
    writeln('Символов разных регистров поровну, текст остается без изминений:');
    writeln;
    for i:=1 to j do
    write(A[i]);
    end;
    end;

    procedure russ(var A:massiv; var i:integer; var j:integer);
    begin
    writeln('Введите текст:');
    writeln;
    i:=1;
    while (1=1) do
    begin
    A[i]:=readkey;
    case A[i] of
    'q': A[i]:='й';
    'w': A[i]:='ц';
    'e': A[i]:='у';
    'r': A[i]:='к';
    't': A[i]:='е';
    'y': A[i]:='н';
    'u': A[i]:='г';
    'i': A[i]:='ш';
    'o': A[i]:='щ';
    'p': A[i]:='з';
    '[': A[i]:='х';
    ']': A[i]:='ъ';
    'a': A[i]:='ф';
    's': A[i]:='ы';
    'd': A[i]:='в';
    'f': A[i]:='а';
    'g': A[i]:='п';
    'h': A[i]:='р';
    'j': A[i]:='о';
    'k': A[i]:='л';
    'l': A[i]:='д';
    ';': A[i]:='ж';
    '''': A[i]:='э';
    'z': A[i]:='я';
    'x': A[i]:='ч';
    'c': A[i]:='с';
    'v': A[i]:='м';
    'b': A[i]:='и';
    'n': A[i]:='т';
    'm': A[i]:='ь';
    ',': A[i]:='б';
    '.': A[i]:='ю';
    '/': A[i]:='.';
    'Q': A[i]:='Й';
    'W': A[i]:='Ц';
    'E': A[i]:='У';
    'R': A[i]:='К';
    'T': A[i]:='Е';
    'Y': A[i]:='Н';
    'U': A[i]:='Г';
    'I': A[i]:='Ш';
    'O': A[i]:='Щ';
    'P': A[i]:='З';
    '{': A[i]:='Х';
    '}': A[i]:='Ъ';
    'A': A[i]:='Ф';
    'S': A[i]:='Ы';
    'D': A[i]:='В';
    'F': A[i]:='А';
    'G': A[i]:='П';
    'H': A[i]:='Р';
    'J': A[i]:='О';
    'K': A[i]:='Л';
    'L': A[i]:='Д';
    ':': A[i]:='Ж';
    '"': A[i]:='Э';
    'Z': A[i]:='Я';
    'X': A[i]:='Ч';
    'C': A[i]:='С';
    'V': A[i]:='М';
    'B': A[i]:='И';
    'N': A[i]:='Т';
    'M': A[i]:='Ь';
    '’: A[i]:=’Ю’;
    ‘?’: A[i]:=’,’;
    #13: break;
    #08: begin i:=i-2; end
    else A[i]:=A[i];
    end;
    clrscr;
    writeln(‘Введите текст:’);
    writeln;
    j:=i;
    for i:=1 to j do write(A[i]);
    i:=i+1;
    end;
    end;

    procedure eng(var A:massiv; var i:integer; var j:integer);
    begin
    writeln(‘Введите текст:’);
    writeln;
    i:=1;
    while (1=1) do
    begin
    A[i]:=readkey;
    case A[i] of
    #13: break;
    #08: begin i:=i-2; end
    else A[i]:=A[i];
    end;
    clrscr;
    writeln(‘Введите текст:’);
    writeln;
    j:=i;
    for i:=1 to j do write(A[i]);
    i:=i+1;
    end;
    end;

    begin
    while (1=1) do
    begin
    writeln(‘Для ввода текста английскими символами нажмите «1», для ввода русскими — «2»:’);
    read(key);
    clrscr;
    if key=1 then begin eng(A,i,j); break; end
    else if key=2 then begin russ(A,i,j); break; end
    else begin writeln(‘Неправильно введены данные, попробуйте еще!’); writeln; continue; end;
    end;
    outcome(A,i,j);
    readln;
    readln;
    end.

Добавить комментарий