Page 1 of 1

Conditional Control Structures Tutorial: if, if-else, and switch-case using if, if-else, and switch-case to make decisions in your program Rate Topic: -----

#1 jjhaag  Icon User is offline

  • me editor am smartastic
  • member icon

Reputation: 44
  • View blog
  • Posts: 1,789
  • Joined: 18-September 07

Post icon  Posted 27 October 2007 - 03:32 PM

Conditional Control Structures Tutorial: if, if-else, and switch-case Statements


Introduction
Conditional control statements are at the very core of programming, in almost any language. The idea behind conditional control is that it allows you to control the flow of the code that is executed based on different conditions in the program, input taken from the user, the internal state of the machine the program is running on, etc. Computers are very good at doing exactly what you tell them to do, but otherwise they are really quite stupid. However, imbuing them with the ability to make decisions through the use of conditional control can make them just a wee bit smarter – they start making the decisions that you tell them to. There are three major structures related to the conditional execution of code in C/C++ - the if statement, the if-else statement, and the switch-case statement. Each will be covered here. It is also possible to use looping structures, such as for-loops and while/do-while loops to conditionally execute code. However, they are covered in another tutorial, so I will not address them here.

The if Control Statement
The ifcontrol statement is likely the first one you are going to encounter in your programming career. The if statement allows the program to execute a block of code, only if a certain condition is met. The general structure for an if statement is given by:
if ( <conditional_expression> ) {
	//conditionally executed code
}//end if statement


The conditional_expression in the if statement can be any statement that evaluates to a boolean true or false. Most often, such conditions are relational statements using the boolean relational operators ==, != , >, <, >=, or <=. These allow the program to, for example, execute a block of code only if a variable exceeds a certain value:
#include <iostream>

using namespace std;

int main() {
	int input;
	
	cout << "Enter an integer: ";
	cin >> input;
	
	if (input > 0) {
		cout << "You have entered a positive number." << endl;
	}
	
	return 0;
}


When this code is compiled and run, the program prompts the user to enter a number (note that there is no error checking to verify the validity of the input). Then, if that number is greater than zero, it tells the user that a positive number was entered. Now, this program isn’t going to be able to cook your meals for you, program your DVD-R, or take your pet chinchilla to the vet for its shots, but it’s a start. You’ve allowed your program to make a decision based on user input.

It is generally good practice to enclose all of the conditional code following an if statement, even if there is only a single line, in a set of curly braces. This makes it absolutely clear which code is going to execute when the conditional expression is true. For example, if we were to remove the braces from the above program and add another line, it becomes unclear which code is to be executed when the number is greater than zero:
int main() {
	int input;
	
	cout << "Enter an integer: ";
	cin >> input;
	
	if (input > 0)
		cout << "You have entered a positive number." << endl;
		cout << "Thank you for your input." << endl;
	
	return 0;
}


Despite the appearance of the code resulting from the indentation, the line cout << "Thank you for your input." << endl; will execute regardless of the input – it is not part of the if control structure. Just remember that C++ ignores whitespace, and doesn’t care about indentation – only explicitly defined blocks of code.

A common pitfall in if statements is the accidental use of non-relational statements as the conditional expression, such as through the use of the assignment operator = instead of the equality comparison operator ==. This can produce rather unexpected results. For instance,
#include <iostream>

using namespace std;

int main() {
	int num=25;
	if (num=4) {
		cout << "The number is equal to 4." << endl;
	}
	return 0;
}


results in the output “The number is equal to 4”, despite the fact that we initialized the variable the value of 25. This occurs because instead of testing for the equality of the variable num to the value of 4, it assigns num the value of 4 – you can check this by placing a cout << num << endl; statement after the end of the conditional block of code.

To understand this behavior, it is critical to understand how the condition expression in an if-statement is treated. The conditional is considered to be a boolean expresion, with a value of true (1) or false (0). It can also be any value that can be cast or evaluated as a boolean. In the above code, the conditional expression is essentially the same as if ( bool(num=4) ). The program first evaluates the inner expression, assigning num the value of 4. This leaves the conditional as if ( bool(num) ). And in the casting of a number to a boolean true or false, any value other than 0 will result in a true. So the expression evaluates to true, and the conditional code executes. The only way that the conditional will not execute when there is an assignment instead of a relational operator is if the value is being assigned is equal to 0. If the above program is changed to:
#include <iostream>

