php的三元运算符面试题,关于php:奇怪的行为三元运算符

来自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

谁能解释这种奇怪的行为?

不要使用那个代码。这是对三元运算符的一种可怕的、不可原谅的滥用。如果我在生产中发现了这个代码,我会立即删除它,并对作者使用非常严厉的语言。使用switch语句。

php支持switch php.net/manual/en/control-structures.switch.php

换个开关怎么样?

这段代码几乎是从en.wikipedia.org/wiki/%3f:php的维基百科页面逐字提取的,它解释了正在发生的事情。我叫巨魔:P

说到c,它在类似的情况下有一个bug。

当可以用if或switch简化语句时,为什么要使用三元语句?

我换的时间要长得多。此代码在C中工作正常。这是PHP中的错误吗?我好像触到了开放的神经?

最丑陋,最难以辨认的三元用法,我已经不高兴看到。它依赖于一个奇怪的级联关联,我不想调试它。如其他人所说,使用开关。

哦!看看所有的否决票!维基用户一定很生气,因为没有给出归属:p

到三元还是不到三元

不是虫子。优先级工作方式的差异。手册清楚地解释了为什么你不应该这样做。

我从维基上看到它是一个被确认的bug。我还是不完全明白。这是个多好的网站啊。有效的问题,3次落选,21次咆哮不使用,没有解释。欢迎使用StackOverflow!

从维基?那么你应该看到下面的解释。

@使用-你在这里遇到了一个稍微有争议的问题。请不要让一次体验决定你在网站上的观点。给它一个公平的机会-我相信你会看到更好的部分!

@用户1782842,但您不是新用户。为什么要创建一个新帐户来发布这个?

如果你在维基(wiki)上概述了你读过它,但是想要一些澄清,可能已经提供了你想要的反馈…你提出问题的方式不是问这个:)

@布莱恩:我没有从维基上读到它,它也不是我的原始代码。我用了一个较短的版本,但本质上是一样的。我希望从专业人员那里得到答案。相反,我得到了5个反对票,这个问题在本土化方面已经结束了。它说的都是这样的情况。急于快速回答问题,却没有真正的编程问题。

张贴的是逐字…

@派-你也可以说同样的事情,判断整个社会的堆栈溢出后,作为一个成员只有2天,只有一个职位…(只是说)

问题中的示例太小,可以通过其他方法来实现,但在某些情况下,这种模式是有效的。

PHP嵌套条件运算符错误?

在其他答案中没有看到任何关于代码为什么被破坏的解释,所以这里有一个快速的运行。

这里的问题更为明显,您添加了括号以使隐式计算顺序更显式。

下面是您的代码的精简版本,它仍然会产生不正确的"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';

你应该开始明白为什么这个坏了。第一个三元对true ? 'train' : 'false'到'train'进行评价:

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

因为当强制转换为布尔值时,'train'为真,所以结果现在为'car':

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

同样,因为非空字符串是"true",所以结果现在是"horse"。所以,第一次在可怕的嵌套case语句中出现true时,结果将级联到所有剩余的语句中,抛出下一个运算符的"true"分支的前一个值。

解决方案是避免使用此代码。这是一种试图走远,太聪明的尝试,结果是一个破碎的,不可读的混乱。完全没有理由使用它。选择一个switch语句,它的目的就是为您想要做的事情而构建。

在任何可感知语言(Java,C,C,C++)中工作良好。一个有文档记录的bug不是一个特性。

为了更好地衡量,这里有javascript、Perl和Ruby。我还没有找到一种用"php方式"来实现它的语言,+1用于解释这里发生的事情。

"php方式"是一个公认的bug,它仍然存在于向后兼容性方面,甚至在主要版本中也是如此。我不希望用理智的作家写的任何其他语言找到它。

它在任何语言中都是令人困惑的,而且几乎任何语言都将提供以清晰的方式设计的更好的构造。

米尔格,你说在这个问题的评论中这不是一个错误。我相信这是一个bug,并没有像您刚才所说的那样修复向后兼容性。@ChrisMiller我并不是说在任何语言中都没有更好的方法可以做到这一点,只是PHP处理它的方式是非常违反直觉的。

