2

C# 出身なので、PHP でプロジェクトを作成する必要があります。

私はこのコードを使用しています:

$transport = 'T';

$vehicle = (
 ( $transport == 'B' ) ? 'bus' :
 ( $transport == 'A' ) ? 'airplane' :
 ( $transport == 'T' ) ? 'train' :
 ( $transport == 'C' ) ? 'car' :
 ( $transport == 'H' ) ? 'horse' :
 'feet' );

echo $vehicle;

私はそれが印刷されると思っていましたtrainが、私はhorse. コードパッドの例: http://codepad.org/rWllfrht

この奇妙な行動を誰が説明できますか?

4

6 に答える 6

16

他の回答でコードが壊れている理由についての説明が表示されないため、ここに簡単な概要を示します。

ここでの問題は、評価の暗黙の順序をより明確にするためにブラケットを追加することで、より明白になります。

これは、「horse」という誤った結果を生成するコードの縮小バージョンです。

 $t = 'T';

 ( $t == 'T' ) ? 'train' : 
 ( $t == 'C' ) ? 'car' : 
 ( $t == 'H' ) ? 'horse' : 'feet';

まず、それを展開しましょう:

( $t == 'T' ) ? 'train' : ( $t == 'C' ) ? 'car' : ( $t == 'H' ) ? 'horse' : 'feet'; 

次に、暗黙的な括弧が既にある場所に、明示的な括弧を追加します。

((($t == 'T') ? 'train' : ($t == 'C')) ? 'car' : ($t == 'H')) ? 'horse' : 'feet';

次に、比較を解決できます。

((true ? 'train' : false) ? 'car' : false) ? 'horse' : 'feet';

これが壊れている理由を理解し始める必要があります。最初の 3 項は次のように評価さtrue ? 'train' : 'false''train'ます。

('train' ? 'car' : false) ? 'horse' : 'feet';

'train'ブール値にキャストすると true になるため、結果は次のようになり'car'ます。

'car' ? 'horse' : 'feet';

ここでも、空でない文字列は「true」であるため、結果は「horse」になります。したがって、ネストされた恐ろしい case ステートメントで初めて atrueが出現すると、結果は残りのすべてのステートメントにカスケードされ、次の演算子の「true」ブランチの前の値が破棄されます。

解決策は、このコードを回避することです。これはあまりに巧妙すぎる試みであり、その結果、壊れて判読不能な混乱が生じます。使用する理由はまったくありません。switchステートメントを選択してください。それはまさにあなたがやろうとしていることのために構築されたものです。

于 2012-10-30T15:53:06.650 に答える
3

これは、http: //en.wikipedia.org/wiki/%3F :#PHPに見られるように、PHP 言語文法のバグが原因で期待どおりに動作しません。

これは、機能する単純なバージョンです。

$transport = 'T';

$vehicle = (
 ( $transport == 'B' ? 'bus' :
 ( $transport == 'A' ? 'airplane' :
 ( $transport == 'T'  ? 'train' :
 ( $transport == 'C'  ? 'car' :
 ( $transport == 'H'  ? 'horse' :
 'feet' ))))));

echo $vehicle;

しかし、他の誰もが言ったように、これが最善の方法ではないことに同意します。if else if または連想配列を使用すると、はるかに読みやすくなります。

于 2012-10-30T15:49:28.340 に答える
1

これは、PHP の一種の「明らかに間違っているにもかかわらず、意図したとおりに動作する」動作です。そのように関連付けられていないため、このコードは他のほとんどの言語では機能しますが、PHP では失敗します。レッスン?異常な関連付けパラダイムで括弧を使用することを学びます。レッスン2?Ternary は魔法の弾丸ではありません。コンパクトで優れている場合もありますが、読みやすい場合にのみ使用する必要があります。私見のネストされた三項ステートメントはただ醜いです。

于 2012-10-30T15:48:45.673 に答える
0

コメントで述べたように、この形式の構文を使用することを選択した理由が正確にはわかりません。これはデバッグするのに悪夢です...ここではスイッチケースの方が良い選択かもしれません-

$vehicle = '';
switch($transport){
  case 'B' :
    $vehicle = 'bus';
  break;
  case 'A' :
    $vehicle = 'airplane';
  break;
  ...
  default:
   // undefined cases
  break;
}

参考文献 -

于 2012-10-30T15:40:24.270 に答える
0

このようなことをしたい場合は、括弧を愛することを学びましょう:

$vehicle =     ( ( $transport == 'B' ) ? 'bus' : 
                    (( $transport == 'A' ) ? 'airplane' :
                       (( $transport == 'T' ) ? 'train' :
                         (( $transport == 'C' ) ? 'car' :
                           (( $transport == 'H' ) ? 'horse' :'feet')))) );

三項http://php.net/manual/en/language.operators.comparison.phpに対する PHP の操作順序のため、三項の各右辺を明確に含める必要があります。

ちなみに、そのページから、このように積み重ねないように明示的に推奨しています...

注: 三項式を「積み重ねる」ことは避けることをお勧めします。単一のステートメント内で複数の三項演算子を使用した場合の PHP の動作は、自明ではありません。

于 2012-10-30T15:42:22.427 に答える
-1

そのようなコードを使用することはお勧めしませんが、教育目的で使用する必要があります

$transport = 'T';
$vehicle = (
        ($transport == 'B') ? 'bus' : 
            (($transport == 'A') ? 'airplane' : 
                (($transport == 'T') ? 'train' : 
                        (($transport == 'C') ? 'car' : 
                                (($transport == 'H') ? 'horse' : 'feet'))))
        );

echo $vehicle;

より良いコードは

$transport = 'T';
switch ($transport) {
    case 'A' :
        $vehicle = 'airplane';
        break;
    case 'B' :
        $vehicle = 'bus';
        break;
    case 'C' :
        $vehicle = 'car';
        break;
    case 'H' :
        $vehicle = 'horse';
        break;
    case 'T' :
        $vehicle = 'train';
        break;
    default :
        $vehicle = 'teleportation';
        break;
}

echo $vehicle;

またはさらに良い:

$transport = 'T';
$array = array('A'=>'airplane','B'=>"bus","C"=>"car","H"=>"horse","T"=>"train");
echo isset($array[$transport]) ? $array[$transport] : null;

または、データベースを使用します。

 SELECT name FROM transpotationTable WHERE someKey = '$transport' 
于 2012-10-30T15:48:37.883 に答える