Каталог статей
Поиск по базе статей  
Статья на тему Интернет » Интересное в сети » Рекурсивные функции в&nb p;языке PHP

 

Рекурсивные функции в&nb p;языке PHP

 

 

Большинство языков программирования поддерживает рекурсивные функции, то есть такие, которые вызывают сами себя. Это весьма мощный инструмент, позволяющий создавать довольно изящные и функциональные программы, но вот используется он достаточно редко — по всей видимости, из-за его сложности для начинающих программистов и умения вызывать неприятные ошибки. Поэтому в сегодняшней заметке мы поговорим о создании и использовании рекурсивных функций в PHP.

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

загрузка...

 

 

Например, если вы напишете

function test() {
разные операторы
test();
разные операторы
}
то это и будет рекурсивная функция.

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

Одна из наиболее употребительных применений рекурсивных функций — это обход деревьев, и сегодня мы попробуем разобрать несколько примеров. Первое, что приходит в голову — это вывод многомерного массива. Разумеется, в PHP есть функция print_r(), но мы попробуем сделать результат более красивым и приспособленным для просмотра через браузер.

 function print_array($ar) {
static $count;

$count = (isset($count)) ? ++$count : 0;

$colors = array('#FFCB72', '#FFB072', '#FFE972', '#F1FF72',
 '#92FF69', '#6EF6DA', '#72D9FE');

if ($count > count($colors)) {
echo "Достигнута максимальная глубина погружения!";
$count--;
return;
}

if (!is_array($ar)) {
echo "Passed argument is not an array!<p>";
return; }

echo "<table border=1 cellpadding=0 cellspacing=0 bgcolor=$colors[$count]>";
while(list($k, $v) = each($ar)) {
echo "<tr><td>$k</td><td>$v</td></tr>\n";
if (is_array($v)) {
echo "<tr><td> </td><td>";
print_array($v);
echo "</td></tr>\n";
}
}
echo "</table>";
$count--;
}

В этой функции используется статическая переменная $count, в которой будет содержаться «глубина погружения» функции — мы будем использовать ее для того, чтобы раскрашивать вложенные массивы в разные цвета, в зависимости от глубины вложенности. Статические переменные сохраняют свое значение при выходе из функции, и использовать их при рекурсии достаточно удобно. Разумеется, с тем же успехом можно было бы передавать переменную $count в качестве параметра, но статические переменные использовать удобнее...

Массив $colors содержит список разных цветов, которые будут использоваться для раскрашивания. Заодно мы его используем для ограничения максимального уровня рекурсии — как только все цвета будут исчерпаны (проверка if ($count >= count($colors)) ), функция будет выводить сообщение о том, что достигнута максимальная глубина.

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

 if (!is_array($ar)) {
echo "Passed argument is not an array!<p>";
return;
}

Затем мы «открываем» таблицу (echo "<table border=1 cellpadding=0 cellspacing=2>";) и начинаем последовательно просматривать переданный в качестве аргумента массив. Конструкция

 while(list($k, $v) = each($ar)) {
...
}


является одним из стандартных способов пошагового прохода массива — в каждом проходе цикла переменным $k и $v присваиваются следующие значения индекса (или, как его еще называют, ключа) и значения элемента массива.

Получив пару "ключ-значение", мы выводим ее в строке таблицы:

echo "<tr><td>$k</td><td>$v</td></tr>\n";

Обратите внимание, что если значением этого элемента является массив, то будет напечатано слово «array». Теперь мы проверяем, является ли значение массивом:
if (is_array($v)) 

и если да, то печатаем (не до конца!) еще одну строку таблицы, пропуская индекс (он уже есть на предыдущей строке):
echo "<tr><td> </td><td>";

и вызываем нашу функцию печати массива, указывая в качестве аргумента вложенный массив:
print_array($v);

Затем (после того как рекурсивно вызванная функция закончит свою работу) мы «закрываем» строку таблицы (обратите внимание, что, так как наша функция печатает «полную таблицу» — от <table> до </table>, — нам не требуется вложенную таблицу закрывать — функция об этом сама позаботится, — а надо только закрыть ячейку и строку текущей таблицы).
echo "</td></tr>\n";

На этом обработка текущей пары "ключ-значение" заканчивается, и цикл while переходит к следующей паре. А когда весь массив пройден, то нам остается только закрыть таблицу:
echo "</table>";

и уменьшить значение глубины
$count--;

Рекурсивная функция не имеет представления о том, что она рекурсивнаяИз написанного выше ясно, что наша функция ничего не знает о том, вызвана она рекурсивно или нет, да ей это и безразлично — главное, чтобы в качестве аргумента был передан массив. Точно так же, при вызове самой себя для обработки вложенного массива, ей безразлично, что это рекурсивный вызов — он ничем не отличается от вызова какой-то другой функции. А заботой программиста является гарантия того, что рекурсивным вызовам где-то придет конец, то есть функция сможет закончить работу, не вызывая больше саму себя. Как только это случится, глубина вложенных вызовов начнет уменьшаться, и в конце концов функция «вынырнет на поверхность».

