BruceyBandit
BruceyBandit

Reputation: 4334

Case statement is not outputting correctly?

This is very strange but below is my case statement:

switch($grade){
    case ($average >70):
    $grade = 'A';
    break;
    case ($average >=60 && $average <=69):
    $grade = 'B';
    break;
    case ($average >=50 && $average <=59):
    $grade = 'C';
    break;

};

So if its 70+ it is grade A, 60-69 grade B, 50-59 grade C.

But instead it outputting this: 60+ grade A, 50-59 grade B, 40-49 grade C.

Why is it doing this because function seems correct?

    echo "<p><strong>Average Mark:</strong> $average</p>";
    echo "<p><strong>Average Grade:</strong> $grade</p>";

Upvotes: 2

Views: 3891

Answers (4)

hakre
hakre

Reputation: 198204

Edit: Alternatively you can calculate the $grade value (50-100 in this example):

$grades = "CBAAA";
$grade = $grades[(int)($average/10) - 5];

The switch loop compares the cases. If you really want to use switch for the job (and not if / elseif / else), then you can to it with a switch that compares against TRUE:

switch(TRUE)
{
    case $average > 70:
        $grade = 'A';
        break;

    case $average >= 60 && $average <= 69:
        $grade = 'B';
        break;

    case $average >= 50 && $average <= 59:
        $grade = 'C';
        break;

    default:
        throw new Exception(sprintf('Unable to map average (%d) to a grade.', $average));
}

Upvotes: 0

animuson
animuson

Reputation: 54797

For those of you saying switch the variable you $average, you are wrong. The only reason it is evaluating in that instance is because switch uses loose comparison, so it is saying that $average being set is true and comparing it to the conditionals, all of which will be either true or false. Previously, using $grade which was unset was evaluating the switch to false because in loose comparison, a variable which is unset will throw a notice and return false.

While I recommend using if-then-else, the proper answer for using a switch statement in this case is as follows:

switch (true) {
    case ($average >= 70):
        $grade = 'A';
        break;
    case ($average >= 60 && $average < 70):
        $grade = 'B';
        break;
    case ($average >= 50 && $average < 60):
        $grade = 'C';
        break;
}

Like said above, every statement will return either true or false. The idea is that only one statement should ever return true at one time, thus the switch statement will match it's value of true to the one statement that passed and execute that code only, since all of the other ones are false and didn't match.

Upvotes: 2

Matty K
Matty K

Reputation: 3891

As others mentioned in comments, the "condition" in a case should be a static value, not a logical expression.

Also, the value you're switching on (in your case, $grade) should is the one you're testing. You appear to be using it as a hint about what variable you're assigning.

The simplest way to fix your code would be to use an if-elseif-else construct:

if ($average >70)
    $grade = 'A';
elseif ($average >=60 && $average <=69)
    $grade = 'B';
elseif ($average >=50 && $average <=59)
    $grade = 'C';

However, to be perverse, and to illustrate how a switch statement works, you could also do the following:

switch(true){
    case ($average >70):
        $grade = 'A';
        break;
    case ($average >=60 && $average <=69):
        $grade = 'B';
        break;
    case ($average >=50 && $average <=59):
        $grade = 'C';
        break;
};

In this example I'm comparing the value true to each of the cases in turn, where each of those case-values is actually the result of evaluating a boolean expression. The first expression whose value matches true will fire.

Probably not much help, if you don't understand switch statements.

Edit: I just noticed that there's a gap in the logic: what if someone's average is exactly 70? Using a cascading statement like a switch or if-else, you can eliminate some of the redundant (and in this case damaging) code, thus:

if ($average >=70)
    $grade = 'A';
elseif ($average >=60)
    $grade = 'B';
elseif ($average >=50)
    $grade = 'C';
// ...
else
    $grade = 'F';

...and so on, to whatever lowest grade you're using.

Upvotes: 6

Tobias Golbs
Tobias Golbs

Reputation: 4616

You should use if/else - statements:

if($average >70)
{
   $grade = 'A';
} else if($average >=60 && $average <=69)
{
   $grade = 'B';
} else if($average >=50 && $average <=59)
{
   $grade = 'C';
}

Upvotes: 1

Related Questions