PHP превключване на главни букви по подразбиране

Ще бъде ли оценена стойността по подразбиране на израз за превключване, ако има съвпадащ случай преди нея?

ex:

switch ($x) {
  case ($x > 5): print "foo";
  case ($x%2 == 0): print "bar";
  default: print "nope";
}

така че за x = 50 ще видите foo и bar, или foo и bar и nope?


person beth    schedule 10.08.2012    source източник
comment
Опитахте ли да стартирате този код?   -  person GreenMatt    schedule 10.08.2012
comment
Ако няма съвпадение на случай, ще се изпълни случаят по подразбиране.   -  person Tony M    schedule 10.08.2012
comment
FYI case ($x > 5) дава оценка на case 1: или case true:.   -  person Matt    schedule 10.08.2012
comment
Без break вашият код ще се опита да отговаря на всички условия. С break ще спре на 1-ви мач.   -  person N.B.    schedule 10.08.2012
comment
Не искам да спира на първия мач. Искам да изпълнява код за всички съвпадащи случаи.   -  person beth    schedule 10.08.2012
comment
Без прекъсвания във вашия код, той ще изпълни първия съвпадащ случай и всеки случай след това.   -  person Adam    schedule 10.08.2012


Отговори (4)


Да, ако няма "прекъсване", всички действия след първото case съвпадение ще бъдат изпълнени. Контролният поток ще "пропадне" през всички следващи case и ще изпълни всички действия под всеки следващ case, докато се срещне оператор break; или докато не бъде достигнат краят на оператора switch.

Във вашия пример, ако $x има стойност 50, всъщност ще видите "nope".

Обърнете внимание, че switch всъщност извършва прост тест за равенство между израза след ключовата дума switch и всеки израз след ключовата дума case.

Вашият пример е необичаен, тъй като ще покаже само "foo", когато $x има стойност 0. (Всъщност, когато $x има стойност 0, това, което ще видите, ще бъде "foo bar nope".)

Изразът след ключовата дума case се оценява, което във вашия случай, например, връща 0 (ако условният тест е фалшив) или 1 (ако условният тест е верен). И това е тази стойност (0 или 1), която switch ще сравни с $x.

person spencer7593    schedule 10.08.2012

Ще бъде ли оценена стойността по подразбиране на израз за превключване, ако има съвпадащ случай преди нея?

В повечето cases не би трябвало, защото често ще имате breaks там. Във вашия случай обаче ще отиде и до default.

Също така, моля, опитайте се да предотвратите тези едноредови неща (за четливост):

$x = 10;

switch (true) {
  case ($x > 5):
      print "foo";

  case ($x%2 == 0):
      print "bar";

  default:
      print "nope";
}

Ще отпечата foobarnope. И така, за да отговоря на въпроса ви: да :-)

person PeeHaa    schedule 10.08.2012
comment
отпечатва foobarnope. Веднага след като всеки случай е верен, всички следващи случаи, включително по подразбиране, до прекъсване (или край на превключване) ще се изпълняват. codepad.viper-7.com/sjHYeZ - person Jonathan Kuhn; 10.08.2012

Превключвателите не работят така.

Съгласно ръководството:

Операторът за превключване е подобен на поредица от оператори IF за един и същи израз. В много случаи може да искате да сравните една и съща променлива (или израз) с много различни стойности и да изпълните различна част от кода в зависимост от стойността, на която се равнява. Точно за това е операторът switch.

Оценка като

case ($x > 5):

просто се равнява на

case true:

or

case false:

в зависимост от стойността на $x, защото ($x > 5) е ОЦЕНКА, а не СТОЙНОСТ. Превключвателите сравняват стойността на параметъра, за да видят дали се равнява на някой от cases.

switch($x) {
    case ($x > 5): // $x == ($x > 5)
        echo "foo";
        break;
    case ($x <= 5): // $x == ($x <= 5)
        echo "bar"
        break;
    default:
        echo "default";
        break;
}

Сравнението в горния код е еквивалентно на

if ($x == ($x > 5)) {
    echo "foo";
} elseif ($x == ($x < 5)) {
    echo "bar";
} else {
    echo "five";
}

което (когато $x == 50) е еквивалентно на

if ($x == true) {
    echo "foo";
} elseif ($x == false) {
    echo "bar";
} else {
    echo "five";
}

което е еквивалентно на

if (true) { // $x == true is the same as saying "$x is truthy"
    echo "foo";
} elseif (false) {
    echo "bar";
} else {
    echo "five";
}

АКО обаче сте използвали израза си за превключване, както е предвидено да се използва (за да сравните параметъра с конкретни стойности):