Результат работы подобной функции будет выглядеть примерно следующим образом (в примере максимальная глубина ограничена третьим уровнем, для наглядности добавлен вывод переменной $count, а в качестве массива для распечатки задан массив array(1, array(1.1, 1.2, 1.3), 2, 3, array(3.1, 3.2, array(3.21, 3.22, 3.23, array(3.231, 3.232), 3.24)), 4)

countkeyvalue
001
01Array
0

countkeyvalue
101.1
111.2
121.3
022
033
04Array
0

countkeyvalue
103.1
113.2
12Array
1

countkeyvalue
203.21
213.22
223.23
23Array
2 Достигнута максимальная глубина погружения!
243.24
054

Рекурсию удобно использовать для обработки файлов в директорияхРаспечатка массива редко бывает нужна «в реальной жизни», разве что для тестирования своих скриптов, но вот рекурсия может пригодиться довольно часто. Например, более жизненная потребность — обработка всех файлов в директории, включая поддиректории. Скажем, для удаления файлов удобно использовать рекурсивную функцию dd() (сокращение от Directory Delete):

 function dd($file) {
if (file_exists($file)) {
chmod($file,0777);
if (is_dir($file)) {
$handle = opendir($file);
while($filename = readdir($handle))
if ($filename != "." && $filename != "..") dd($file."/".$filename);
closedir($handle);
rmdir($file);
} else {
unlink($file);
}
}
}

Работает она по точно такому же принципу — если в качестве аргумента передан файл, то он удаляется (unlink($file);), а если директория — она открывается, последовательно просматривается, и для каждого файла (включая поддиректории) вызывается все та же функция dd()...

Еще одним примером, где рекурсивные функции использовать очень удобно, является чтение файлов по HTTP-протоколу с отслеживанием редиректов — вам надо открыть соединение, запросить файл (или только заголовок) и проверить ответ сервера — если в нем содержится заголовок

Location: xxx

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

Вот, пожалуй, и все. Надеюсь, что использование рекурсивных функций сможет пополнить ваш «арсенал программиста» еще одним мощным орудием...



Статья получена: hostinfo.ru

загрузка...

 

 

Наверх


Постоянная ссылка на статью "Рекурсивные функции в&nb p;языке PHP":


Рассказать другу

Оценка: 4.0 (голосов: 16)

Ваша оценка:

Ваш комментарий

Имя:
Сообщение:
Защитный код: включите графику
 
 



Поиск по базе статей:





Темы статей






Новые статьи

Противовирусные препараты: за и против Добро пожаловать в Армению. Знакомство с Арменией Крыша из сэндвич панелей для индивидуального строительства Возможно ли отменить договор купли-продажи квартиры, если он был уже подписан Как выбрать блеск для губ Чего боятся мужчины Как побороть страх перед неизвестностью Газон на участке своими руками Как правильно стирать шторы Как просто бросить курить

Вместе с этой статьей обычно читают:

Отчет по вебинару Zend «Web Service with PHP»

В последнее время проведение онлайновых семинаров (вебинаров, вебкастов), посвященным IT-технологиям, становится все более и более популярным явлением не только в качестве рекламы крупных софтверных компаний, но и в области Open Source проектов. Не является исключением и язык программирования PHP, по разным аспектам использования которого компания Zend, лидер разработок в области PHP, старается проводить вебинары не реже одного раза в месяц. Семинар этого месяца касался акт ...

» Продвижение и оптимизация - 2019 - читать


Рынок разработки переполнен недоучками – PHP и хорош и плох своей простотой.

24-25 мая Международный PHPCLUB совместно с корпорацией Microsoft провел шестую международную конференцию веб-разработчиков. На мероприятие собрался практически весь цвет разработчиков Рунета. За два дня успели обсудить все актуальные вопросы: - применение php в веб-разработке (приемы, методы и парадигмы программирования в php, полезные модули и библиотеки, интеграция с Ajax) - эффективное создание приложений (фреймворки, гибкие методологии, экстремальное программирование, ...

» Продвижение и оптимизация - 1626 - читать


Функции тестирования в&nb p;PHP-проектах

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

» Интересное в сети - 1852 - читать


Секреты PHP-функций для работы с&nb p;массивами. Обработка данных и&nb p;сортировка

Итак, что же там с вашим менеджером, который был упомянут в анонсе статьи? Вы уже написали ту самую злополучную версию функции для перекодировки какого-то поля в XML-файле. Но вечером того же дня оказывается, что надо срочно поменять логику работы скрипта, который уже закачан на сервер, протестирован вашим инженерным составом и одобрен чуть ли не самим генеральным директором фирмы.

» Интересное в сети - 2176 - читать


Секреты PHP-функций для работы с&nb p;массивами. Создание массивов

Основное назначение массивов — быстрая обработка данных. Часто разработчики программного обеспечения выполняют с их помощью сортирование информации, манипулирование исходными данными и получение различных выборок из наборов данных. Бытует мнение, что функциональность массивов гораздо проще организовать с помощью применения «толстой» прослойки SQL-кода и обращения к внешним приложениям типа специализированных хранилищ данных.

» Интересное в сети - 2066 - читать



Статья на тему Интернет » Интересное в сети » Рекурсивные функции в&nb p;языке PHP

Все статьи | Разделы | Поиск | Добавить статью | Контакты

© Art.Thelib.Ru, 2006-2024, при копировании материалов, прямая индексируемая ссылка на сайт обязательна.

Энциклопедия Art.Thelib.Ru