За последние 24 часа нас посетили 60298 программистов и 1815 роботов. Сейчас ищут 864 программиста ...

рекурсия и возврат данных

Тема в разделе "Прочие вопросы по PHP", создана пользователем amir_Mirov, 24 янв 2015.

  1. amir_Mirov

    amir_Mirov Новичок

    С нами с:
    25 сен 2014
    Сообщения:
    90
    Симпатии:
    0
    Доброго времени суток !
    имею код
    Код (Text):
    1.  
    2.     function mystrlen($item)
    3.     {
    4.         if(is_null($item))
    5.                 return 0;
    6.         if(!is_string($item))
    7.                 return 0;
    8.            
    9.             static $c = 0;
    10.             $rr = $item{$c};
    11.             if(!$rr == 0 )
    12.             {
    13.                 $c++;
    14.                         mystrlen($item);
    15.                        
    16.             }else{
    17.        
    18.             var_dump( $c);
    19.            
    20.             return $с;
    21.         }
    22.     }
    23.     $item = 'dfgdfgdfgdfgd';
    24.     $val = mystrlen($item);
    25. var_dump($val);
    проблема в том , что в вал функция отдает null
    я не могу почему до return var_dump отдает количество элементов а ретурн получается отдает нулл
    хотелось бы понять почему так
     
  2. p@R@dox 55RU

    p@R@dox 55RU Зэк
    [ БАН ]

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    а что значить эта запись
    Код (Text):
    1. rr = $item{$c};  if(!$rr == 0 )  {  $c++;  mystrlen($item);  }
    ???
     
  3. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    у тебя ретёрн делается из элса условия "не рр равно нулю". а более нигде ретёрна не делается. а поскольку результат вызова функции присваивается переменной - пхп записывает void как результат. а поскольку войда в пхп нет - записывается налл.
     
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    всегда удивляли программисты, у которых отступ 3 пробела. и вообще здесь с отступами полных ппц. они не соответствуют структуре, только сбивают с толку. это специальный подвох чтобы одурачить читателя?
     
  5. denis01

    denis01 Суперстар
    Команда форума Модератор

    С нами с:
    9 дек 2014
    Сообщения:
    12.227
    Симпатии:
    1.714
    Адрес:
    Молдова, г.Кишинёв
  6. p@R@dox 55RU

    p@R@dox 55RU Зэк
    [ БАН ]

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    я знаю что можно использовать. Меня заинтересовала эта запись
    Код (Text):
    1. if(!$rr == 0 )
    Чтооооо это такоее?
     
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    автор, у тебя переменная в return в кириллическом написании! это не ЛатинскаяЦе, а РусскаяЭс )))
    это специальный подвох №2 чтобы одурачить читателя?

    собственно ошибка в том, что финальный ретурн происходит неявно, не там где "ретурн эс", а просто по окончанию функции — т.к. сработал блок иф, а не блок элс.
    это подвох №3, я считаю.
    глаз видит оператор возврата и кажется, что именно там всегда происходит выход. на самом деле тот ретурн срабатывает один раз по достижении конца строки. именно поэтому мы видим только один результат вардамп!
    а неявный выход случается столько раз, сколько символов в строке.

    Добавлено спустя 7 минут 1 секунду:
    исправленный вариант функции:
    Код (PHP):
    1. function mystrlen($item)
    2. {
    3.    static $c = 0;
    4.    if(isset($item{$c}))
    5.    {
    6.       $c++;
    7.       mystrlen($item);
    8.             
    9.    }
    10.    return $c;
    11. }
     
  8. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    условие "если не рр равно нулю" оно же "если рр не равно нулю". отрицание.
     
  9. p@R@dox 55RU

    p@R@dox 55RU Зэк
    [ БАН ]

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    да я прекрасно понимаю что это отрицание... Но это не то место где его использовать в таком виде. Если бы $rr было логическим выражением -вопросов бы не было. А за такого некорректного когда начинаются тормоза и лишние вопросы.
     
  10. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    хаха, дык вся это функция, мягко говоря, небыстрая. видимо не было такой цели.
    это похоже на специально написанный тест на способность видеть ошибки. судя по многообразию косяков.

    кстати, где-то в теме про беспощадную микрооптимизацию я читал, что isset($str{0}) вероятно самый быстрый способ проверки на непустую строку.

    edited: объяснение - On PHP function calls
     
  11. p@R@dox 55RU

    p@R@dox 55RU Зэк
    [ БАН ]

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    зачем тогда сочинять очередной велосипед, который в результате ваще не работает? есть же strlen - и пользуйся им на здоровье.
    Лучше бы время на что-то более полезное тратить ))
     
  12. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    про идее быстрее будет empty - она к счетчику символов должна будет обратиться а там ноль или не ноль. это к вопросу о том использовать или нет count($array) внутри условия циклов - функция не считает длину массива а сразу возвращает значение внутреннего счетчика. но могу врать ибо давно сурсы зенд-машины читал.
     
  13. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Ganzal
    Код (Text):
    1. $s = '0';
    2. var_dump(empty($s)); // bool(true)
    поэтому таки isset.

    хотя есть случаи, когда '0' и '' действительно имеют один и тот же смысл, тогда ок.
     
  14. amir_Mirov

    amir_Mirov Новичок

    С нами с:
    25 сен 2014
    Сообщения:
    90
    Симпатии:
    0
    всем спасибо ! все работает . нехватало returna вне блоков. смысл этого велосипеда в том что это просто практика набиваю руки уж простите сам учусь - как могу . могу показать реальный код рабочий )
     
  15. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    Амир, еще на заметку - вот это
    Код (PHP):
    1.       if(is_null($item))
    2.             return 0;
    3.       if(!is_string($item))
    4.             return 0;
    можешь заменить на просто
    Код (PHP):
    1.       if(!is_string($item))
    2.             return 0;
    ))) пустое значение не является строкой
     
  16. p@R@dox 55RU

    p@R@dox 55RU Зэк
    [ БАН ]

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    это было куда интереснее, и советы услышал бы тоже полезные, как можно было бы правильнее сделать...
    Мы рады за тебя! Успехов! :)
     
  17. amir_Mirov

    amir_Mirov Новичок

    С нами с:
    25 сен 2014
    Сообщения:
    90
    Симпатии:
    0
    Ув Гуру ! следуя вашим замечания немного поправил код. теперь он менее походит на Г_код ?
    Задача была описать встроенную функцию strlen() своими силами. В голову пришла рекурсия ,но была идея использовать цикл for , проверять с помощью if - стоп цикл с помощью break или ретурн ( он работает если не ошибаюсь тоже как break)
    почему рекурсия - посчитал ее более подходящей в плане количества кода. буду рад замечаниям !
    Код (Text):
    1.  
    2.  
    3. function mystrlen($item)
    4.     {
    5.             if(!is_string($item))
    6.                     return 0;
    7.                 static $c = 0;         
    8.             if(!$item{$c} == 0 ){
    9.                 $c++;
    10.                 mystrlen($item);
    11.              }else{
    12.                  return $с;
    13.                  }
    14.             return $c;
    15.     }
    16. $item = 'string';
    17. $val = mystrlen($item);
    18. echo $val;
     
  18. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    artoodetoo, ну count-то по пустой-непустой строке правильно сработает?))))
     
  19. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    да, наверное count тоже годится. не возьмусь вычислять самый быстрый метод ))) мне достаточно знать просто рабочий.
    а про быстроту я цитировал с долей сарказма.
     
  20. Ganzal

    Ganzal Суперстар
    Команда форума Модератор

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    ну да, с рабочим я облажался)))) бывает
     
  21. amir_Mirov

    amir_Mirov Новичок

    С нами с:
    25 сен 2014
    Сообщения:
    90
    Симпатии:
    0
     
  22. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.128
    Симпатии:
    1.248
    Адрес:
    там-сям
    amir_Mirov, как упражнение для ума это конечно забавно, но как альтернативный strlen это не годится, сам же понимаешь. надеюсь, что понимаешь )))

    чем плох твой нынешний код:
    - блок else просто лишний
    - !$item{$c} == 0 это нечитабельно. ну не пишут так люди "не икс равно нулю" )))
    - !$item{$c} == 0 вызовет выдачу предупреждения на последнем проходе, см. ниже
    - static вещь коварная, он ведь сохранит значение! что будет если протестировать сначала '123456', а потом '123' ?

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

    Добавлено немного спустя:
    Всегда отлаживай свои скрипты со включенным выводом предупреждений. А на рабочем сайте выключай!
    Включается вывод так:
    Код (PHP):
    1. error_reporting(-1); // 0 - выключить, -1 - включить все, другие значения включают какие-то отдельные ошибки
    2. ini_set('display_errors', 'on');
    Добавлено спустя ещё некоторое время:
    проверять наличие переменной, или элемент массива, или смещение строки (как у тебя), чтобы при этом не выдавалось предупреждение можно с помощью встроенных функций isset и empty, почитай по ним справку!
    если быть точным, это даже не функции, а конструкции языка, как if или for
    поэтому в своем примере я тестировал то же самое через isset.
     
  23. amir_Mirov

    amir_Mirov Новичок

    С нами с:
    25 сен 2014
    Сообщения:
    90
    Симпатии:
    0
    Спасибо за замечания.
    не подходит как альтернативный strlen - оригинальная функция написана на с ( скорость ) + зачем писать то что уже написано.
    блок else - убрал все отработало ! все ок
    static - учел. (изменил )
    error_reporting(-1) вывел увидел
    В итоге много выводов. и огромное вам человеческое спасибо!
    след функция. var_dump();
    Код (Text):
    1.  
    2. function mystrlen($item,$c=0)
    3.     {
    4.             if(!is_string($item))
    5.                     return 0;          
    6.             if(isset($item{$c})){
    7.                           $c++;
    8.                 return mystrlen($item,$c);
    9.              }
    10.             return $c;
    11.     }
    12. $item = 'strifg';
    13. echo  mystrlen($item);
     
  24. Period

    Period Новичок

    С нами с:
    29 дек 2014
    Сообщения:
    148
    Симпатии:
    1
    Всё это while'ом можно без проблем подсчитать без статических переменных и рекурсии. Идёте посимвольно по строке и считаете, пока строка не закончится. Зачем так мудрить?
     
  25. amir_Mirov

    amir_Mirov Новичок

    С нами с:
    25 сен 2014
    Сообщения:
    90
    Симпатии:
    0
    согласен что можно ! можно еще что- нибуть придумать. а можно раскрытый ответ если while то почему кода будит тоже количество
    while быстрей или просто вам он удобней. хотелось бы фактов - я учусь учтите этот факт . спасибо