В этом уроке мы реализуем функцию mysubstr()
, которая извлекает из строки подстроку указанной длины.
Она принимает на вход два аргумента:
Эта функция возвращает подстроку, начиная с первого символа:
<?php
function mysubstr($str, $length)
{
$index = 0;
$result = '';
while ($index < $length) {
$currentChar = $str[$index];
$result = "{$result}{$currentChar}";
$index = $index + 1;
}
return $result;
}
$str = 'If I look back I am lost';
mysubstr($str, 1); // 'I'
mysubstr($str, 7); // 'If I lo'
https://replit.com/@hexlet/php-basics-edge-cases-mysubstr
Кажется, что все хорошо. Но наша функция содержит множество ошибок, потому что в ней не учтены так называемые пограничные случаи. Функция нормально работает только с нормальными аргументами. Но мы не знаем, как она поведет себя, если передать ей такие варианты длины:
0
Функция mysubstr()
не рассчитана на такие варианты. Можно подумать, что это не проблема: функция работает в нормальных условиях, и просто не нужно передавать ей «плохие аргументы».
В идеальном мире — да, но в реальном мире ваш код будет запускаться в разных ситуациях, с разными комбинациями условий и данных. Нельзя быть уверенным, что аргументы всегда будут корректными, поэтому нужно учитывать все случаи, в рамках здравого смысла.
Пограничные случаи — самая распространенная причина логических ошибок в программах. Программисты часто забывают что-нибудь учесть. Такие ошибки часто проявляются не сразу, и могут долгое время не приводить к видимым проблемам. Программа продолжает работать, но в какой-то момент обнаруживается, что в результатах есть ошибки.
Часто причина заключается в слабой типизации PHP. Умение справляться с такими ошибками приходит с опытом, через постоянные проблемы в стиле «Ой, забыл проверить на пустую строку!».
Давайте представим себе расширенную функцию mysubstr()
. Она принимает три аргумента:
Функция возвращает подстроку указанной длины начиная с указанного индекса. Посмотрим примеры вызова:
<?php
$str = 'If I look back I am lost';
mysubstr($str, 0, 1); // 'I'
mysubstr($str, 3, 6); // 'I look'
Обсудим, что может пойти не так. Какие пограничные случаи стоит учитывать:
В реализации функции каждый пограничный случай будет отдельным куском кода, скорее всего реализованным с помощью if
.
Чтобы написать функцию mysubstr()
и защититься от этих случаев, стоит написать отдельную функцию, которая будет проверять аргументы на корректность. Займемся этим в задании к этому уроку.
Реализуйте функцию-предикат isArgumentsForSubstrCorrect
, которая принимает три аргумента:
Функция возвращает false
, если хотя бы одно из условий истинно:
В ином случае функция возвращает true
.
Не забывайте, что индексы начинаются с 0
, поэтому индекс последнего элемента — это «длина строки минус 1».
Пример вызова:
<?php
$str = 'Sansa Stark';
isArgumentsForSubstrCorrect($str, -1, 3); // false
isArgumentsForSubstrCorrect($str, 4, 100); // false
isArgumentsForSubstrCorrect($str, 10, 10); // false
isArgumentsForSubstrCorrect($str, 11, 1); // false
isArgumentsForSubstrCorrect($str, 3, 3); // true
isArgumentsForSubstrCorrect($str, 0, 5); // true
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Это нормально 🙆, в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Ваше упражнение проверяется по этим тестам
1<?php
2
3namespace HexletBasics\Loops\EdgeCases;
4
5use PHPUnit\Framework\TestCase;
6
7class Test extends TestCase
8{
9 public function test()
10 {
11 require 'index.php';
12
13 $str = 'Sansa Stark';
14
15 assert(isArgumentsForSubstrCorrect($str, -1, 3) === false);
16 assert(isArgumentsForSubstrCorrect($str, 4, 100) === false);
17 assert(isArgumentsForSubstrCorrect($str, 10, 10) === false);
18 assert(isArgumentsForSubstrCorrect($str, 11, 1) === false);
19 assert(isArgumentsForSubstrCorrect($str, 11, 0) === false);
20 assert(isArgumentsForSubstrCorrect($str, 3, 3) === true);
21 assert(isArgumentsForSubstrCorrect($str, 10, 1) === true);
22 }
23}
24
Решение учителя откроется через: