Повторим?

Ну что, читатель, если ты прошел огонь, воду и медные трубы предыдущих уроков, решил хотя бы половину задач, у меня для тебя есть хорошая новость: ты способен программировать на языке PHP. Конечно, пока идти писать серьезные приложения или сайты тебе рано, так как у тебя не хватает нужных знаний, но это не беда. Проходи этот курс дальше, делай задания и все у тебя получится.

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

Поскольку это последний урок на 1-м уровне, сегодня мы будем повторять старый материал, изучим чуть-чуть нового и порешаем задачки. Решивший их автоматически переходит на 2-й левел, не решивший — решает дальше!

Комментарии

Кроме привычных тебе по предыдущим урокам комментариев вида /* ... */, в PHP есть еще 2 способа их записи:

Комментарии в PHP

Для однострочных комментариев используют обычно «//», а не «#». Поэтому не используй символ решетки для комментариев. И, кстати, не перепутай прямой и обратный слеши:

Прямой и обратный слеш

Циклы

Ты, наверно, помнишь 2 способа организовать цикл:

Циклы for и foreach

Надеюсь, ты не забыл, что в условиях при сравнении используют не «=», а «==»?

Сравнение и присваивание

Кроме них, есть еще цикл

while (условие) { ...действия.... }

и do { ... действия ... } while (условие);

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

Цикл while

Кажется, что цикл while можно использовать вместо for, увеличивая переменную в теле цикла, но делать так не стоит. Если у тебя в цикле увеличивается счетчик, используй именно for (так как иначе опытные программисты на тебя обидятся). Так как почти в любом цикле что-то увеличивается или уменьшается, цикл while используется нечасто.

Если ты используешь цикл для обхода массива, и пишешь for ($i = 0; $i < count($array); $i++) { .. } — знай, ты не прав. Чтобы обойти все элементы массива, надо использовать foreach, он специально для этого и придуман.

Выход из цикла и завершение текущего шага

Во всех типах циклов (for, foreach, while) можно применять 2 инструкции, чтобы нарушить нормальный порядок выполнения:

Continue в цикле

Тернарный оператор

Кроме математических операций вроде +, -, *, /, в PHP есть так называемый тернарный оператор. Он имеет такой вид:

условие ? если-верно : если-неверно

В качестве если-верно и если-неверно надо указать какое-то выражение (строки, числа, переменные или действия с ними). Этот оператор, если условие верно, возвращает значение выражение если-верно, иначе значение выражения если-неверно. В общем-то, его можно заменить ветвлением if ... else, но такая запись компактнее.

Тернарный оператор

Ссылка на пример: http://codepad.org/p3Un6QRv

Вывод значения переменной

Если в переменной число или строка, ее значение легко вывести с помощью echo (все помнят, как?). Но если в переменной, например, хранится большой массив, то его с помощью echo не выведешь. Для того, чтобы вывести значение любой переменной («сдампить», говорят бывалые кодеры), есть 2 функции: print_r($variable); и var_dump($variable);. Они делают примерно одно и то же, просто выводят информацию немного по-разному. Используй их при отладке программы и поиске ошибок.

Также, есть интересная функция var_export($variable);. Она выводит значение переменной в таком виде, как оно пишется в коде (строки заключаются в кавычки, массивы описываютя с помощью array()).

print_r(), var_dump() и var_export()

Ссылка на этот пример: http://codepad.org/dxEDeDUP

Где обещанные задачи??7

Наберись еще немного терпения. Никто не обещал, что будет легко.

Встроенные математические функции

Начнем с повторения математических функций и операций. Наверно, они тебе пока не понядобятся, потому учить их не надо, просто посмотри.

Математические функции в PHP

Подробнее об этих функциях читай в официальном мануале по PHP.

Встроенные функции работы со строками

Как ты уже наверно заметил, в PHP много готовых функций на все случаи жизни. Напомню, что для правильной работы со строками надо не забыть настроить кодировку в начале скрипта: mb_internal_encoding('utf-8');

Строковые функции в PHP

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

Как разбить строку на отдельные символы

Можно пройти посимвольно по строке от 0 до mb_strlen($string) и вырезать буквы с помощью mb_substr(). Но есть хитрый способ, скорее магия, с пустым регулярным выражением:

Разбиение строки на символы

Объяснение примерно такое: пустое регулярное выражение соответствует промежуткам между буквами, потому оно разбивает слово на отдельные буквы. Флаг u в регулярке надо ставить при использовании utf-8 и русских букв всегда, а PREG_SPLIT_NO_EMPTY удаляет из массива 2 пустых элемента, в начале и конце слова.

