Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Котеров Д. В., Костарев А. Ф. - PHP 5. 2-е издание (В подлиннике) - 2008

.pdf
Скачиваний:
6114
Добавлен:
29.02.2016
Размер:
11.36 Mб
Скачать

284

Часть IV. Стандартные функции PHP

тему, перебирая пароли с бешеной скоростью, алгоритм MD5 работает довольно медленно. И его нельзя никак ускорить, потому что это будет уже не MD5. Так что даже на самых мощных компьютерах вряд ли получится перебирать более нескольких тысяч паролей в секунду, а это совсем маленькая скорость, капля в океане возможных MD5-кодов.

В августе 2004 группа китайских ученых провела исследования, ставящие под сомнение надежность алгоритма MD5 в некоторых приложениях. Было показано, что если известен MD5-код некоторой строки и сама эта строка, то за разумное время можно найти другую строку, имеющую тот же самый хэш-код. Если же исходная строка неизвестна (как, например, в случаем с базой данных паролей), MD5-код по-прежнему надежен.

int crc32(string $st)

Функция crc32() вычисляет 32-битную контрольную сумму строки $st. То есть, результат ее работы — 32-битное (4-байтовое) целое число. Эта функция работает быстрее md5(), но в то же время выдает гораздо менее надежные хэш-коды для строки. Так что теперь, чтобы получить методом случайного подбора для двух разных строк одинаковые хэш-коды, вам потребуется не триллион лет работы самого мощного компьютера, а всего лишь... год-другой. Впрочем, если не использовать генератор случайных чисел, а разобраться в алгоритме вычисления 32-битной контрольной суммы, эту же задачу легко можно решить буквально за секунду, потому что алгоритм crc32 имеет бо´льшую предсказуемость, чем MD5.

string crypt(string $st [,string $salt])

Алгоритм шифрования DES до недавнего времени был стандартным для всех версий Unix и использовался как раз для кодирования паролей пользователей (тем же самым способом, о котором мы говорили при рассмотрении функции md5()). Но в последнее время MD5 постепенно начал его вытеснять. Это и понятно: алгоритм MD5 гораздо более надежен. Рекомендуем и вам везде применять md5() вместо crypt().

Впрочем, функция crypt() все же может понадобиться в одном случае: если вы хотите сгенерировать хэш-код для другой программы, которая использует именно алгоритм DES (например, для сервера Apache).

Хэш-код для одной и той же строки, но с различными значениями $salt (кстати, это должна быть обязательно двухсимвольная строка) дает разные результаты. Если параметр $salt пропущен, PHP сгенерирует его случайным образом, так что не удивляйтесь работе следующего примера:

$st = "This is the test";

echo crypt($st)."<br>"; // можем получить, например, 7N8JKLKbBWEhg echo crypt($st)."<br>"; // а здесь появится, например, Jsk746pawBOA2

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

Глава 15. Строковые функции

285

Сброс буфера вывода

void flush()

Эта функция имеет очень и очень отдаленное отношение к работе со строками, но она еще дальше отстоит от других функций. Именно поэтому мы включили ее в данную главу. Начнем издалека: обычно при использовании echo данные не прямо сразу отправляются клиенту, а накапливаются в специальном буфере, чтобы потом транспортироваться большой "пачкой". Так получается быстрее. Однако иногда бывает нужно досрочно отправить все данные из буфера пользователю, например, если вы что-то выводите в реальном времени (так зачастую работают чаты). Вот тут-то вам и поможет функция flush(), которая отправляет содержимое буфера echo в браузер пользователя.

Резюме

В данной главе мы рассмотрели большинство основных функций PHP для работы со строками. Мы научились производить поиск и замену (самая популярная операция в Web-программировании), преобразовывать тексты в разные кодировки, а также использовать локаль (локальные настройки) для корректной работы в Unix. В главе также описаны функции для форматирования больших блоков текста: удаление и "экранирование" тегов, разбиение текста на строки, получение хэш-кода.

ГЛАВА 16

Работа с массивами

Листинги данной главы можно найти в подкаталоге funcarr.

В части III книги мы уже рассматривали многие возможности, которые предостав-

ляет PHP для работы с ассоциативными массивами. В их число входят различные

механизмы перебора, получение числа элементов, оперирование ключами и значениями и т. д.

Однако здесь перечислено далеко не все, что можно делать с массивами в PHP.

Язык (особенно версий 4 и 5) содержит множество других, иногда крайне полезных, функций. В этой главе мы рассмотрим большинство из них.