@NullUserException我并不是说它不是一个错误,不是为了向后兼容而修正的。这恰好使它非常违反直觉。:)

@美加:谢谢!你的解决方案解释了为什么我的不起作用。参见i.imgur.com/ph2zec6.png

我认为说这是个错误是不公平的。有人在定义三元运算符的关联性时搞砸了。他们犯了一个错误,但这不是一个bug,而是一个定义明确的(尽管不精确)行为。

@Andreafaulds err,你到底认为bug是什么?

@微不足道的错误、意外的行为。但语言规范的勘误表和错误之间存在差异。有些事情可能是一个错误的决定,但是PHP解释器没有任何问题,好吧,正确地解释PHP语言。出现了错误,三元运算符的定义方式错误。但它不是PHP中的bug。这只是语言中一个不幸的部分。

@Andreafaulds我会把对嵌套三元的phps处理称为"错误的意外行为"。那很合身。

由于在php语言语法中出现了一个bug,这无法按预期工作,如:http://en.wikipedia.org/wiki/%3f:php所示。

这里有一个简单的版本,可以工作:

$transport = 'T';

$vehicle = (

( $transport == 'B' ? 'bus' :

( $transport == 'A' ? 'airplane' :

( $transport == 'T'  ? 'train' :

( $transport == 'C'  ? 'car' :

( $transport == 'H'  ? 'horse' :

'feet' ))))));

echo $vehicle;

但正如其他人所说,我同意这不是最好的方法。您可以使用开关盒,如果不是,或者关联数组,并且可读性更高。

这是一种"按预期工作,即使它明显是错误的"PHP行为。它不会以这种方式关联,所以尽管这段代码可以在大多数其他语言中工作,但它在PHP中会失败。教训?学会在不寻常的关联范例上使用括号。第二课?三元不是一个神奇的子弹,虽然它可以很好和紧凑,它应该只在它可读的时候使用。imho嵌套的三元语句很难看。

如果你想这样做,就要学会爱妄想症:

$vehicle =     ( ( $transport == 'B' ) ? 'bus' :

(( $transport == 'A' ) ? 'airplane' :

(( $transport == 'T' ) ? 'train' :

(( $transport == 'C' ) ? 'car' :

(( $transport == 'H' ) ? 'horse' :'feet')))) );

由于php对三元的操作顺序http://php.net/manual/en/language.operators.comparison.php,三元的每个右侧都需要清楚地包含。

顺便说一下,从那个页面,他们明确建议不要像这样堆叠它们…

Note: It is recommended that you avoid"stacking" ternary expressions. PHP's behaviour when using more than one ternary operator within a single statement is non-obvious:

我的眼睛!可怕的!

@jackflash并没有说它是好的,但它让可怕的三元工作。

唯一一个指向实际问题的答案,即使您可以稍微解释表达式中没有括号的情况。

@用户1782842我的原始答案忘记了一个偏执,现在它被修正了。

@雷,这就是当你这么做的时候…你忘了括号:)不管怎样,OP只是在跟踪我们。

我不清楚您为什么选择使用这种形式的语法,正如在注释中提到的,这将是调试的一个噩梦…换个箱子可能是更好的选择-

$vehicle = '';

switch($transport){

case 'B' :

$vehicle = 'bus';

break;

case 'A' :

$vehicle = 'airplane';

break;

...

default:

// undefined cases

break;

}

参考文献-

switch statement

不知道为什么投了反对票…这是最合适的开发人员将要实现的解决方案!

它不能回答问题(这是在寻找解释,而不是另一种选择)

@que-有时候解释是"你做错了"。除此之外,我还提供了另一种解释。

这就是我想要的。

我不建议你使用这样的代码,但为了教育目的,它应该是

$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'

在php 7中,您甚至可以编写以下代码:['A'=>'airplane','B'=>"bus","C"=>"car","H"=>"horse","T"=>"tr‌​ain"][$transport] ?? null

哦,安德列。那太好了。

或者对于OP的情况:['A'=>'airplane','B'=>"bus","C"=>"car","H"=>"horse","T"=>"tr‌​ain"][$transport] ??"feet"。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值