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