Лексикографическая и числовая сортировки

Так как в PHP основными примитивными типами являются число и строка, существуют два метода сортировки:

лексикографическое упорядочивание: сортировка по алфавиту. Именно так сортируются слова в толковом или иностранном словаре;

числовое упорядочивание: сортировка по возрастанию (или убыванию).

С точки зрения лексикографической сортировки последовательность строк "1", "10",

"2" корректно упорядочена по возрастанию, в то время как при числовой сортировке порядок должен быть, конечно же, таким: 1, 2, 10.

По умолчанию все функции сортировки, имеющиеся в PHP, выбирают один из мето-

дов самостоятельно. Если сравниваемые значения представляют собой числа (или строки, содержащие числа), то они сравниваются в числовом контексте, в против-

ном случае — в лексикографическом. Тем не менее существует способ явно указать, что тот или иной массив следует сортировать конкретным методом. Для этого предназначен необязательный параметр $sort_flag (далее мы его все время будем приво-

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

SORT_REGULAR — автоматический выбор метода;

SORT_NUMERIC — числовая сортировка;

SORT_STRING — лексикографическая сортировка. По умолчанию подразумевается SORT_REGULAR.

Глава 16. Работа с массивами

287

Сортировка произвольных массивов

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

горассудится — посредством пользовательской функции сортировки.

Сортировка по значениям

void asort(array &$array [,int $sort_flag])

void arsort(array &$array [,int $sort_flag])

Функция asort() сортирует массив, указанный в ее параметре, так, чтобы его значения располагались в алфавитном (если это строки) или в возрастающем (для чисел)

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

чениями, т. е. некоторые пары ключ=>значение просто "всплывают" наверх, а некото-

рые — наоборот, "опускаются". Пример — в листинге 16.1.

Листинг 16.1. Файл asort.php

<?php ## Сортировка массива по значениям. $tools = array(

"a" => "Zero", "b" => "Weapon", "c" => "Alpha", "d" => "Processor"

); asort($tools); print_r($tools);

//Array([c]=>Alpha [d]=>Processor [b]=>Weapon [a]=>Zero)

//как видим, поменялся только порядок пар ключ=>значение

?>

Функция arsort() выполняет то же самое, однако упорядочивает массив не по воз-

растанию, а по убыванию.

Параметр $sort_flag здесь и далее имеет один и тот же смысл, который упоминался в разд. "Лексикографическая и числовая сортировки" ранее в этой главе.

Сортировка по ключам

void ksort(array &$array [,int $sort_flag])

void krsort(array &$array [,int $sort_flag])

Функция ksort() практически идентична функции asort(), с тем различием, что сортировка осуществляется не по значениям, а по ключам (в порядке возрастания).

Пример — в листинге 16.2.

288

Часть IV. Стандартные функции PHP

Листинг 16.2. Файл ksort.php

<?php ## Сортировка массива по ключам. $tools = array(

"c" => "Alpha", "a" => "Zero",

"d" => "Processor", "b" => "Weapon",

); ksort($tools); print_r($tools);

// Array([a]=>Zero [b]=>Weapon [c]=>Alpha [d]=>Processor) ?>

Функция для сортировки по ключам в обратном порядке называется krsort() и

применяется точно в таком же контексте, что и ksort().

Пользовательская сортировка по ключам

void uksort(array &$array, string $callback)

Довольно часто нам приходится сортировать что-то по более сложному критерию,

чем просто по алфавиту. Например, пусть в $files хранится список имен файлов и подкаталогов в текущем каталоге. Возможно, мы захотим вывести этот список не

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

того требует uksort() (листинг 16.3).

Листинг 16.3. Файл uksort.php

<?php ## Пользовательская сортировка по ключам.

//Эта функция должна сравнивать значения $f1 и $f2 (имена

//файлов или каталогов) и возвращать:

//-1, если $f1 < $f2,

//0, если $f1 == $f2

//1, если $f1 > $f2

//Под < и > понимается следование этих имен в выводимом списке function fCmp($f1, $f2) {

// Каталог всегда предшествует файлу

if (is_dir($f1) && !is_dir($f2)) return -1; // Файл всегда идет после каталога

if (!is_dir($f1) && is_dir($f2)) return 1; // Иначе сравниваем лексикографически

if ($f1<$f2) return -1; elseif ($f1>$f2) return 1; else return 0;

}

//Записываем в $files содержимое текущего каталога:

//массив с ключами — именами файлов и значениями — их размером. $d = opendir(".");

while (false !== ($e=readdir($d))) $files[$e] = filesize($e);

Глава 16. Работа с массивами

289

// Сортируем его и печатаем.

uksort($files, "fCmp"); // передаем имя функции

print_r($files);

?>

Забегая вперед, заметим, что функции opendir() и readdir() предназначены для чте-

ния имен файлов и подкаталогов в некотором каталоге. Мы используем их для заполнения массива $files так, чтобы в его ключах находились имена файлов, а в значениях — их размеры.

Конечно, связи между ключами и значениями функции uksort() сохраняются, т. е. опять же некоторые пары просто "всплывают" наверх, а другие — "оседают".

Пользовательская сортировка по значениям

void uasort(array &$array, string $callback)

Функция uasort() очень похожа на uksort(), с той разницей, что сменной (пользовательской) функции сортировки "подсовываются" не ключи, а очередные значения их массива. При этом также сохраняются связи в парах ключ=>значение.

Переворачивание массива

array array_reverse(array $array [,bool $preserveKeys=false])

Функция array_reverse() возвращает массив, элементы которого следуют в обратном порядке относительно массива, переданного в параметре. При этом связи между ключами и значениями не теряются. Например, вместо того чтобы ранжировать массив в обратном порядке при помощи arsort(), мы можем отсортировать его

в прямом порядке, а затем перевернуть (листинг 16.4).

Листинг 16.4. Файл array_reverse.php

<?php ## Переворачивание массива. $tools = array(

"a" => "Zero", "b" => "Weapon", "c" => "Alpha", "d" => "Processor"

); asort($tools);

$tools = array_reverse($tools); print_r($tools);

// Array([a]=>Zero [b]=>Weapon [d]=>Processor [c]=>Alpha) ?>

Конечно, указанная последовательность asort()+array_reverse() работает дольше,

чем один-единственный вызов arsort().

Если положить необязательный параметр $preserveKeys равным true, тогда перево-

рачиваться будут только значения, а ключи останутся в прежнем порядке. Связи

между ключами и значениями массива в данном случае, конечно, нарушатся. Это

290

Часть IV. Стандартные функции PHP

удобно, если мы работаем со списком, а не с произвольным ассоциативным мас-

сивом.

"Естественная" сортировка

Предположим, что в списке $files у нас хранятся имена файлов в некотором каталоге. Мы хотели бы их упорядочить по возрастанию (листинг 16.5).

Листинг 16.5. Файл natsort.php

<?php ## Естественная сортировка. $files = array(

"img10.gif",

"img1.gif",

"img2.gif",

"img20.gif",

); asort($files);

//natsort($files);

echo "<pre>"; print_r($files); echo "</pre>"; ?>

Мы увидим следующий результат:

Array

(

[1]=> img1.gif

[0]=> img10.gif

[2]=> img2.gif

[3]=> img20.gif

)

В большинстве случаев это не то, что мы хотели бы видеть — действительно, имена

оказались упорядочены в лексикографическом порядке, что в данном примере не

очень наглядно. В то же время, применять числовой контекст сортировки (SORT_NUMERIC) здесь нельзя: ведь список содержит не только числа.

Специально для решения данной проблемы в PHP существует функция естествен-

ной (натуральной) сортировки.

void natsort(array &$array)

Функция сортирует массив так, чтобы порядок элементов казался человеку "естест-

венным" (от англ. natural — естественный). Например, если вы раскомментируете в листинге 16.5 вызов natsort() (и уберете asort()), то увидите, что после сортиров-

ки результат будет таким:

Array

(

[1]=> img1.gif

[2]=> img2.gif

Глава 16. Работа с массивами

291

[0] => img10.gif

[3] => img20.gif

)

Согласитесь, результат выглядит значительно "естественнее", чем в предыдущем примере.

Обратите внимание, что функция natsort() сохраняет связи между ключами и значениями, и этим она очень похожа на asort().

void natcasesort(array &$array)

Данная функция работает точно так же, как natsort(), однако при сортировке она

не учитывает регистр букв.

Сортировка списков

Ранее мы договорились называть списками такие массивы, ключи которых начина-

ются с 0 и идут без перерывов. Некоторые стандартные функции PHP воспринимают свои аргументы как списки, даже если им будут переданы ассоциативные масси-

вы (не списки). То есть, они полностью игнорируют ключи и полагаются исключи-

тельно на порядок элементов в массиве.

