Conditional Expressions and Statements

By Herbert J. Bernstein

The basic structure of a conditional statement is:

if ( expression ) statement

Or

if ( expression ) statement_1 else statement_2

The expression is evaluated. If the resulting value is non-zero, the statement after the closing parenthesis is executed. If there is an else and if the expression evaluated to zero, the statement after the else is executed.

If if statements are nested, as in

if (expression_1) if ( expression_2 ) statement_1 else statement_2

then the else clause is associated with the closest prior if with which no else has been associated. However, a much better practice is to use explicitly nesting

if (expression_1) { if ( expression_2) statement_1 else statement_2 }

A conditional expression is of the form

expression_1 ? expression_2 : expression_3

which evaluates to the value of expression_2 if the value of expression_1 is non-zero and to the value of expression_3 is the value of expression_1 is zero.

In order to allow control over the order of evaluation of components of an expression for use in a conditional, the operators && (logical and) and || (logical or) work left to right through their operands, with execution for further operands skipped once the value of the expression has been determined.

The statement

switch ( expression ) {

case const_1: statement_1

break;

case const_2: statement_2

break;

case const_3: statement_3

break;

default: statement_default

}

has the same meaning as

if ( expression == const_1 ) {

statement_1

} else {

if ( expression == const_2 ) {

statement_2

} else {

if ( expression == const_3 ) {

statement_3

} else {

} else {

statement_default

}

}

}

}

To help understand the uses of conditional statements, let us consider a simple program which accepts strings of digits and which reports the equivalent integer numeric value:

```#include <iostream.h>

char instream[1024];

int myatoi(const char xstring[]){
int ipos = 0;        /* position within string */
int idig;            /* current numeric digit  */
int xvalue = 0;      /* tentative return value */
register char c;     /* next character from string */

while (c = xstring[ipos++]) {
switch (c) {
case ('0'): idig = 0; break;
case ('1'): idig = 1; break;
case ('2'): idig = 2; break;
case ('3'): idig = 3; break;
case ('4'): idig = 4; break;
case ('5'): idig = 5; break;
case ('6'): idig = 6; break;
case ('7'): idig = 7; break;
case ('8'): idig = 8; break;
case ('9'): idig = 9; break;
default: idig = -1;
}
if (idig == -1) return xvalue;
xvalue = xvalue*10 + idig;
}
return xvalue;
}

int main( void ) {
int num = 1;
while (num) {
cout << "Type a number: ";
cin  >> instream;
cout << (num = myatoi(instream)) << endl;
}
}
```

This program takes a very naïve approach to the characters in the input string, making no assumptions about the collation sequence of digits and not making use of library routines to help in what it is doing. A real program would use library routines, but this simple application helps us to see the pwer of the switch statement in simplifying the presentation of complex conditionals.

The first version of this program lacks some useful features. It does not handle signs, and it only handles integers. Let us add handling of signs first. We add a case for the two possible sign symbols, '-' or '+', and test if we previously had a sign, making use of a conditional expression to distinguish the two signs, and adding a conditional expression on some of the returns to allow for three cases: no sign given, '-' given or '+' given.

```#include <iostream.h>

char instream[1024];

int myatoi(const char xstring[]){
int ipos = 0;        /* position within string */
int isign = 0;       /* flag for sign:
0 not found, -1 negative, 1 positive */
int digfound = 0;    /* flag for digits found  */
int idig;            /* current numeric digit  */
int xvalue = 0;      /* tentative return value */
register char c;     /* next character from string */

while (c = xstring[ipos++]) {
switch (c) {
case ('0'): idig = 0; digfound = 1; break;
case ('1'): idig = 1; digfound = 1; break;
case ('2'): idig = 2; digfound = 1; break;
case ('3'): idig = 3; digfound = 1; break;
case ('4'): idig = 4; digfound = 1; break;
case ('5'): idig = 5; digfound = 1; break;
case ('6'): idig = 6; digfound = 1; break;
case ('7'): idig = 7; digfound = 1; break;
case ('8'): idig = 8; digfound = 1; break;
case ('9'): idig = 9; digfound = 1; break;
case ('-'):
case ('+'):
if (!isign && !digfound) {
isign = (c == '-')?(-1):1;
} else {
return (isign?isign:1)*xvalue;
}
break;
default: idig = -1;
}
if (idig == -1) return (isign?isign:1)*xvalue;
if (digfound) {
xvalue = xvalue*10 + idig;
}
}
return (isign?isign:1)*xvalue;
}

int main( void ) {
int num = 1;
while (num) {
cout << "Type a number: ";
cin  >> instream;
cout << (num = myatoi(instream)) << endl;
}
}
```

The last version of this program will accept a decimal point. We now process numbers as double instead of as int. Just as a second sign or a sign after digits terminate the number, so will multiple decimal points.

```#include <iostream.h>

char instream[1024];

double myatod(const char xstring[]){
int ipos = 0;        /* position within string */
int isign = 0;       /* flag for sign:
0 not found, -1 negative, 1 positive */
int digfound = 0;    /* flag for digits found  */
int idig;            /* current numeric digit  */
int decpos = 0;      /* position after the decimal point */
double xvalue = 0.;  /* tentative return value */
double xpow10 = 1.;  /* next (negative) power of ten */
register char c;     /* next character from string */

while (c = xstring[ipos++]) {
switch (c) {
case ('0'): idig = 0; digfound = 1; break;
case ('1'): idig = 1; digfound = 1; break;
case ('2'): idig = 2; digfound = 1; break;
case ('3'): idig = 3; digfound = 1; break;
case ('4'): idig = 4; digfound = 1; break;
case ('5'): idig = 5; digfound = 1; break;
case ('6'): idig = 6; digfound = 1; break;
case ('7'): idig = 7; digfound = 1; break;
case ('8'): idig = 8; digfound = 1; break;
case ('9'): idig = 9; digfound = 1; break;
case ('.'):
if (!decpos) {
idig = 0;
digfound = -1;
decpos++;
xpow10 /= 10.;
} else {
return (isign?isign:1)*xvalue;
}
break;
case ('-'):
case ('+'):
if (!isign && !digfound) {
isign = (c == '-')?(-1):1;
} else {
return (isign?isign:1)*xvalue;
}
break;
default: idig = -1;
}
if (idig == -1) return (isign?isign:1)*xvalue;
if (digfound > 0 ) {
if (!decpos) {
xvalue = xvalue*10. + (double)idig;
} else {
xvalue = xvalue + ((double)idig)*xpow10;
decpos++;
xpow10 /= 10.;
}
}
}
return (isign?isign:1)*xvalue;
}

int main( void ) {
double num = 1.;
while (num != 0. ) {
cout << "Type a number: ";
cin  >> instream;
cout << (num = myatod(instream)) << endl;
}
} ```