# The dangling else ambiguity in the if-statement

• Ambiguity problem in the IF-statement

• Java's if statement has an ambiguity problem...

Question: write a Java program to print out the shipping cost as follows:

• Shipping charge is always \$5.00, except:
• If shipped to Hawaii, USA (HI), shipping charge is \$10.00
• If shipped outside USA, shipping charge is \$20.00

• Proposed solution:

 ``` double shippingCharge; shippingCharge = 5.00; if ( country.equals("USA") ) if ( state.equals("HI") ) shippingCharge = 10.00; // Shipping to Hawaii is \$10 else shippingCharge = 20.00; // Shipping to outside USA is \$20 ```

• Is there a problem with this program ???

• Ambiguity: more than one way to read a program

 ``` double shippingCharge; shippingCharge = 5.00; if ( country.equals("USA") ) if ( state.equals("HI") ) shippingCharge = 10.00; // Shipping to Hawaii is \$10 else shippingCharge = 20.00; // Shipping to outside USA is \$20 ```

Can be read as:

First way to associate "else" to "if" Second way to associate "else" to "if"
```
double shippingCharge;

shippingCharge = 5.00;
if ( country.equals("USA") )
if ( state.equals("HI") )
shippingCharge = 10.00;
else
shippingCharge = 20.00;
```
```
double shippingCharge;

shippingCharge = 5.00;
if ( country.equals("USA") )
if ( state.equals("HI") )
shippingCharge = 10.00;
else
shippingCharge = 20.00;
```

Or after indenting it properly:

First way to associate "else" to "if" Second way to associate "else" to "if"
```
double shippingCharge;

shippingCharge = 5.00;
if ( country.equals("USA") )
if ( state.equals("HI") )
shippingCharge = 10.00;
else
shippingCharge = 20.00;
```
```
double shippingCharge;

shippingCharge = 5.00;
if ( country.equals("USA") )
if ( state.equals("HI") )
shippingCharge = 10.00;
else
shippingCharge = 20.00;
```

• This phenomenon is called the dangling else ambiguity - it can only happen when the last else keyword can be associated with 2 different if keyword...

• How Java reads an IF statement

• To resolve this ambiguity, the Java (C/C++) language uses the following rule:

 An else keyword always associates with the closest if that does NOT cause a syntax error

• Therefore, the Java compiler will read this program as:

Program Text as written Program Text as understood by Java compiler
```
double shippingCharge;

shippingCharge = 5.00;

if ( country.equals("USA") )
if ( state.equals("HI") )
shippingCharge = 10.00;
else
shippingCharge = 20.00;
```
```
double shippingCharge;

shippingCharge = 5.00;

if ( country.equals("USA") )

if ( state.equals("HI") )
shippingCharge = 10.00;
else
shippingCharge = 20.00;
```

• This is due to the rule that an else keyword must be associated to the closest if keyword does NOT cause a syntax error

• This program will do the following computation:

• Shipping cost is \$5.00, except
• If shipped to USA, then:

• if shipped to HI, shipping cost = \$10.00
• otherwise (to the other states in USA), shipping cost = \$20.00

• Obviously, it's NOT what we want...

• How to force Java to associate an ELSE keyword to the first IF keyword in the example

• We must use "{" and "}" to force an "else" to associate with the first "if" by enclosing the THEN part inside the { and } pair:

 ``` double shippingCharge; shippingCharge = 5.00; if ( country.equals("USA") ) { if ( state.equals("HI") ) shippingCharge = 10.00; // Shipping to Hawaii is \$10 } else shippingCharge = 20.00; // Shipping to outside USA is \$20 ```

• Placing the braces "{" and "}" around the then part removes the ambiguity as follows:

• When the if ( country.equals("USA") ) part is encountered, the Java compiler will look for one of these 2 possible statements:

 ``` if ( condition ) one-statement ```

Or:

 ``` if ( condition ) one-statement else one-statement ```

• The next thing that follows "if ( country.equals("USA") )" is { - which signals a compound statement (which counts for 1 statement)

So the compiler will consider this as the THEN part of the "if ( country.equals("USA") )":

 ``` double shippingCharge; shippingCharge = 5.00; if ( country.equals("USA") ) { // THEN part if ( state.equals("HI") ) shippingCharge = 10.00; } else shippingCharge = 20.00; ```

• And after detecting the else keyword, the Java compiler wil consider this as the ELSE part of the "if ( country.equals("USA") )":

 ``` double shippingCharge; shippingCharge = 5.00; if ( country.equals("USA") ) { if ( state.equals("HI") ) shippingCharge = 10.00; } else shippingCharge = 20.00; // ELSE part ```

• Also, there is no syntactically correct way to associate the else keyword with the second if:

Because if we try to associate the else keyword with the second if, we will find a syntax error:

• Consider what happens if we try to associate the ELSE to 2nd IF:

 ``` double shippingCharge; shippingCharge = 5.00; if ( country.equals("USA") ) { if ( state.equals("HI") ) shippingCharge = 10.00; } else shippingCharge = 20.00; ``` ``` Re-written separately to enhance focus: if ( state.equals("HI") ) shippingCharge = 10.00; } else shippingCharge = 20.00; ```

• The extra "}" without a corresponding "{" between the "IF" and "ELSE" keywords prevents Java from associating the "ELSE" to the second "IF" keyword !

• Moral of the story...

• Many programmers do not like to deal with the ambiguity issue (what you write down may not be what you ment) and prefer to write unambigious statements

• You can do this easily by always writing the THEN part and ELSE part between braces {...}

• So always write an if statement as:

 ``` OR: if ( Condition ) if ( Condition ) { { statements... statements... } } else { statements... } ```