switch ($x) {
    case 50:
        echo "foo ";
    case 30:
        echo "bar ";
    default:
        echo "foo-bar";
}

и $x == 50, изходът ви ще бъде

foo bar foo-bar

поради факта, че нямате break във вашите случаи.

Ако бяхте добавили ключовата дума break в края на всеки случай, щяхте да изпълните кода само за този конкретен случай.

switch ($x) {
    case 50:
        echo "foo ";
        break;
    case 30:
        echo "bar ";
        break;
    default:
        echo "foo-bar";
        break;
}

Изход:

foo 
person Matt    schedule 10.08.2012
comment
Не, не си. Прочети какво си написал. Казахте, че не можете да използвате такива превключватели и грешите - можете и нищо не пречи на никого да го прави. Публикуването на полуверен отговор е ужасно, някой ще влезе и ще прочете какво сте написали и ще си помисли, че сте били прави, когато не сте. - person N.B.; 10.08.2012
comment
Изявлението за превключване на OP е напълно валидно. Наличието на оценки в случаи е напълно валиден и силно желателен код. Вашият отговор показва само един вид употреба на твърдението. - person Buggabill; 10.08.2012
comment
@Matt - няма нищо лошо зад логиката, която се опитваш да обясниш, това, което не е наред, е твоето обяснение на израза switch. Операторът Switch се държи точно като оператор if. Можете да сравните стойности, за да получите true или false. switch е просто измислено удобство, за да не се налага да въвеждате 100 комбинации if/else и да влагате кода в забрава. - person N.B.; 10.08.2012
comment
@buggabill Не съм толкова сигурен, че е силно желателно, но е валидно. Мисълта ми беше, че не трябва да се използва по този начин освен ако не е напълно разбрано защо се използва. - person Matt; 10.08.2012
comment
@N.B. Искате да кажете, че case ($x > 5) е същото като if ($x > 5)? Защото не е. Това се равнява на if ($x == ($x > 5)) и OP трябва да знае това. - person Matt; 10.08.2012
comment
@Matt - добре, съжалявам, но грешите. Изявление switch се държи точно като if. case $x > 50: е точно като if($x > 50) и това е. - person N.B.; 10.08.2012
comment
@N.B. моят отговор беше в отговор на последния въпрос на OP: so for x = 50, you'd see foo and bar, or foo and bar and nope? Очевидно тя не разбира как се правят сравнения в switch и съм почти сигурен, че този отговор помогна да се изясни това. - person Matt; 10.08.2012
comment
@N.B. Инструкцията за превключване е подобна на поредица от инструкции IF за един и същи израз. В много случаи може да искате да сравните една и съща променлива (или израз) с много различни стойности и да изпълните различна част от кода в зависимост от стойността, на която се равнява. Точно за това е операторът switch. - person Matt; 10.08.2012
comment
@N.B. stackoverflow.com/questions/11904754/switch-evaluations Надяваме се, че отговорът на този въпрос ще разреши този наш аргумент. Ако греша, ще премахна отговора си и ще ви дам награда от 500. Ако греша, очаквам да премахнете вашите коментари и вашето -1. - person Matt; 10.08.2012
comment
@N.B., @Matt е напълно прав за това как работи превключвателят. ако имахте превключвател на switch($x){ case 0: echo "hi"; break; } няма ли еквивалентът на оператора if да бъде if($x == 0)...? тогава защо превключвателят на OP да не е равен на if($x == ($x > 5))...? губите ли по някакъв начин уравнението на случая? - person Jonathan Kuhn; 10.08.2012
comment
@Matt, един ред, но не съм съгласен. Изходът за горния код винаги ще бъде по подразбиране, освен ако $x == 1. Това не е вярно. В сравнението $x==($x > 5) например има имплицитно преобразуване на $x в булево, което ще се изчисли като true, докато $x!=0. Ако $x=0, този израз действително ще върне истина, тъй като $x ще бъде невярно, а $x›5 е невярно, така че получавате false==false. Ако $x=1 до 5, операторът връща false, тъй като всяко число, различно от 0, се преобразува в булево true. така че изявлението става true==false. всяко число над 5 изразът ще върне true true == true. - person Jonathan Kuhn; 10.08.2012

Щеше да е по-лесно да опитате сами.

Но така или иначе, ако не използвате break в случай, всички следващи случаи ще бъдат изпълнени (включително по подразбиране).

person Oussama Jilal    schedule 10.08.2012
comment
Вярно е, че има места, различни от stackoverflow, за да намерим отговорите на въпроси, но когато го направим, никой не може да събира репутация ;-) - person beth; 10.08.2012