質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

再帰

情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

Q&A

解決済

2回答

1454閲覧

PHPの静的変数を使用した再帰関数について

jakecoffee

総合スコア4

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

ループ

ループとは、プログラミングにおいて、条件に合致している間、複数回繰り返し実行される箇所や、その制御構造を指します

再帰

情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

1グッド

0クリップ

投稿2020/06/29 16:19

PHPのホームページのDocumentetionのを読んでいたら「例6 再帰関数での静的変数の使用」と言う項目で以下の説明と例がありました。

static変数は、再帰関数を実現する1つの手段としても使用されます。再帰 関数は、自分自身をコールする関数です。再帰関数を書くときには、無限 に再帰を行う可能性があるため、注意する必要があります。適当な方法に より再帰を確実に終了させる必要があります。次の簡単な関数は、中止す るタイミングを知るためにstatic変数$countを用いて、 10 回まで再帰を行います。

PHP

1<?php 2function test() 3{ 4 static $count = 0; 5 6 $count++; 7 echo $count; 8 if ($count < 10) { 9 test(); 10 } 11 $count--;  //ここが気になりました 12} 13?>

説明文からこのコードを実行すると以下のようになるのは推察できました。

terminal

1~ $ php main.php 212345678910~ $

しかし最後の「$count--;」が気になりました。ループを回避するためにあるのかな?と思いましたが気になったので「$count--;」のあとに「echo $count;」を追加してみてみました。すると以下の結果になりました。

terminal

1~ $ php main.php 2123456789109876543210~ $

予想では

terminal

1~ $ php main.php 2123456789109~ $

となり終了するのではないかと思いましたがそれでは無限ループ回避には関係ないですし実行結果からみると最後にゼロになってので無限ループを回避できたのか」?などと思いましたが理解不能です。おそらく本当に基本的なことなんだとは思うんですが調べてみてもわかりません。よろしく願いします。

退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

コードの作者の意図を予想した、おそらくの回答ですが、
連続して test() を呼び出したときに再び 12345678910 と出力させるため
と思われます

最後の $count--; がないと、
連続して呼び出したときは 2回目は 11, 3回目は 12 となってしまうでしょう

追記: なぜ $count がゼロまで戻るのか

$count--; は1回のみの動作で終了してしまうと思うのですがなぜゼロまで戻るのでしょうか?

処理が関数 test() の中 10 回入っていったので、
test() の中から 10 回出てきたためです
1 回ではありません

検証

同じ関数に再帰的に入っていくので理解が難しくなっているかもしれないので
違う関数に入っていく場合を考えてみましょう

次の例を実行してみましょう:

php

1<?php 2function test() 3{ 4 echo "before test\n"; 5 testtest(); 6 echo "after test\n"; 7} 8 9function testtest() 10{ 11 echo "before testtest\n"; 12 echo "after testtest\n"; 13} 14?>

実行結果:

console

1before test 2before testtest 3after testtest 4after test

さらに次の例を実行してみましょう:

php

1<?php 2function test() 3{ 4 echo "before test\n"; 5 testtest(); 6 echo "after test\n"; 7} 8 9function testtest() 10{ 11 echo "before testtest\n"; 12 testtesttest(); 13 echo "after testtest\n"; 14} 15 16function testtesttest() 17{ 18 echo "before testtesttest\n"; 19 echo "after testtesttest\n"; 20} 21?>

実行結果:

console

1before test 2before testtest 3before testtesttest 4after testtesttest 5after testtest 6after test

ご覧のように、関数呼び出しの後の処理は、
関数呼び出しが完了した後に実行されます

再帰呼び出しの場合も同様です

複数回関数呼び出しを行うということは、
呼び出した回数だけ、関数呼び出し後の処理も実行されます

投稿2020/06/29 16:33

編集2020/06/29 17:16
y_shinoda

総合スコア3272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jakecoffee

2020/06/29 16:52

素早いご回答ありがとうございます。さっそく試してみました。$count--;のあとのecho $count;はなしで2回連続で実行したみたところ以下ののようになり確かに2回めも1からスタートしています。 ~ $ php main.php 1234567891012345678910~ $ そういう意図があったんでしょうね。なるほど。 実はこういう挙動になること自体がわかりません。質問に書きましたように「$count--;」のあとに「echo $count;」を追加した場合は ~ $ php main.php 123456789109~ $ となるように思えるのです。if のブロックを抜けてからなので $count--; は1回ののみの動作で終了してしまうと思うのですがなぜゼロまで戻るのでしょうか?お手数おかけしますがよろしく願いします。
y_shinoda

2020/06/29 17:21

なぜゼロまで戻るのかについて、追記してみました この説明が効果的なのか自信はないので、 理解しづらければお気軽にフィードバックください、よろしくおねがいします
jakecoffee

2020/06/30 02:44

腑に落ちました。本当にありがとうございます。検証で用意していただいたコードでイメージができました。もとのコードでは入れ子の関数以前のコードが実行したあと順次次の入れ子が作られながら関数前のコードが実行される。なのでcountがひとつづつ増えていき10個目の入れ子関数の実行後は内側の関数の中の関数以後の処理をしながら戻っていくのでcountがひとつづつ減っていくということなんですね。 ~ $ php main.php 123456789109876543210~ $ 説明の効果についてご謙遜されましたが大変わかり易かったです。今後再帰関数を作成するときまにモヤっとしたらこのように置き換えてみたいと思います。すごいなと思いプロフィールを拝見させていただいたら大ベテランでありいろいろ発信されていることを知りました。Git 講座もゆっくり拝見したいと思います。また教えていただくチャンスがあればいいな思います。今後もよろしく願いします。
guest

0

再帰関数の挙動が理解できないって質問のようですね。

再帰関数の挙動って、実際に見てみないとよく理解できないと思います。
デバッグ環境を整えて、ステップ実行することで一気に解消できるのですけど、オンライン上で似たようなことができるので紹介します。

http://pythontutor.com

言語が JavaScript になり(残念ながら php のものが探せてないので)、static ではなく、global を使用していますが、再帰関数の挙動は追えると思います。

test() で積み上げられ、関数の最後まで実施されると、返り値(undefined) と共に、解消されるのが分かるかと。

質問内容の元のは、静的変数の使用 だと思うので、質問に追記しておいてください。(あとから見る人が、探さなくて良いようにしてあげてください)

投稿2020/06/29 22:41

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jakecoffee

2020/06/30 02:53

ご教授ありがとうございます。こんなツールがあるんですね。再帰関数の様子が実感できました。再帰関数でつまずいたら見直してみようと思います。 静的変数の意味は自分なりに理解できたつもりではあります。関数などの実行で宣言され終了でも破棄されずに値が保持される変数だと思っています。私の疑問は再帰関数であり静的変数ではなかったようです。紛らわしいタイトルにしてしまい申し訳ありません。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問