САМОУЧИТЕЛЬ PHP 4

       

Пример функции


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

Листинг 11.1. Пример функции

function GetMaxNum($arr, $max="")

{ // проходимся по всем элементам массива

  for($i=0,$n=-1; $i<count($arr); $i++) {

    // если этот элемент нам пока подходит, запоминаем его

    if((!Isset($m) || $arr[$i]>$m) && ($max==="" || $arr[$i]<$max)) {

      // сюда мы попадаем, когда очередной элемент больше текущего,

      // либо же текущего элемента еще не существует (первый проход)

      $m=$arr[$i]; // запоминаем текущий элемент

      $n=$i;       // запоминаем его номер

    }

  }



  return $n;

}

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

echo "Программа...";

function GetMaxNum($arr,$max)

{ ... тело функции ...

}

echo "Программа продолжается!";

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

Итак, мы создали функцию с именем GetMaxNum() и двумя параметрами, первый из которых рассматривается ей как массив, а второй — как вещественное число.

На самом деле на этапе создания функции еще никаких предположений о типах параметров не строится. Однако попробуйте нашей функции вместо массива в первом аргументе передать число — интерпретатор "заругается", как только выполнение дойдет до строчки с $arr[$i], и скажет, что "переменная не является массивом".[E50] 


Алгоритм работы функции таков: в цикле анализируем очередной элемент на предмет "максимальности": если он больше текущего максимального элемента, но меньше $max, он сам становится текущим максимумом, а его положение запоминается в $n. (Обратите внимание, что в описании функции параметр $max задается в виде $max="". Ýто означает, что если при вызове он будет опущен, то функция получит пустую строку в $max.)
После окончания цикла в $n окажется номер такого элемента (либо число -1, которое мы присвоили $n в начале). Его-то мы и возвращаем в качестве значения функции оператором return.
Ну вот, теперь в программе ниже описания функции можно написать:
$a=array(10,20,80,35,22,57);
$m=GetMaxNum($a,50);  // теперь $m=3, ò. å. $a[$m]=35

В действительности, поскольку фаза трансляции и исполнения в PHP разделены, мы можем применять вызовы функции еще до того, как она была описана. Однако это работает, конечно же, только в том случае, когда в момент интерпретации вызова функции ее код будет уже оттранслирован (например, вызов и описание функции происходят в одном и том же файле). Тем не менее, не советую вам злоупотреблять данной возможностью — лучше всегда поступать так, как это принято в Паскале: вызывать функции только после того, как они будут определены.
Зачем может понадобиться функция GetMaxNum() в реальной жизни? Например, для сортировки массива в порядке убывания с одновременным получением уникальных элементов. Конечно, это будет очень неоптимальный алгоритм, но для тренировочных целей он нам вполне подойдет (листинг 11.2):
Листинг 11.2. Сортировка с применением GetMaxNum()
function MySort($Arr)
{ $m= GetMaxNum($Arr)+1; // число, на 1 большее максимума в массиве
  while(($n=GetMaxNum($Arr,$m))!=-1)
    $New[]=$m=$Arr[$n];  // добавляем очередной максимальный элемент
  return $New;
}
// Пример вызова:
$Sorted=MySort(array(1,2,5,2,4,7,3,7,8));
// Теперь $Sorted===array(8,7,5,4,3,2,1)
Приведенная функция не изменяет исходный массив, а возвращает новый. В силу устройства функции GetMaxNum()
в результирующий массив будут помещены только уникальные элементы из $Arr, отсортированные в порядке убывания.

Функцию MySort()
можно ускорить примерно в 2 раза, если после каждой итерации удалять из массива $Arr обработанный элемент при помощи Unset(). Впрочем, это не так интересно, как может показаться.

Содержание раздела