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

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

7. Переменные-флаги

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

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

7.1. Переменные-флаги: теория

Флаг – это полотнище правильной (как правило, прямоугольной) формы прикрепленное к древку или поднимаемое на специальной мачте (флагштоке). Исторически флаги появились для передачи простых сигналов на поле боя. Например: подняли флаг, и конница понеслась в атаку! Как-то так. В простейшем случае с помощью флага передается информация объемом 1 бит (одно из двух: флаг поднят или нет).

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

1) Подводится баланс коммерческого предприятия. Дальнейшие действия могут зависеть от того, будет он положительным или отрицательным. Если отрицательный, надо просить кредит, положительный – планировать отдых на Багамах. В общем, самая существенная информация может быть передана одним битом.

2) Решаем квадратное уравнение. Если дискриминант не отрицательный – ищем корни. Для хода вычислительного важен факт не отрицательности, который также содержит 1 бит информации и может, таким образом, быть сохранен с помощью логической переменной.

3) Детям на уроке физкультуры велено построиться по росту. Если они построились не по росту, надо на них наорать. Опять действия учителя зависят от информации объемом 1 бит.

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

Пример 1. Решение квадратного уравнения.

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

  var
    a, b, c: real;	{Коэффициенты уравнения  }
    d: real;	{Дискриминант}
    x1, x2: real;	{Корни}
    RootsExist: boolean;	{Переменая-флаг}
  begin
    {Блок, написанный первым программистом}
    readln(a, b, c);
    d := sqr(b)-4*a*c;
    RootsExist := (d>=0); {Флаг служит для хранения 
                           информации о наличии корней}
    if RootsExist then
    begin
      x1:=(-b+sqrt(d))/(2*a);
      x2:=(-b-sqrt(d))/(2*a);
    end;
    {Блок, написанный вторым программистом}
    if RootsExist then
      writeln(x1, x2)
    else
      writeln('Roots don’t exist');
  end.

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

  if RootsExist then

не написать

  if d>=0 then

Зачем использовать еще одну переменную? Давайте вспомним, что второй программист ничего не знает о квадратных уравнениях и в частности не в курсе, что наличие корней определяется знаком дискриминанта. Не вдаваясь в тонкости чужой задачи, он просто просит первого программиста передать существенную информацию, через переменную-флаг.

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

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

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

В дополнение еще один пример.

Пример 2. Проверка упорядоченности последовательности.

Пользователь вводит 10 чисел. Требуется проверить, упорядочены ли они по возрастанию, и передать эту информацию с помощью переменной флага.

Решение:

  Growing:=true;	{Переменная флаг}
  readln(x);
  for i:=2 to 10 do
  begin
    x2:=x;
    readln(x);
    Growing:=Growing and (x > x2);
  end;

Если очередное введенное число (x) будет меньше предыдущего (x2), то флаг примет значение false и сохранит это значение до конца цикла.

Блоки, передающие друг другу информацию с помощью флагов, не обязательно должны идти последовательно друг за другом. Можно представить себе ситуацию, когда один блок является составной частью другого. Например:

Пример 3: Найти все простые числа от 1 до N.

Число называется простым, если не делится ни на какое другое число кроме 1 и самого себя. Простейший алгоритм поиска таких чисел состоит в том, чтобы перебрать все числа и для каждого проверить наличие делителей. Поиск делителей можно мыслить себе как отдельный блок программы, результатом работы которого будет присваивание значения флаговой переменной.
Блок поиска простых чисел будет включать в себя блок проверки на наличие делителей.
Программную реализацию этого алгоритма выполните в качестве самостоятельного упражнения (см. задачу 7.1).

Не обязательно использовать в качестве флага именно логическую переменную. В принципе флагом может считаться любая переменная, принимающая небольшое количество возможных значений, каждое из которых характеризует тот или иной результат вычислительного процесса.
В примере с квадратным уравнением можно было бы предусмотреть еще одну ситуацию, когда a = 0, то есть уравнение не квадратное. Тогда для передачи информации в следующий блок можно использовать либо две переменные логического типа, либо одну, но принимающую три значения (в качестве таковой можно использовать, например, переменную целого типа).

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

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

3 комментария

  1. Александр

    Во втором примере ошибка, я думаю.
    Growing:=Growing and (x > x2) должно быть, разве нет?

  2. Taras

    Спасибо, исправил.

  3. Ruslan

    Ничего не понял.

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