Руководство разработчика

Цикл ИНДЕКС

Цикл перебора элементов контейнерных переменных (цикл ИНДЕКС) предназначен для последовательного получения значений элементов и соответствующих им значений индексов, содержащихся в контейнерной переменной.

Синтаксис:

ЦИКЛ ИНДЕКС ( <переменная значения> = [КОНСТ]
              <контейнерная переменная или поле> [<переменная-индекс1> [, …] ] )
  <операторы секции цикла>
КОНЕЦ_ЦИКЛА

Количество переменных-индексов должно соответствовать размерности контейнерной переменной. Переменная значения и переменные-индексы последовательно принимают значения, соответствующие элементам контейнерной переменной.

Указание ключевого слова КОНСТ после знака равенства и перед контейнерным значением позволяет ускорить выполнение цикла за счет того, что контейнерное значение рассматривается как неизменяемое в теле цикла. По умолчанию считается, что значение может изменяться, что приводит к дополнительному копированию и проверкам. Если ключевое слово КОНСТ указано, но в теле цикла прямо или опосредованно происходит изменение контейнерного значения, то возможно проявление различных артефактов поведения. Следует избегать такой практики и указывать ключевое слово КОНСТ только в тех циклах, где осуществляется доступ к перебираемому контейнерному значению исключительно на чтение.

Пример:

ВЫЧИСЛИТЬ
  // определим двумерную контейнерную переменную,
  // которая содержит три элемента
  ПЕРЕМ СТРОКА: ип[ЧИСЛО,СТРОКА] = 
  (
  1, "И": "Иванов",
  2, "П": "Петров",
  3, "С": "Сидоров"
  )
  // перебираем элементы в цикле
  // переменные фамилия, номер и буква принимают значения,
  // соответствующие элементам контейнерной переменной ип
  ЦИКЛ ИНДЕКС (фамилия = ип[номер, буква])
    СООБЩЕНИЕ(СТР(номер) + ", " + буква + " : " + фамилия)
  КОНЕЦ_ЦИКЛА
КОНЕЦ

Помимо стандартного перебора значений, цикл ИНДЕКС предоставляет следующие возможности:

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

Синтаксис:

ЦИКЛ ИНДЕКС (* = <контейнерная переменная> [ <индексы> ])

То есть звездочка на месте элемента указывает на то, что при переборе нам не нужны его значения. Аналогично могут быть проигнорированы значения индексов (одного, нескольких или всех).

ПЕРЕМ СТРОКА: а[ЧИСЛО,ЧИСЛО] = ( 1, 1: "А", 2, 2: "Б" )
ЦИКЛ ИНДЕКС (стр = а[*,*]) // значения индексов нам не нужны
  ОТЛАДКА(стр)
КОНЕЦ_ЦИКЛА

Результат: А Б

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

Тип константы или выражения должен соответствовать типу индекса.

Пример:

ПЕРЕМ СТРОКА: а[ЧИСЛО,ЧИСЛО] = ( 1, 1: "А", 1, 2: "Б", 2, 1: "В", 2, 2: "Г" )
ЦИКЛ ИНДЕКС (стр = a[ 1, и2 ]) // первый индекс зафиксирован равным 1 
  ОТЛАДКА(стр)
КОНЕЦ_ЦИКЛА
ОТЛАДКА("---")
и2 = 2 
ЦИКЛ ИНДЕКС (стр = a[ и1, КОНСТ и2 ]) // второй индекс зафиксирован равным и2
  ОТЛАДКА(стр)
КОНЕЦ_ЦИКЛА

Результат: А Б --- Б Г

Для управления итерациями цикла используются ключевые слова ПРОДОЛЖИТЬ и ПОВТОР. ПРОДОЛЖИТЬ переходит к следующей итерации цикла без выполнения нижеследующих операторов тела цикла. ПОВТОР повторно выполняет текущую итерацию цикла., т.е. управление передается от ключевого слова ПОВТОР в начало цикла. Цикл ИНДЕКС корректно поддерживает модификацию контейнерного значения в процессе его перебора даже в случае вложенных циклов ИНДЕКС по одному индексному значению. Наиболее важной задачей, где совместно применяются перебор и модификация, является удаление некоторых элементов контейнерного значения. В случае удаления текущего элемента возникает неопределенность с новым текущим элементом. Логика перебора в этом случае зависит от природы последнего индекса: ассоциативный или последовательный. Тем не менее, ключевое слово ПОВТОР позволяет создать инвариатный алгоритм, корректно работающий в обоих случаях:

ЦИКЛ ИНДЕКС (стр = a[ и1, и2 ])
  ЕСЛИ НадоУдалять(стр, и1, и2) ТО // функция принимает решение об удалении 
    ЕСЛИ ^а[ и1, и2 ] ТО // если успешно удален 
      ПОВТОР // если здесь не вернемся в начало цикла,
      // то пропустим следующий за удаленным элемент
    КОНЕЦ_ЕСЛИ
    КОНЕЦ_ЕСЛИ 
КОНЕЦ_ЦИКЛА

См. также: