Выбрать главу

Цикл while

Наиболее примитивной циклической конструкцией во многих языках программирования является цикл while (англ. пока). Цикл while, как правило, имеет следующий вид:

пока

 верно условие

выполнять

 действия

В качестве примера while-цикла напишем на языке Java программу вычисления факториала в итеративном стиле:

int factorial(int n) {

 int i = n;

 int result = 1;

 while (i != 0) {

  result = result * i;

  i--;

 }

 return result;

}

В этой функции условием является отличие значения переменной i от 0, а действиями — умножение значения переменной result на значение переменной i, и уменьшение значения этой переменной на 1.

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

пока

 верно условие(x1,x2, ...,xn)

выполнить

 x1' := функция1(x1,x2,...,xn)

 х2' := функция2(x1,x2,...,xn)

 ...

 xn' := функцияn(x1,x2,...,xn)

 действия(x1,x2,...,хn)

 x1 := x1'

 x2 := x2'

 ...

 xn := xn'

иначе

 вернуть результат(x1,...,хn)

Переопределение значений переменных x1, … , хn в этом случае выполняют n функций: функция1 …, функцияn. И если изменить значение переменной мы не могли, переопределить связанное с ней значение мы вполне в состоянии, добавив в контекст новый параметр или переменную с тем же именем.

Теперь мы можем записать весь цикл while как одну рекурсию:

while(x1, ..., xn) ::=

 если

  выполняется условие(x1, ..., xn)

 то

  действия(x1, ..., хn)

  while(функция1(x1, ..., хn),

   функция2(x1, ..., хn),

   ...,

   функцияn(x1, ..., xn))

 иначе

  результат(x1, ..., хn)

Теперь уже совершенно очевидно, как while-цикл должен выглядеть в преобразовании.

Листинг 11.10. Шаблон цикла while в общем виде

<xsclass="underline" template name="while">

 <xsclass="underline" param name="x1"/>

 <!-- ... -->

 <xsclass="underline" param name="xn"/>

 <xsclass="underline" choose>

  <xsclass="underline" when test="условие($x1,...,$xn)">

   <!-- Действия -->

   <xsclass="underline" call-template name="while">

    <xsclass="underline" with-param name="x1" select="функция_1($x1, ... $xn) "/>

    <!-- ... -->

    <xsclass="underline" with-param name="xn" select="функция_n($x1, ... $xn) "/>

   </xsclass="underline" call-template>

  </xsclass="underline" when>

  <xsclass="underline" otherwise>

   <xsclass="underline" value-of select="результат($x1, ..., $xn)"/>

  </xsclass="underline" otherwise>

 </xsclass="underline" choose>

</xsclass="underline" template>

В качестве примера приведем while-цикл для программы, вычисляющей факториал. Java-код был следующим:

while (i != 0) {

 result = result * i;

 i--;

}

В этом цикле участвуют две переменные — i и result. Функции, использующиеся в этом цикле, запишутся следующим образом:

условие($1, $result)      ::= ($i != 0)

функцияi($i, $result)     ::= ($i - 1)

функцияresult($i, $result) ::= ($i * $result)

результат($I, $result)    ::= ($result)

Именованный шаблон для этого случая будет иметь вид.

Листинг 11.11. Пример шаблона цикла while

<xsclass="underline" template name="while">

 <xsclass="underline" param name="i"/>

 <xsclass="underline" param name="result"/>

 <xsclass="underline" choose>

  <xsclass="underline" when test="$i != 0">

   <xsclass="underline" call-template name="while">

    <xsclass="underline" with-param name="i" select="$i — 1"/>

    <xsclass="underline" with-param name="result" select="$result * $i"/>

   </xsclass="underline" call-template>

  </xsclass="underline" when>

  <xsclass="underline" otherwise>

   <xsclass="underline" value-of select="$result"/>

  </xsclass="underline" otherwise>

 </xsclass="underline" choose>

</xsclass="underline" template>

Вызвать этот шаблон можно следующим образом:

<xsclass="underline" template match="/">

 <xsclass="underline" call-template name="while">

  <xsclass="underline" with-param name="i" select="6"/>

  <xsclass="underline" with-param name="result" select="1"/>

 </xsclass="underline" call-template>

</xsclass="underline" template>

Результатом будет, естественно, число 720.

Цикл for

Частным случаем цикла while является цикл for. В разных языках программирования for имеет различную семантику; мы будем рассматривать циклы for вида

for (int i = 0; i < n; i++) { ... }

в языках Java и С или

for i := 0 to n-1 do begin ... end;

в Pascal. Иными словами, нас будет интересовать циклическое выполнение определенных действий при изменении значения некоторой переменной (называемой иногда индексом цикла) в интервале целых чисел от 0 до n включительно.

Цикл for может быть определен через while с использованием следующих условных и изменяющих функций: