За последние 24 часа нас посетили 24183 программиста и 1654 робота. Сейчас ищут 870 программистов ...

Вычисление факториала, рекурсия и формочка

Тема в разделе "PHP для новичков", создана пользователем iNEEdhLw, 17 янв 2015.

  1. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    код вычисления факториала:
    Код (Text):
    1. <form action="" method="POST">
    2.     <input type="text" name="text" >
    3.     <input type="submit" name="click" value="Рассчитать факториал">
    4. </form>
    5. <?php
    6. $number = $_POST['text'];
    7.  function factorial($number)
    8. {
    9.    if ($number == 0 or $number ==1) return 1;
    10.    $result = $number*factorial($number-1);
    11.    return $result;
    12.    
    13. }
    14.  
    15. if (isset($number)) echo factorial($number);
    интересует следующий момент:
    при первом(!) заходе на страницу с кодом, результат выглядит так (как и должен выглядеть):
    предположим, что я захотел вычислить факториал числа 4 :
    всё хорошо - считает, но делаю обновление страницы и число 24 остается, в чём трабл? в моём представлении должно стать так, как было до вычислений, т.е. пустой инпут и кнопка отправки.
     
  2. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    при обновлении страницы браузер спрашивать а не сделать ли мне удалому молодцу пост-запрос с теми же данными формы. и ты соглашаешься. и он делает. и ты вновь видишь 24.
     
  3. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    После принятия пост-запроса, нужно отдавать заголовок с переадресацией. Пусть даже на эту же самую страничку.
     
  4. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    куда ещё можно вставить заголовок не знаю, однако получаю варнинг :(
    разжует кто-нибудь?
    [​IMG]
    з.ы. перевод ошибки я и сам прекрасно понимаю, мне решение и причину подсказать нужно бы)
     
  5. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    В саааамом начале кода поставь ob_start(), будет тебе счастье.
    И потом почитай, что такое буфер вывода, как он работает и какие фичи умеет.

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

    Добавлено спустя 3 минуты 22 секунды:
    p.s. НИКОГДА не выкладывай код в виде скриншота. Копипасть.

    Добавлено спустя 1 минуту 26 секунд:
    И да, в твоем случае, лучше просто передавать GET-ом число. Потому что ты сейчас именно в той ситуации, когда вместо GET-а используется POST.
     
  6. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    так точно, почитаю и приму к сведению.
    но проблема теперь такая:
    код выглядит сл. образом:
    Код (Text):
    1. <?php
    2. ob_start();
    3. ?>
    4. <form action="" method="POST">
    5.     <input type="text" name="text" >
    6.     <input type="submit" name="click" value="Рассчитать факториал">
    7. </form>
    8. <?php
    9.  
    10. $number = $_POST['text'];
    11. header("location: index.php");
    12.  function factorial($number)
    13. {
    14.    if ($number == 0 or $number ==1) return 1;
    15.    $result = $number*factorial($number-1);
    16.    return $result;
    17.    
    18. }
    19.  
    20. if (isset($number)) echo factorial($number);
    21.  
    22.  
    23. ?>
     
  7. p@R@dox 55RU

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

    С нами с:
    21 май 2014
    Сообщения:
    1.358
    Симпатии:
    7
    Адрес:
    с планеты Ялмез
    подобная же печаль тебя ждет, если в $_POST['text'] передать даже число '-1' ;)
     
  8. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    я туда ещё даже нечего не передавал, это выскакивает при первом же входе на страничку
     
  9. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Потому что ты, при заходе на страницу, сразу же отдаешь заголовок переадресации)

    Добавлено спустя 2 минуты 21 секунду:
    Вообще тебе тут, повторюсь, нужен обычный GET. Без заголовков и тд. Ситуация не для POST.
     
  10. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    так-с, я проснулся - можно начинать думать.
    у меня происходит редирект(так, кажется, это называется?), но не так, как мне нужно.
    я отправляю через форму число, скрипт обрабатывает это число и перенаправляет меня на эту же страницу, так, что я не вижу того, что он вывел там, т.е. результата вычислений визуально нет.
    Код (Text):
    1. <?php
    2. ob_start();
    3. ?>
    4. <form action="" method="POST">
    5.     <input type="text" name="text" >
    6.     <input type="submit" name="click" value="Рассчитать факториал">
    7. </form>
    8. <?php
    9.  
    10. $number = $_POST['text'];
    11.  
    12.  function factorial($number)
    13. {
    14.      if ($number >= 0)
    15.      {
    16.          
    17.    if ($number == 0 or $number ==1) return 1;
    18.    $result = $number*factorial($number-1);
    19.    return $result;
    20.      }
    21.      else echo "error";
    22. }
    23.  
    24. if (isset($number))
    25. {
    26.    
    27.  
    28. echo factorial($number);
    29. header("Location: index.php");
    30. }
    такой способ мне не совсем подходит. мне нужно, чтобы он вывел результат, а при обновлении страницы (alt+f5, for example) введенные мною данные были сброшены, т.е. я пришел к исходному виду.

    Добавлено спустя 4 минуты 58 секунд:
    а если не использовать буфер (и, соответственно, заголовок), то при нажатии alt+f5 происходит следующее
    но вне зависимости от моего ответа (да или нет) - результат скрипта вычислений "не сбрасывается".
    з.ы. если что не понятно объяснил - пишите)
     
  11. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    iNEEdhLw, поставьте в форму method='get', и не парьтесь (естественно, введённое значение надо будет забирать из $_GET). Сурикат небось тут уже устал повторять. post запросы принято использовать для таких задач, как добавление чего-то в базу данных, или когда желательно, чтоб данные не фигурировали в урле (как при авторизации, к примеру)
     
  12. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    забыл об этом написать, я так уже делал, но тогда окошко с вопрос не выскакивает, а обновление страницы будто и вовсе не происходит - рез-ат вычислений не пропадает.
    Код (Text):
    1. <?php
    2. // ob_start();
    3. ?>
    4. <form action="" method="GET">
    5.     <input type="text" name="text" >
    6.     <input type="submit" name="click" value="Рассчитать факториал">
    7. </form>
    8. <?php
    9.  
    10. $number = $_GET['text'];
    11.  
    12.  function factorial($number)
    13. {
    14.      if ($number >= 0)
    15.      {
    16.          
    17.    if ($number == 0 or $number ==1) return 1;
    18.    $result = $number*factorial($number-1);
    19.    return $result;
    20.      }
    21.      else echo "error";
    22. }
    23.  
    24. if (isset($number))
    25. {
    26.    
    27. // header("location: index.php");
    28. echo factorial($number);
    29.  
    30. }
     
  13. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    да сделай ты уже на javascript-е и всё)))
     
  14. iNEEdhLw

    iNEEdhLw Новичок

    С нами с:
    22 окт 2014
    Сообщения:
    414
    Симпатии:
    0
    побегу за двумя зайцами - ни одного не поймаю :(
    я js даже не начинал изучать ещё, рановато
     
  15. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    у протокола передачи гипертекста и пхп на стороне сервера есть две возможности.
    возможность первая: гет-запрос. но тебе не нравится что у тебя данные в урл попадают
    возможность вторая: пост-запрос. но тебе не нравится что обновление страницы приводит к повторной отправке того же значения и как следствие повторному вычислению и тому же результату. а ты хочешь на обновление страницы чтоб всё пусто было. ну не знаю, можно через сессии сделать костыль. открылась форма - записали в сессию рандом и спрятали этот рандом в сессию и в скрытое поле в форме. отправленную форму проверяем на актуальность этого рандома. если он актуален - считаем факториал. не актуален - пропускаем подсчет. и не забываем обновление рандома в правильных местах кода.
    ну и естественно джаваскрипт тоже не стоит со счетов сбрасывать. открыли страницу, ввели число, нажали кнопку, посчитали, записали результат. и другой адрес не придется открывать. и если обновить - всё очищается и без назойливых предупреждений.
     
  16. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ganzal, можно и проще. Результаты вычисления писать в сессию, переадресовывать на ту же страницу, считывать... Но зачем такие сложности ради вычисления факториала.
    Код (PHP):
    1. <?php
    2.  function factorial($number)
    3. {
    4.    if ($number == 0 or $number ==1) return 1;
    5.    $result = $number*factorial($number-1);
    6.    return $result;
    7.    
    8. }
    9. if ($_SERVER["REQUEST_METHOD"] == "POST") {
    10.     $number = $_POST['text'];
    11.     $_SESSION["factorial"] = factorial($number);
    12.     header("Location: " . $_SERVER["REQUEST_URI"]);
    13.    die;
    14. }
    15. $fact = isset($_SESSION["factorial"]) ? $_SESSION["factorial"] : "";
    16. unset($_SESSION["factorial"]);
    17. ?>
    18. <form action="" method="post">
    19.     <input type="text" name="text" >
    20.     <input type="submit" name="click" value="Рассчитать факториал">
    21. </form>
    22. <?= $fact; ?>
    Добавлено спустя 54 секунды:
    P.S. Считать факториал рекурсией - глупость, там цикл фор в 2 строчки лучше справится.
     
  17. Ganzal

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

    С нами с:
    15 мар 2007
    Сообщения:
    9.893
    Симпатии:
    965
    да, я именно такую логику и предлагаю но по традиции минирую логику фрагментами её отсутствия. ТС как бы должен задаться вопросом "а зачем тут вот этот мусор?" и переписать. мы же в форуме для новичков не для слепоглухонемых халявщиков.

    поддерживаю. опять же лимит рекурсии может неожиданно подкрасться.
     
  18. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Рассчет факториала, кстати, одна из задач, которую именно на примере рекурсии и показывают. Чисто чтоб понять, что это такое. Но в практическом плане да, не самое оптимальное решение.
    Нет у рекурсии лимита. Есть лимит размера колл-стэка. Но его исчерпать-таки тяжко.
     
  19. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.598
    Симпатии:
    1.764
    Ага, и ещё - числа Фибоначчи, для которых тоже рекурсия не лучшее решение, но там хоть действительно без рекурсии кода раза в 2 больше нужно писать.
     
  20. Fell-x27

    Fell-x27 Суперстар
    Команда форума Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.156
    Симпатии:
    1.771
    Адрес:
    :сердА
    Задачки на то и задачки.