• Nem Talált Eredményt

Selective structures

4. Control program structures

4.2. Selective structures

if (b*b-4*a*c>=0) { double x1, x2;

x1 = (-b + sqrt(b*b-4*a*c))/(2*a);

x2 = (-b - sqrt(b*b-4*a*c))/(2*a);

cout << x1 << endl;

cout << x2 << endl;

} }

4.2. Selective structures

Selective structures (if, switch) decide on the following steps to be executed by a program on the basis of certain conditions. These structures allow for one-way, two-way or multiple-way branches. Selections can be nested in one another, too. Conditions are expressed by comparison (relational) and logical operations.

4.2.1. if statements

In the case of an if statement, the execution of an activity (statement) depends on the value of an expression (condition). if statements have three forms

One-way branch

In the following form of if, the statement is only executed if the value of condition is not zero (i.e. true). (It should be noted that conditions should always be within brackets.)

if (condition) statement

The functioning of the different control structures can be demonstrated by the following block diagram. The simple if statement is represented in I.7. ábra - Functioning of a simple if statement.

I.7. ábra - Functioning of a simple if statement

In the following example, the square root of the number read from the keyboard is only calculated if it is not negative:

#include <iostream>

#include <cmath>

using namespace std;

int main() { double x = 0;

cout << "x = "; cin >> x;

if (x >= 0) {

cout<<sqrt(x)<<endl;

} }

Two-way branches

In the complete version of an if statement, an activity can be provided (statement2) when the value of the condition is zero (i.e. false) (I.8. ábra - Logical representation of if-else structures). (If statement1 and statement2 are not compound statements, they should end with a semicolon.)

if (condition) statement1 else

statement2

I.8. ábra - Logical representation of if-else structures

In the following example, the if statement decides whether the number read from the keyboard is even or odd:

#include <iostream>

using namespace std;

int main() {

int n;

cout<<"Type an integer number: "; cin>>n;

if (n % 2 == 0)

cout<<"The number is even!"<<endl;

else

cout<<"The number is odd!"<<endl;

}

if statements can be nested in one another. However, in such cases, we have to be careful when using else branches. Compilers connect else branches to the closest preceding if statement.

The following example decides whether a given integer number is a positive and even number or whether it is a non-positive number. The correct solution can be realized in two different ways. One possibility is to attach an else branch containing an empty statement (;) to the internal if statement:

if (n > 0)

if (n % 2 == 1)

cout<<"Positive odd number."<< endl;

else ; else

cout<<"Not a positive number."<<endl;

Another possibility is to enclose the internal if statement in braces, that is to place it in a statement block:

if (n > 0) {

if (n % 2 == 1)

cout<<"Positive odd number."<< endl;

} else

cout<<"Not a positive number."<<endl;

This problem does not arise if statement blocks are used in the case of both if, which is by the way required by safe programming:

if (n > 0) {

if (n % 2 == 1) {

cout<<"Positive odd number."<< endl;

} } else {

cout<<"Not a positive number."<<endl;

}

In this case, both branches can be safely expanded by further statements.

I.9. ábra - Logical representation of multi-way branches

Multi-way branches

A frequent case of nested if statements is to use further if statements in else branches (I.9. ábra - Logical representation of multi-way branches).

This structure realizes multi-way branches. If any condition is true, the corresponding statement is executed. If no condition is fulfilled, only the last else statement is executed.

if (condition1) statement1 else if (condition2) statement2 else if (condition3) statement3 else

statement4

The following example decides whether number n is negative, 0 or positive:

if (n > 0)

cout<<"Positive number"<<endl;

else if (n==0) cout<<"0"<<endl;

else

cout<<"Negative number"<<endl;

A special case of else-if structures is when we check whether two elements are equal or not (==). The following example demonstrates a calculator counting the result of a simple addition and subtraction:

#include <iostream>

cout <<a<<op<<b<<'='<<c<<endl;

return 0;

4.2.2. switch statements

In fact, switch statements are statement blocks that we can enter into depending on the value of a given integer expression. The parts of the code to be executed are determined by the so-called case labels (caseconstant expressions).

switch (expression) {

caseconstant_expression1 : statements1 caseconstant_expression2 : statements2 caseconstant_expression3 : statements3 default :

statements4 }

First, switch statements evaluate the expression, then transfer control to the case label in which the value of the constant_expression equals to the value of the evaluated expression. After that, all statements are executed from the entering point until the end of the block. If none of the case constants are equal to the value of the expression, control passes to the statement with label default. If no default label is provided, control passes to the statement following the brace closing the block of the switch statement.

This little bit weird functioning is demonstrated by an exceptional example code. The following switch statement is able to count the factorial of all integer numbers between 0 and 5. (In this case, the adjective exceptional means 'not to be followed'.)

int n = 4, f(1);

switch (n) {

case 5: f *= 5;

case 4: f *= 4;

case 3: f *= 3;

case 2: f *= 2;

case 1: f *= 1;

case 0: f *= 1;

}

In most cases switch statements are used, similarly to else-if structures, to realize multi-way branches. For that purpose, all statement blocks that correspond to a case have to end with a jump statement (break, goto or return). break statements transfer control to the statement immediately following the switch block, goto to the statement with the specified label within the function block and finally return exits the function.

Since our aim is to create well functioning and easily comprehensible source codes, the number of jump statements should be reduced to a minimum level. However, the usage of break is completely allowed in switch statements. In general, statements even at the end of the default label is followed by a break since the default case can be placed anywhere within switch statements.

On the basis of the above, the calculator program of the previous subsection can be rewritten by switch in the following way:

#include <iostream>

using namespace std;

int main() {

char op;

double a, b, c;

cout<<"expression :";

cin >>a>>op>>b;

cout <<a<<op<<b<<'='<<c<<endl;

return 0;

}

The next example demonstrates how to associate the same code part to more cases. In the source code, the case labels corresponding to cases 'y' and 'Y', as well as 'n' and 'N' were placed one after the other in the switch

cout<<"The response [Y/N]?";

char response=cin.get();

In programming, program structures ensuring automatic repetitions of statements are called iterations or loops.

In C++, loop statements repeat a given statement in the function of the repetition condition until the condition is true.

while (condition) statement

for (initialisationopt; conditionopt; increment_expressionopt) statement dostatementwhile (condition)

In the case of for statement, opt means that the corresponding expressions are optional.

Loops can be classified on the basis of the place where control conditions are processed. Loops in which the control condition is evaluated before statements are executed are called pre-test loops. Any statement in the loop is executed if and only if the condition is true. Pre-test loops of C++ are while and for.