using namespace std;

int main() {
	int num=0;
	if (num=0) {
		cout << "The number is equal to 0." << endl;
	}
	return 0;
}


the conditionally executed code will not run. However, the assignment in the conditional statement (num=0) will still occur, resulting in the assignment of the value 0 to num. This can be a dangerous side effect, and result in many problems down the line.

One trick that experienced programmers sometime use is to place the literal first in the conditional expression. When this happens, if you accidentally use the assignment operator = instead of the comparison operator ==, the compiler will produce an error, because you are trying to assign a value to a literal, which is not possible:
#include <iostream>

using namespace std;

int main() {
	int num=25;
	if (4=num) {
		cout << "The number is equal to 4." << endl;
	}
	return 0;
}


..\main.cpp:7: error: non-lvalue in assignment
And an error is generally better than an unexpected behavior. However, this trick will not work if you are trying to compare the equality of two variables, or if you are using an inequality operator like > or <=; so generally it is a good idea to be VERY careful when typing your conditional expressions into if statements.



Alternate Execution: The if-else Control Statement
The if control structure allows for the conditional execution of a single block of code, depending on the result of a relational expression. However, that is all it does. There is no alternate behavior when the expression evaluates to false. To get such behavior, you can use the else statement, which executes a certain block of code in the event that the conditional in an if statement is false. The general form of an if-else statement is simply an extension of that for the if statement:
 if ( <conditional_expression> ) {
	//conditionally executed code
}//end if statement
else {
	//alternate code if <conditional_expression> is false
}//end else statement


Going back to our first example, we can extend it using an else statement to have another set of code execute when the conditional is false:
#include <iostream>

using namespace std;

int main() {
	int input;
	
	cout << "Enter an integer: ";
	cin >> input;
	
	if (input > 0) {
		cout << "You have entered a positive number." << endl;
	}
	else {
		cout << "You have not entered a positive number." << endl;
	}
	
	return 0;
}


In this code, if the user enters a positive number, the first block of code (following the if statement) executes. If not, the second block of code (following the else statement) executes. Again, note the use of curly braces to properly define which statements are executed. In this simple one-line case it is not absolutely necessary; however, it is a solid coding practice to get into.

if and if-else statements are not restricted to a single if-else pair. They can be organized in sequence or nested to produce linear or branching chains of logic that control the execution of multiple blocks of code. The following two programs illustrate these sequential and nested logical chains:

Program 1:
#include <iostream>

using namespace std;

int main() {
	int input;
	
	cout << "Enter an integer: ";
	cin >> input;
	
	if (input > 0) {
		cout << "You have entered a positive number." << endl;
	}
	else if (input < 0 ) {
		cout << "You have entered a negative number." << endl;
	}
	else {
		cout << "You have entered 0." << endl;
	}
	
	return 0;
}


Output:

Quote

Enter an integer: 1
You have entered a positive number.

Quote

Enter an integer: -1
You have entered a negative number.

Quote

Enter an integer: 0
You have entered 0.


Program 2:
#include <iostream>

using namespace std;

int main() {
	int input;
	
	cout << "Enter an integer: ";
	cin >> input;
	
	if (input > 0) {
		cout << "You have entered a positive number." << endl;
		if ( input%2==0 ) {
			cout << "	The number is even." << endl;
		} else {
			cout << "	The number is odd." << endl;
		}
	}
	else if (input < 0 ) {
		cout << "You have entered a negative number." << endl;
		if ( input%2==0 ) {
			cout << "	The number is even." << endl;
		} else {
			cout << "	The number is odd." << endl;
		}
	}
	else {
		cout << "You have entered 0." << endl
		cout << "	The number is even." << endl;
	}
	
	return 0;
} 

The first program simply adds another if-else control in series to test for a positive, negative, or zero input. The second expands on this by using nested if-else statements to further test whether the number is even or odd, by taking the remainder (modulus) of the number with respect to 2.

It is important to note that an else statement is not defined when it doesn’t follow (terminate) an if statement. For example, the following code will produce an error, because there is an else statement that doesn’t follow an if statement:
#include <iostream>

using namespace std;

int main() {
	
	int x=4;
	
	if (4==x) {
		cout << "The number is 4." << endl;
	}
	else {
		cout << "The number is not 4." << endl;
	}
	else {
		cout < "This else statement causes an error." << endl;
	}

	return 0;
}




