Control Flow¶
Control flow, a.k.a. flow of control, is the order of the instruction execution in an imperative program.
Types¶
Sequential
The fundamental control flow is the execution of instructions one after another in the natural order of the instructions.
Branch/Selection/Conditional
Execution of different sets of instructions according to a condition.
Loop/Iteration
Repeated executions of a sequence of instructions according to a condition
Branch¶
Branch Statements¶
if-else
boolean expression
optional else
optional {} when only one statement in its body
if, else pairing
negating logic to swap if and else blocks
switch
expression types: int, char, etc.
mandatory {}
default case
use of break statements
merged cases
break
Branch Pitfalls¶
switch on double/float values
missing break statements in switch
bad boolean expression in if
incorrect use of {}
1// ==== branch ====
2
3// ---- correct ----
4if (a > 10) cout << "a is greater than 10\n";
5
6if (a > 10)
7 cout << "a is greater than 10\n";
8
9if (a > 10) {
10 cout << "a is greater than 10\n";
11}
12
13// ---- wrong ----
14
15// empty if, will run but the if block is empty
16// the second line is not part of the if and will run always
17if (a > 10);
18 cout << "a is greater than 10\n";
19
20// missed {} so the third line is not part of the if and will run always
21if (a > 10)
22 cout << "a is greater than 10\n";
23 cout << "Please try a smaller value!\n";
24
25// will run but does not mean a is between 1 and 10
26if (1 < a < 10)
27 cout << "a is between 1 and 10\n";
28
29// switch on double
30// double value is not exact
31// this snippet may work and may cause problem
32double a;
33cin << a;
34switch (a) {
35 case 1.0:
36 ...
37 break;
38 case 2.0:
39 ...
40 break;
41 ...
42}
43
44// missing break
45// will also display "case 2" when input is 1
46switch (input) {
47 case 1:
48 cout << "Case 1" << endl;
49 case 2:
50 cout << "Case 2" << endl;
51 // ...
52}
53
54// ---- poor ----
55
56bool flag;
57// calculate flag
58if (flag == true) // should be if (flag)
59 cout << "True\n";
Branch Patterns¶
Various ways to solve the same grade conversion problem are compared below.
Multi-way branching
switch (not always work, depend on math tricks)
if-else if-…-else
nested if-else
standalone if-else
1// switch version 2// use integer division 3// not a general solution 4// why no break statements are needed here? 5char percentToLetterGrade1(int percentGrade) { 6 switch (percentGrade / 10) { 7 case 10: 8 case 9: 9 return 'A'; 10 case 8: 11 return 'B'; 12 case 7: 13 return 'C'; 14 case 6: 15 return 'D'; 16 default: 17 return 'F'; 18 } 19} 20 21// nested if-else version 22// implicit conditions 23// least comparison in the worst case 24char percentToLetterGrade2(int percentGrade) { 25 if (percentGrade >= 70) 26 if (percentGrade >= 90) 27 return 'A'; 28 else if (percentGrade >= 80) 29 return 'B'; 30 else 31 return 'C'; 32 else if (percentGrade >= 60) 33 return 'D'; 34 else 35 return 'F'; 36} 37 38// flat if-else version 39// nested only in else block 40// implicit conditions 41// most readable 42char percentToLetterGrade3(int percentGrade) { 43 if (percentGrade >= 90) 44 return 'A'; 45 else if (percentGrade >= 80) 46 return 'B'; 47 else if (percentGrade >= 70) 48 return 'C'; 49 else if (percentGrade >= 60) 50 return 'D'; 51 else 52 return 'F'; 53} 54 55// flat if version 56// no implicit condition 57// also most readable 58// more comparisons 59char percentToLetterGrade4(int percentGrade) { 60 if (percentGrade >= 90) 61 return 'A'; 62 if (percentGrade < 90 && percentGrade >= 80) 63 return 'B'; 64 if (percentGrade < 80 && percentGrade >= 70) 65 return 'C'; 66 if (percentGrade < 70 && percentGrade >= 60) 67 return 'D'; 68 if (percentGrade < 60) 69 return 'F'; 70}
Loop¶
Loop Statements¶
while
boolean expression
optional {} when only one statement in its body
do-while
boolean expression
optional {} when only one statement in its body
at least run once
not general
for
initialization; boolean expression; update
optional {} when only one statement in its body
translate to the equivalent while loop
break
continue
Break, Continue and Return¶
Modify the flow of control in a loop
- break:
jump out of the inner most loop
- continue:
jump to the start of the next round in the loop
- return:
jump out of the function
Loop Pitfalls¶
bad initial value
exit conditions are not checked right after they are changed
1// wrong! The last negative input as the terminator 2// will be added to the sum 3int input = -1; 4int sum = 0; // do not forget to initialization to 0 5while (input > 0) { // where the condition is checked 6 cout << "Please input a positive value to sum up (negative value to exit): "; 7 cin >> input; // where the condition changed! 8 sum += input; // where the mistake happens 9} 10 11// correct way 12int input; 13int sum = 0; 14while (true) { 15 cout << "Please input a positive value to sum up (negative value to exit): "; 16 cin >> input; // where the condition changed! 17 if (input < 0) 18 break; // where the condition is checked 19 sum += input; 20}
bad border conditions
check first run
check last run
1// expect print 0 to 5 2for (int i = 0; i < 5; ++i) // last round wrong should be i <= 5 or i < 6 3 cout << i << " "; 4 5// expect to get a positive integer 6int input; 7while (input < 0) { // first round wrong! input has no initial value! 8 cout << "Please input a positive value (negative value to exit): "; 9 cin >> input; 10}
variable scope problem
for (int i = 0; i < 5; ++i) cout << i << " "; cout << i; // wrong! variable i is out of scope
Loop Patterns¶
Check the chapter 2 examples.
input validation
input validation with error message
text menu operation
statistical analysis