都道府県穴埋めゲーム

switch文の中でforeachをしたいのですが、うまくいきません。

<現状>
$x=5;
switch( $x ){
 case 2:
  echo $x="JavaScript";
   break;
 case 5:
  echo $x="PHP";
  break;
 default:
  echo $x="未分類";
}

<やりたいこと>判定データを別で用意して、読み込ませたい
$x_master = array(
 2 => "JavaScript",
 5 => "PHP",
);

■テスト1
$x=5;
switch( $x ){
 foreach( $x_master as $key => $value ){
  case $key:
   echo $x=$value;
  break;
 }
  default:
   echo $x="未分類";
}
これを試すと、Parse error: syntax error, unexpected T_FOREACH, expecting T_CASE or T_DEFAULT or '}'となります。これは、switchの中でforeachは使えないということでしょうか?

■テスト2
$x=5;
foreach( $x_master as $key => $value ){
 switch( $x ){
  case $key:
   echo $x=$value;
   break;
  default:
   echo $x="未分類";
 }
}
$x=2;だとJavaScript未分類となるのに、$x=5;だと未分類未分類になります。
$x=2と$x=5で挙動が異なる理由が分かりません。

■テスト3
$x=5;
foreach( $x_master as $key => $value ){
 switch( $x ){
  case $key:
   echo $x=$value;
  break;
 }
}
これでようやく望んだ結果が得られたのですが、これでo.k.のなのでしょうか? なんでdefault入れてはダメなのでしょうか? foreachでいくら回しても、該当部分が存在する限り、breakして、defaultへはいかないと思うのですが…。それともforeachの一番最後の終了処理で何かが返ってきて、それが該当項目に存在せず、defaultへ流れる結果となるのでしょうか?
そもそも、考え方として、foreachで回している以上、この場合、例外というか、switch文のdefaultに該当する部分は必要ないとの認識でよいでしょうか?



質問内容
■テスト1が、syntax errorとなる理由
■テスト2で、$x=2なら$x_masterを読み込むのに、$x=5なら$x_masterを読み込まない理由
■テスト3のケースは、default部分を本当に書かなくてo.k.でしょうか? またその理由は?

A 回答 (2件)

> ■テスト1


switch 文の構造を間違えています。
case は一種の「分岐命令」で、switchで指定した数値に合うcase文に実行の流れが飛ばされます。
それ以外の部分は実行されません。そのため、「switch の直下には case 文が必要」です。

> switch( $x ){
> foreach( $x_master as $key => $value ){
>  case $key:
この例では、foreach文を実行するような選択になるcase文がありませんから、エラーになります。

> ■テスト2
「echo $x="JavaScript";」
これが代入文であることを理解されてますでしょうか。
これは「$x="JavaScript"」という代入で変数$xの内容を変えたあとで、
その代入結果である「"JavaScript"」がechoに渡されて、「JavaScript」と表示されます。

一方、このforeachループの処理の流れを展開すると、
---ここから---
$x=5;
 $key=2;
 $value="JavaScript";
 switch( $x ){
  case $key:
   echo $x=$value;
   break;
  default:
   echo $x="未分類";
 }
 $key=5;
 $value="PHP";
 switch( $x ){
  case $key:
   echo $x=$value;
   break;
  default:
   echo $x="未分類";
 }
}
---ここまで---
という処理の流れになります。そのため、そのため、$x=5の場合、foreachの1回目($key=2,$value="JavaScript")の実行で「echo $x="未分類";」が実行されて、結果として「$x="未分類"」になってしまい、
2回目の($key=5,$value="PHP")でも「echo $x="未分類";」が実行されてしまいます。
結果、表示は「未分類未分類」になります。


> ■テスト3
このforeachの処理の流れはほぼテスト2で述べた通りですが、かなり回りくどいです。
単に$xが$x_masterに該当しているかどうかを表示したいだけでしたら、

---ここから---
$x_master = array(
2 => "JavaScript",
5 => "PHP",
);
$x=5;
if (isset($x_master[$x])) {
echo "x=$x_master[$x]";
} else {
echo "x=未分類";
}
---ここまで---
これだけで十分です。
    • good
    • 0
この回答へのお礼

>「switch の直下には case 文が必要」です
はっきりとしたご指摘、ありがとうございます。

>一方、このforeachループの処理の流れを展開すると、
ひとつひとつ処理を追いかけていったら、すごく理解できました。

>このforeachの処理の流れはほぼテスト2で述べた通りですが、かなり回りくどいです。
1さんの回答もそうですが、この質問をしたことで、色々な書き方を覚えることが出来たので、とても勉強になりました。
(質問した時点では、foreach以外、全く頭に思い浮かびませんでしたー。)

お礼日時:2010/12/20 16:19

switchは構文ですから、構文に合わないものは当然文法エラーでしょう。


もしやるならこんな感じでどうでしょう?

<?
$x=5;
$x_master = array(
2 => "JavaScript",
5 => "PHP"
);
switch( $x ){
case in_array($x,array_keys($x_master)):
echo '$x='.$x_master[$x];
break;
default:
echo '$x=未分類';
break;
}
?>


ちなみにecho $x=・・・・的な書き方はその時点で$xに値が上書きされているので
常識的にありえない書き方です。

この回答への補足

>case in_array($x,array_keys($x_master)):
こんな書き方も出来るんですね。初めて知りました。

>ちなみにecho $x=・・・・的な書き方はその時点で$xに値が上書きされているので、常識的にありえない書き方です。
ご指摘ありがとうございます。上書きしていってるのに、気が付きませんでした。これから気をつけたいと思います。

補足日時:2010/12/20 16:11
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報