The switch-case Control Statement
The other common control structure used in C++ programs is the switch-case structure. Instead of accepting any relational expression as in the if and if-else statements, switch-case structures are used to execute alternate blocks of code based on the value of a single variable. The general of the switch-case expression is given by:
switch (<test_variable>) {
	case <test_value_1>: {
		//statements to execute if test_variable is equal to test_value_1 
		break;
	}
	
	//... other case: test_value structures
	
	default: {
		//statements to execute if test_variable is not equal to 
		//any of the specified values
	}
}


The switch-case works as follows. A variable is entered as the test variable in place of <test_variable> in the above statements. When the program reaches the switch statement, it examines the value of test_variable, and compares it to the values given by test_value_1, etc. When it first reaches a value that matches the value of test_variable, it executes all of the code following that case label. If no value is found in any of the specified cases that matches the value of test_variable, the statements specified in the default case are executed. The default must always be the last case provided in the switch-case structure. The termination of each case with the break; statement will be discussed shortly; for now, it is sufficient to state that the break statement causes the switch-case structure to exit, so that no further cases will execute.

switch-case structures are frequently seen in the context of menus for simple console programs. The following program gives a very short example of such a usage:
#include <iostream>

using namespace std;

int main() {
	int input;

	cout << "1.  Welcome message:"<< endl;
	cout << "2.  Print a random number:"<< endl;
	cout << "Enter an option: ";
	cin >> input;

	switch (input) {
		case 1: {
			cout << "Welcome to a simple switch-case demonstration"<< endl;
			break;
		}
		case 2: {
			cout << rand() << endl;
			break;
		}
		default: {
			cout << "Good-bye."<< endl;
			break;
		}
	}

	return 0;
}


In this example program, the user is presented with a menu with 2 choices. If the user inputs the number 1, a greeting is displayed, the switch-case structure exits (by the break; statement), and the program terminates. If the user inputs the number 2, a pseudo-random number is printed, and the switch-case again exits and the program terminates. If neither of these two values is entered, the control reaches the default case, which prints “Good-bye”. In the default case, since it is located at the end of the structure, no break statement is required; the structure terminates automatically when it reaches the end, and then the program exits.

Note that in the above code, the body of the switch is enclosed in curly braces { and }, as is the body of each case following the colon. The braces surrounding all of the cases (following the (input) statement) are required, while the braces around each of the case bodies are not. However, as with the if and if-else statements, it is a good idea to get into the habit of including those braces, both to clarify what each case is supposed to be doing, and to limit the scope of any variables that you might declare within each case. Excluding the braces around each case body should only be done if you have good reason to, and for the moment those potential reasons are beyond the scope of this tutorial.

The inclusion of the break; statement at the end of each case is not necessary. If the break statement is excluded, C and C++ switch-case structures have a potentially useful “fall-through” behavior, where the structure continues to execute all of the code following a match with a particular case’s test_value, until a break statement or the end of the structure is reached. If the break statements are removed from the above program, the following input/output sequences result:

Quote

1. Welcome message:
2. Print a random number:
Enter an option: 1
Welcome to a simple switch-case demonstration
41
Good-bye.

Quote

1. Welcome message:
2. Print a random number:
Enter an option: 2
41
Good-bye.

Quote

1. Welcome message:
2. Print a random number:
Enter an option: 3
Good-bye.


This fall-through behavior can be useful, for example, in executing a single menu option when one of several possible sequences are inputted, such as in the following program:
#include <iostream>

using namespace std;

int main() {
	char input;

	int nobreak=1;
	while (nobreak) {
		cout << "Do you want to quit?"<< endl;
		cin >> input;

		switch (input) {
			case 'n':
			case 'N': {
				cout << "Loop will continue"<< endl;
				break;
			}
			case 'y':
			case 'Y': {
				cout << "Good-bye!"<< endl;
				nobreak=0;
				break;
			}
			default: {
				cout << "Unkown option, menu loop will continue"<< endl;
			}
		}
	}

	return 0;
}