Функции для работы с массивами

Учить их не надо, надо просто прочесть и иметь предстваление, какие вообще функции есть в природе, чтобы не изобретать потом то, что уже давно сделано и написано.

Функции для работы с массивами в PHP

Много? Но их же не надо запоминать, так что ничего страшного. Полный список функции ищи, как всегда, в официальном мануале: массивы в PHP, функции для работы с массивами

Задачки

На десерт у нас, как всегда, развлечения в виде задачек.

Клавиша shift

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

Дан неграмотно написанный текст, состоящий из нескольких предложений на русском языке. Ошибки заключаются в неправильной расстановке пробелов и отсутствии заглавных букв. Исправь текст так, чтобы все предложения в нем начинались с большой буквы, а после знаков запятая, точка, точка с запятой, двоеточие, восклицательный и вопросительный знак стоял ровно один пробел (а перед ними — ни одного). Составные знаки вроде многоточия или 2 вопросительных знаков подряд должны сохраняться.

Исходный код тут: http://ideone.com/xnxvJ.

Пиши верно

Вот фраза с ошибками для самопроверки:

  • Вариант с ошибками: "много их в Петербурге,молоденьких дур,сегодня в атласе да бархате,а завтра , поглядишь , метут улицу вместе с голью кабацкою...в самом деле ,что было бы с нами ,если бы вместо общеудобного правила:чин чина почитай , ввелось в употребление другое,например:ум ума почитай?какие возникли бы споры!"
  • Правильный вариант: "Много их в Петербурге, молоденьких дур, сегодня в атласе да бархате, а завтра, поглядишь, метут улицу вместе с голью кабацкою... В самом деле, что было бы с нами, если бы вместо общеудобного правила: чин чина почитай, ввелось в употребление другое, например: ум ума почитай? Какие возникли бы споры!" автор

Подсказки

Если попытаться разбить строку на предложения с помощью preg_split, то знаки в конце предложения потеряются, так как preg_split вырезает из строки захваченные регуляркой (соответствующие ей) символы. Для борьбы с этим можно использовать утверждения в регулярках, которые не захватывают символ, а только проверяют его наличие перед или после определенного места. Например: preg_split("/(?<=\d)/u", "12abc3") разобьет строку по всем позициям, перед которыми стоит цифра; это даст массив ['1', '2', 'abc3', '']. Последний элемент массива появился из-за того что регулярка сработала после цифры 3, а так как за ней символов нет, получилась пустая строка. Избавиться от нее можно с помощью флага PREG_SPLIT_NO_EMPTY, подробности в мануале.

Расставить пробелы вокруг знаков препинания проще всего с помощью preg_replace. Чтобы не разбивать на части составные знаки вроде ... или ??, надо в регулярке добавить проверку того, какие символы идут после знака препинания.

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

Yoda Speak

Если ты хоть раз в жизни смотрел «Звездные войны», ты наверно заметил там такого персонажа, как магистр Йода, который говорил фразы, переставляя в них слова. Давай попробуем синтезировать речь Йоды программным способом.

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

Пожалуйста, не меняй код присваивания переменных в начале и код вывода текста в конце, твоя задача лишь исправить функцию makeYodaStyleText(). Код (почти готовый) бери тут: http://ideone.com/q6h0M. Постарайся сделать программу качественно: чтобы в результате не было слов с большой буквы в конце предложения, например.

Задачка про Йоду

Подсказка для глупеньких: сначала надо разбить текст на предложения. Предложения разделяются точкой, восклицательным и вопросительным знаком, и точкой с запятой, так что регулярное выражение и preg_split легко правятся с этой задачей (не забудь, что в регулярках точку и вопрос надо экранировать). Затем, проходясь в цикле по предложениям, мы разбиваем их на массив слов (preg_split или explode), переворачиваем его (array_reverse) и склеиваем назад в строку (implode). Осталось только собрать предложения в единую строку. Не забудь, что в начале предложений слово начинается с большой буквы. Также, стоит удалить знаки вроде запятых, чтобы они не мешались.

Удачи!

Числа прописью

Во многих серьезных документах принято писать денежные суммы цифрами и прописью, вот так: «триста двадцать шесть (326) рублей», «две тысячи один (2001) рубль». Давай избавим людей от рутинной работы, и поручим склонение слов роботам и языку PHP.

Дана сумма, находящаяся в банке на счету, в рублях. Вывести ее в текстовом виде вроде "шестнадцать миллионов десять тысяч три (16010003) рубля".

Полезные ссылки: правописание числительных там написано «несколько простых правил» — значит задача совсем несложная, верно?. Код (как обычно, почти готовый) бери тут: http://ideone.com/uQ9xG

Сумма прописью

Проверь свою программу на таких числах: 999999999, 0, 1, 11012013, 7000008, 1002, 1000, 7000000.

Разбор задачи

В этой задаче есть подводные камни:

Если ты попытаешься написать решение "в лоб", то наверно столкнешься с тем, что код получается довольно большой и запутанный. Это плохо, в большом объеме текста легче допустить ошибку, и тяжело разобраться. Для борьбы с этим программу надо разбивать на небольшие функции - тогда его будет писать проще. К тому же, функции проще протестировать по отдельности.

Также, функции позволяют избежать повторения кода. Это важно: в твоем коде не должно быть повторяющихся кусков и "копипасты". Этот принцип называется DRY (Don't Repeat Yourself).

Если твоя функция содержит больше 30-40 строк кода - стоит подумать о дальнейшем разбиении (массив с написанием цифр можно не учитывать при подсчете).

Если ты в затруднении, могу предложить сделать такие функции:

Алгоритм функции spellSmallnumber() получается довольно простым и выглядит так:

Некоторые делают ошибку, пытаясь работать с числами строковыми функциями вроде mb_substr() или mb_strlen(). Это неправильно. Для работы с числами надо использовать математические операторы, обычно это / и %. Например, чтобы найти последние 2 цифры числа, можно сделать деление на 100 с остатком: $number % 100. А убрать из числа последние 2 цифры можно, поделив число на 100 и округлив: floor($number / 100)

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

Калькулятор

Задача: написать программу, имитирующую работу обычного кнопочного калькулятора (если у тебя нет калькулятора, можешь попробовать запустить его на телефоне/айфоне/компьютере). Калькулятору на вход дается строка, содержащая целые числа и знаки  «+», «-», «*» и «=». По знаку «=» калькулятор выводит ответ. Порядок действий не соблюдается (как и в обычном калькуляторе), то есть 2+2*2= выведет 8. Скажу по секрету, писать калькулятор со скобками и порядком действий — в разы сложнее!

Если сложно, попробуй начать с всего 2 действий, например 345+567=

Усложнение: ввести поддержку дробных чисел и деления

Подсказка, как решать: идея примерно такая: мы заводим переменные $result (результат предыдущих действий), $number (число, которое сейчас набирается) и $op (предыдущая операция). Затем разбираем строку посимвольно (циклом for). Если это цифра — добавляем ее к числу $number (умножаем на 10 и прибавляем цифру), если это операция — то выполняем предыдущую операцию (которую мы храним в $op) над $result и $number, сохраняем итог в $result, а текущую операцию на будущее сохраняем в op. Если это «=», то выполняем предыдущую операцию и выводим $result

Тебе могут пригодиться эти функции, возьми их с собой:

Я у мамы калькулятор

Один анонимный пользователь, пытаясь прикинуться новичком, кстати сделал калькулятор (в hard mode, со скобками и приоритетом операций) с использованием стройного и красивого ООП и паттернов. Вот его код: http://ideone.com/T0AfO. Спасибо тебе, Калькулятор-кун! Отличное решение!

Удачи! Ты на пути к переходу на 2-й уровень!

-----

Куда вводить код? Что надо скачать? Читай первый урок.

Есть вопросы? Задай гуглу или автору.

Нравится урок? Лайкай, репости, приглашай друзей, пости котов и Канако, шли добра, решай задачи, помогай новичкам! Кнопок для лайка нет, кто хочет зарепостить, всегда может сделать это ручками.

Как связаться с автором? Я хочу переодеть его в платье школьницы и жениться на нем. Ящик codedokode (кот) gmail.com ждет ваших писем. А вконтактик и фейсбучек ждут ваших лайков. Но ответ на банальные вопросы лучше искать в Гугле или на stackoverflow.

Я решил задачку!!! Молодец, делай следующий урок

Ideone не работает!11 Ну так открой Гугл и найди сайты вроде http://phptester.net/ или http://codepad.org/ или http://www.runphponline.com/ . Не ленись.

Почему так много рекламы? Всю рекламу на сайте ставит юкоз (бесплатный хостинг же), а не я.

На сайте установлена система Google Analytics (и еще несколько аналогичных систем от юкоза). Данные о твоем IP-адресе, посещаемых страницах, времени посещения отправляются в Google Corporation, США. Хочу знать, кто и зачем сюда заходит. Поверь, другие сайты делают точно так же. Все сайты пишут логи.