Сортировка списка

void sort(array &$array [,int $sort_flag])

void rsort(array &$array [,int $sort_flag])

Обе функции предназначены в первую очередь для сортировки списков. Функция sort() сортирует список в порядке возрастания, а rsort() — в порядке убывания.

Разумеется, сортировка идет по значениям. Пример — в листинге 16.6.

Листинг 16.6. Файл sort.php

<?php ## Сортировка списков.

$numbers = array("One", "Two", "Three", "Four"); sort($numbers);

print_r($numbers);

// Array([0]=>Four [1]=>One [2]=>Three [3]=>Two) ?>

Давайте теперь посмотрим, что произойдет, если мы передадим функции sort() не

список, а обычный ассоциативный массив (листинг 16.7).

Листинг 16.7. Файл sort1.php

<?php ## Сортировка списков (случай ассоциативного массива).

$numbers = array(

292

Часть IV. Стандартные функции PHP

"a" => "Zero", "b" => "Weapon", "c" => "Alpha", "d" => "Processor"

); sort($numbers); print_r($numbers);

// Array([0]=>Alpha [1]=>Processor [2]=>Weapon [3]=>Zero) ?>

Мы видим, что ключи массива потерялись! Любой ассоциативный массив воспринимается функциями sort() и rsort() как список. То есть после упорядочивания последовательность ключей превращается в 0, 1, 2, ..., а значения нужным образом перераспределяются. Связи между парами ключ=>значение не сохраняются, более того — ключи просто пропадают, поэтому сортировать что-либо, отличное от списка, вряд ли целесообразно.

Пользовательская сортировка списка

void usort(array &$array, string $callback)

Эта функция как бы является "гибридом" функций uasort() и sort(). От sort() она отличается тем, что критерий сравнения обеспечивается пользовательской функцией. А от uasort() — тем, что она не сохраняет связей между ключами и значениями и потому пригодна разве что для сортировки списков. Вот тривиальный пример (листинг 16.8).

Листинг 16.8. Файл usort.php

<?php ## Пользовательская сортировка списков. function fCmp($a, $b) { return strcmp($a, $b); } $tools = array("One", "Two", "Three", "Four"); usort($tools, "fCmp");

print_r($tools);

// Array([0]=>Four [1]=>One [2]=>Three [3]=>Two) ?>

Использованная нами функция strcmp($a, $b), как и ее пращур в языке C, возвращает 1, если $a<$b; 0, если они равны; 1, если $a>$b. В принципе, приведенный

здесь пример полностью эквивалентен простому вызову sort().

Перемешивание списка

void shuffle(array &$array)

Функция shuffle() "перемешивает" список, переданный ей первым параметром, так, чтобы его значения распределялись случайным образом. Обратите внимание, что,

во-первых, изменяется сам массив, а во-вторых, ассоциативные массивы восприни-

маются как списки. Пример — в листинге 16.9.

Глава 16. Работа с массивами

293

Листинг 16.9. Файл shuffle.php

<?php ## Перемешивание списка.

$concept = array("Banana", "Coffee", "Ice cream", "Throat"); shuffle($concept);

print_r($concept); ?>

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

Ключи и значения

array array_flip(array $array)

Эта функция "пробегает" по массиву и меняет местами его ключи и значения. Исходный массив $array не изменяется, вместо этого функция возвращает новый массив. Если в массиве присутствовали несколько элементов с одинаковыми значениями, учитываться будет только последний из них (листинг 16.10).

Листинг 16.10. Файл array_flip.php

<?php ## Обращение массива. $names = array(

"Joel" => "Silver", "Grant" => "Hill", "Andrew" => "Mason",

);

$names = array_flip($names); print_r($names);

// Array([Silver]=>Joel [Hill]=>Grant [Mason]=>Andrew) ?>

list array_keys(array $array [,mixed $searchVal])

Функция возвращает список, содержащий все ключи массива $array. Если задан необязательный параметр $searchVal, то она вернет только те ключи, которым соответ-

ствуют значения $searchVal.

Фактически эта функция с заданным вторым параметром является обратной по отношению к оператору [] — извлечению значения по его ключу.

list array_values(array $arrray)

Функция array_values() возвращает список всех значений в ассоциативном массиве $array. Очевидно, такое действие бесполезно для списков, но иногда оправдано для

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

жем написать следующий оператор:

Тут вы можете оставить комментарий к выбранному абзацу или сообщить об ошибке.

Оставленные комментарии видны всем.