In this program, the menu runs in a loop, asking the user if s/he wants to quit. If ‘n’ is entered, the program goes to the start of the case with that value. The case is empty, and since it has no break statement, the program falls through and executes the code for the ‘N’ value. Then it hits a break statement, and the loop continues. If the user had entered ‘N’ to start with, the switch statement would have gone to that case first, but the same sequence of execution would occur after that. If the user enters ‘y’, a similar behavior occurs – the switch goes first to the ‘y’ case, then falls through and executes the ‘Y’ case. Then the variable nobreak is set to 0 and the program breaks out of the switch with the break statement. And then since the value of nobreak is now 0, the while loop terminates and the program exits.



Conclusions
That about covers it for now. Hopefully, you are now ready to go forth and write flexible programs that can make decisions for themselves.

And for anyone who is programming in pure C rather than C++, fear not. Other than the use of cout, cin, namespaces, and the particular headers used, all of the lessons in this tutorial can be readily applied to C. The syntax is of the if, if-else, and switch-case structures are identical, and the recommendations are the same.

Is This A Good Question/Topic? 0
  • +

Replies To: Conditional Control Structures Tutorial: if, if-else, and switch-case

#2 Lt_Kernel  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 48
  • Joined: 05-September 07

Posted 17 November 2007 - 07:49 AM

The simplest form of an 'if - then' construct expressed in C is as follows. 
	If (x == 10) 
	 DoSomething(x); 

If an if - then type construct has more than one statement to execute C uses curly braces to enclose the statements as follows... 

	If (x > 10) 
	 { 
		DoFirstThing; 
		DoSecondThing; 
	 } 

C also allows the use of any non zero variable as the test in an if statement.  As long as the variable is non-zero the test evaluates true and the following statement executes. 

	If (x) DoSomething; 

The exclamation point indicates the not statement in C.  In the following example if 'not x'  the statement following will execute (in otherwords if x is zero, which makes the statement false, the '!' (not) operator will change the test result to true, so that the following statement executes)... 

   If (!x) DoSomething; 

The else construct uses the following syntax...(Note the way the curly braces are used to seperate the if construct from the else construct...) 

   If (x == 20) 
	 { 
		DoSomething; 
		DoAnotherThing; 
	 } 
   else 
	 { 
		DoSomethingElse; 
		DoSomeOtherThing; 
	 } 

If statements can be nested as follows... 

   If (x > 10) 
	 If (x < 20) 
		 DoSomething; 

Nesting can also become more complex by including multiple statements, which then requires the use of the curly braces to delimit the blocks of code... 

	if (x > 10) 
	  { 
		 DoSomethingOne; 
		 If (x < 20) 
		   { 
			  DoSomeOtherthing; 
			 If (x = 15) 
			   { 
				   DoThatThing; 
				   DoThisThing; 
			   } 
			} 
	   } 
   else  if (x > 0) 
		 { 
			DoSomethingElse; 
			If (x = 1) 
			  { 
				 DoWhatEver; 
				 DoWhatEverElse; 
			  } 
		 } 
   else { 
			DoThis; 
			DoThat; 
		  } 


u mean like this?
and in your code above can you please tell me where is the "PRIMARY Expression " before "ELSE"?
i always have that problem!

This post has been edited by Lt_Kernel: 17 November 2007 - 07:59 AM

Was This Post Helpful? 0
  • +
  • -

#3 jjhaag  Icon User is offline

  • me editor am smartastic
  • member icon

Reputation: 44
  • View blog
  • Posts: 1,789
  • Joined: 18-September 07

Posted 25 November 2007 - 04:44 PM

View PostLt_Kernel, on 17 Nov, 2007 - 07:49 AM, said:

u mean like this?
and in your code above can you please tell me where is the "PRIMARY Expression " before "ELSE"?
i always have that problem!


I'm not exactly sure what you mean by these statements...exactly what are you referring to when you say "like this"? The "code" that you posted is not legal C - the "if"s cannot be capitalized, and the statements like DoFirstThing; and DoSecondThing; are not valid statements without some other context. Your post is more of a hybrid between C and pseudocode than it is actual code.

And as for the primary expression before else, are you talking about a compiler error that you frequently receive? Because such an error can be generated when you either have multiple else statements in sequence (each else-statement needs to be preceded by an if-statement), or you have an else statement without any if statement. But again, if you're refering to the code in your post above, that's got some serious problems that make it not legal C.

Please clarify your statements. I'd love to help, but I have very little idea what you're talking about.

And, please don't post code together with text in code blocks. The lack of line wrapping makes the text portions impossible to read. Use separate blocks for each segment of code using the code tags.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1