Главная страница проекта ИНФОРМАТИКА-21

Наука Школе

О структурном программировании и отсутствии GOTO

Говорить о структурном программировании, как о "программировании без GOTO" — слишком грубое упрощение. Если просто взять наивную программу с парой вложенных циклов и выходами из них с помощью GOTO и механически исключить GOTO, вводя дополнительные логические переменные, то "исправленная" программа может оказаться еще менее ясной, чем исходная.

Вот пример подобного рода программы без единого GOTO, наваянной на Компонентном Паскале энергичным (и, кстати, талантливым) программистом-самоучкой:

PROCEDURE (obj:setGuider) generate*,NEW;
    VAR exit,reset:BOOLEAN;i:INTEGER;
  BEGIN
    exit:=FALSE;reset:=FALSE;i:=LEN(obj.content)-1;
    WHILE exit=FALSE
        DO
            IF i>=0 THEN
                obj.content[i].checkFull();
                IF obj.content[i].full=FALSE THEN
                    obj.content[i].add();
                    exit:=TRUE;
                ELSE
                    reset:=TRUE;
                    obj.content[i].reset();
                    DEC(i);
                END;
                IF (reset=TRUE) & (exit=TRUE) THEN
                    obj.setMax(i);
                END;
            ELSE
                exit:=TRUE;
                obj.end:=TRUE;
            END;
        END;
END generate;

Сколько времени потребуется читателю, чтобы понять смысл фигурирующего здесь цикла WHILE?

Отметим достаточно типичное неумение пользоваться логическими выражениями: WHILE exit = false DO ... вместо просто WHILE ~exit DO ...

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

PROCEDURE ( sg: SetGuider ) Next*, NEW;
    VAR i: INTEGER; c: POINTER TO ARRAY OF Set;
BEGIN
    c := sg.content;
    i := LEN(c) - 1;
    WHILE ( i >= 0 ) & c[i].IsFull() DO
        c[i].Reset(); i := i - 1
    END;
    IF i < 0 THEN
        sg.end := TRUE
    ELSE
        c[ i ].Inc();
        IF i < LEN( c ) - 1 THEN sg.SetMax( i ) END
    END
END Next;

Здесь сразу видно, что цикл WHILE устроен по принципу поиска в массиве первого с конца элемента, не обладающего свойством c[i].IsFull():

    ПОКА (не вышли из массива) И (текущий элемент не удовлетворяет условию поиска) ДЕЛАТЬ ..,

а оператор IF в конце — стандартный обработчик двух возможных состояний после выхода из цикла:

    ЕСЛИ (вышли из массива, т.е. дошли до конца, не найдя элемента) ТО ...

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

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

Назад на страничку о GOTO

Главная страница проекта ИНФОРМАТИКА-21

Наука Школе