CSC 101 Lecture Notes Week 3

CSC 101 Lecture Notes Week 3
More on Arithmetic Expressions;
Output Formatting;
Introduction to Logical Expressions and Conditionals




  1. Note the following update to the class schedule and reading assignment for this week.
    1. This week we will cover both Chapter 3 and most of Chapter 5 of the book.
    2. The revised reading assignment for this week is as follows:
      1. All of Chapter 3; this reading is pertinent to programming assignment 2.
      2. Pages 185-230 of Chapter 5; this is pertinent to programming assignment 3, coming up next week.

  2. Summary of arithmetic operators
    1. The following table lists all of the C++ arithmetic operators:
      + Unary plus
      - Unary minus
      + Addition
      - Subtraction
      * Multiplication
      / Floating point division (floating point result)
      Integer division (no fractional part)
      % Modulus (remainder from integer division)
    2. C++ provides two short-hand operators for incrementing and decrementing
      ++ increment the value of a variable by 1
      -- decrement the value of a variable by 1
      1. The expression x++ is equivalent to the assignment statement x = x + 1.
      2. The expression x-- is equivalent to the assignment statement x = x - 1.
      3. The increment and decrement operators may appear before or after the name of the variable being incremented or decremented.
    3. Note: increment and decrement operators my appear within expressions, as well as by themselves in a statement.
      1. E.g.,
        x = y++ * 10;
        
      2. For now, you should only use the increment decrement operators as stand-alone statements, not within expressions.

  3. Precedence rules
    1. C++ follows the same rules for operator precedence as in normal math.
    2. The precedence of C++ operators is as follows:
      ( ... ) highest
      * / % next highest
      + - lowest
    3. This means, for example, that the value of the following expression
      1 + 2 * 3
      
      is 7, since the 2 * 3 subexpression is evaluated first.
    4. Parentheses can be used to alter the normal precedence of expressions, as in
      (1 + 2) * 3
      
      which has the value 9, since the parentheses force the evaluation of 1 + 2 to be done first.
    5. Where there are multiple operators of the same precedence in one expression, they associate to from left to right.
    6. This means the expression
      1 - 2 + 3
      
      associates as
      (1 - 2) + 3
      

  4. Type coercion and type casting
    1. Integer and floating point values are stored differently in computer memory.
    2. An integer variable cannot physically hold a floating point number, and vice versa.
    3. Therefore, in an assignment statement of the form
      some_int = 2.5
      
      C++ truncates the floating point value 2.5 to the integer value 2.
    4. Similarly, the assignment
      some_float = 2
      
      converts the integer 2 into the floating point value 2.0 and stores it in the floating point variable.
    5. These forms of conversion are called type coercion, since they involve converting a value of one type to another type.
    6. Type coercions occur during mixed int/float expression evaluation as follows:
      1. the int operand is temporarily coerced to float
      2. the operation is performed on two float operands
      3. the result is float
    7. The following table summarizes the type coercion done by the compiler in any arithmetic expression

      type of
      left operand
      type of
      right operand
      type of
      result
      int int int
      int float float
      float int float
      float float float
    8. Type coercion is performed implicitly by the compiler.
    9. There is also something called type casting, that is a form of data conversion performed explictly by the programmer.
      1. E.g., the following expression
        float x, y, z;
        
        x = int(x + z);
        
        explicitly converts the result of y + z to an int (i.e., truncates off the fractional part, if any).
      2. The general form of a type cast is

      3. Explicit type casting is not all that useful between just int and float types, but later in the quarter we will see casting used in more useful ways with other C++ data types.
      4. For now, the following is a handy use of a cast that accomplishes the normal kind of rounding of real numbers to integers:
        some_int = int(some_float + 0.5);
        

  5. Output manipulators
    1. Output manipulators allow fine-grain control of output format of numeric values.
      1. They are used as additional terms in a cout statement.
      2. The manipulators are setw(n) and setprecision(n)
    2. The setw manipulator controls the total width (in character positions) of numeric output, both int and float.
    3. The setprecision manipulator controls the precision (i.e., number of digits) of float output.
    4. An example of using setw is the following:
      int i, j, k;
      
      i = 123;
      j = 1234;
      k = 12;
      
      cout << setw(4) << i << setw(5) << j << setw(3) << k;
      
      which outputs
    5. An example of setprecision is
      #include <iostream.h>
      #include <iomanip.h>
      
      int main () {
      
          float x, y, z;
      
          cout.setf(ios::fixed, ios::floatfield);     // Set up floating point
          cout.setf(ios::showpoint);                  //   output format
      
          x = 12.345;
          y = 12.3456;
          z = 12.3;
      
          cout << setprecision(5) << x << "," << setprecision(8) << y << ","
               << setprecision(4) << z << endl;
      }
      
      which outputs
      12.34500,12.34560013,12.3000
      
      1. The two statements "cout.setf(...)" are described below.
      2. Notice the inaccuracy of the output for y.
        1. This is the result of the fact that numeric values are stored in a fixed amount of computer memory.
        2. This means that large integer values and multi-digit real values cannot always be accurately represented.
        3. We will discuss this issue further later in the quarter.
    6. There are two other issues involving output formatting of floating point numbers:
      1. Normally C++ will not print a decimal point if a floating point number has no fractional part; e.g., if a floating point variable x = 10.0, then
        cout << x
        
        prints the value as just 10, not 10.0.
      2. The second issue is the use of scientific notation for large floating point numbers; e.g., if a floating point variable x = 123456789.5, then
        cout << x
        
        prints the value as 1.234567E+08, i.e., 1.234567 * 108.
      3. Both of these issues are addressed by including the cout.setf(...) statements in a program before any cout statements are executed.
    7. Important notes about setw and setprecision
      1. To use the setw and setprecision manipulators, you must include the library <iomanip.h> (in addition to <iostream.h>).
      2. setw only applies to the immediately following item in a cout.
      3. In contrast to setw, setprecision stays in effect until another setprecision appears.

  6. Introduction to the C++ conditional statement
    1. Back in Lecture 1, we saw the following simple use of a conditional statement:
      #include <iostream.h>           // The C++ input/output library
      
      int main() {                    // C++ programs always start with this header
      
          int x;                      // Declare a variable to hold the input number
      
          cin >> x;                   // Input the number typed on the screen
      
          if (x > 0)                  // Check if the number is > 0 (i.e., positive)
              cout << "yes";          //   If so, output "yes" to the screen
          else                        //   If not,
              cout << "no";           //      output "no" to the screen
      
      }                               // End of main program (matches the "{")
      
    2. In C++, the if statement is used to make a decision in a program.
      1. Such decisions are fundamental to computer programming.
      2. They allow a program to perform a different computation, based on the outcome of some test of program data values.
    3. In these notes, we will examine more advanced uses of the C++ conditional statement.

  7. Updating program 1 to use conditionals
    1. In the change making program of assignment 1, we made two assumptions about the input:
      1. The inputs are correctly entered as positive integer values.
      2. The amount tendered is greater than or equal to the purchase amount.
    2. In the assignment writeup, it was stated that you (the programmer) could rely on these assumptions to be true.
    3. Question: is relying on such user input assumptions a good idea in a program?
      1. The answer is most definitely NO.
      2. Programs should be written to behave sensibly under all possible inputs.
      3. In many cases, in order to produce sensible behavior, input values must be checked to ensure that they are legitimate.
      4. When one or more inputs is not legitimate, then the program should output an appropriate error message and terminate its computation 1.
    4. So, suppose we want to update the change making program to check for the two assumptions and behave accordingly based on the outcome of the checks.
    5. We will do so now.

  8. Updating the change program to check for a valid amount tendered.
    #include <iostream.h>
    
    int main() {
    
        //
        // Declare program variables to hold the purchase amount, amount tendered,
        // total change amount, and the amounts of each denomination of change,
        // from dollars to pennies.
        //
        int purchase;                       // Amount of purchase
        int tendered;                       // Amount tendered
        int change;                         // Total change due
    
        //
        // Prompt for and input the amount of purchase.
        //
        cout << "Input the amount of the purchase, in cents: ";
        cin >> purchase;
    
        //
        // Prompt for and input the amount tendered.
        //
        cout << "Input the amount tendered, in cents: ";
        cin >> tendered;
    
        if (tendered < purchase) {
            cout << "Sorry, your purchase cannot be completed since"
                 << endl
                 << " the amount tendered is less than the amount of the purchase."
                 << endl;
        }
        else {
    
            //
            // ... The rest of the change computation goes here ...
            //
    
        }
    }
    

  9. Updating the change program to check for a positive inputs.
    #include <iostream.h>
    
    int main() {
    
        //
        // Declare program variables to hold the purchase amount, amount tendered,
        // total change amount, and the amounts of each denomination of change,
        // from dollars to pennies.
        //
        int purchase;                       // Amount of purchase
        int tendered;                       // Amount tendered
        int change;                         // Total change due
    
        //
        // Prompt for and input the amount of purchase.
        //
        cout << "Input the amount of the purchase, in cents: ";
        cin >> purchase;
    
        //
        // Prompt for and input the amount tendered.
        //
        cout << "Input the amount tendered, in cents: ";
        cin >> tendered;
    
        if (tendered <= 0 || purchase <= 0) {
            cout << "Sorry, your purchase cannot be completed since"
                 << endl
                 << " both inputs must be greater than zero."
                 << endl;
        }
        else {
    
            //
            // ... The rest of the change computation goes here ...
            //
    
        }
    }
    

  10. Updating the change program to check for both positive inputs and valid amount tendered.
    #include <iostream.h>
    
    int main() {
    
        //
        // Declare program variables to hold the purchase amount, amount tendered,
        // total change amount, and the amounts of each denomination of change,
        // from dollars to pennies.
        //
        int purchase;                       // Amount of purchase
        int tendered;                       // Amount tendered
        int change;                         // Total change due
    
        //
        // Prompt for and input the amount of purchase.
        //
        cout << "Input the amount of the purchase, in cents: ";
        cin >> purchase;
    
        //
        // Prompt for and input the amount tendered.
        //
        cout << "Input the amount tendered, in cents: ";
        cin >> tendered;
    
        if (tendered <= 0 || purchase <= 0) {
            cout << "Sorry, your purchase cannot be completed since"
                 << endl
                 << " both inputs must be greater than zero."
                 << endl;
        }
        else if (tendered < purchase) {
            cout << "Sorry, your purchase cannot be completed since"
                 << endl
                 << " the amount tendered is less than the amount of the purchase."
                 << endl;
        }
        else {
    
            //
            // ... The rest of the change computation goes here ...
            //
    
        }
    }
    

  11. An alternative (and inferior) way to check for both assumptions.
    #include <iostream.h>
    
    int main() {
    
        //
        // Declare program variables to hold the purchase amount, amount tendered,
        // total change amount, and the amounts of each denomination of change,
        // from dollars to pennies.
        //
        int purchase;                       // Amount of purchase
        int tendered;                       // Amount tendered
        int change;                         // Total change due
    
        //
        // Prompt for and input the amount of purchase.
        //
        cout << "Input the amount of the purchase, in cents: ";
        cin >> purchase;
    
        //
        // Prompt for and input the amount tendered.
        //
        cout << "Input the amount tendered, in cents: ";
        cin >> tendered;
    
        if (tendered <= 0 || purchase <= 0 || tendered < purchase) {
            cout << "Sorry, your purchase cannot be completed since"
                 << endl
                 << " both inputs must be greater than zero, and"
                 << endl
                 << " the amount tendered cannot be less than the amount of purchase."
                 << endl;
        }
        else {
    
            //
            // ... The rest of the change computation goes here ...
            //
    
        }
    }
    

  12. The syntax of the C++ if statement.
    1. The general syntax of the C++ if statement is as follows:

    2. Note that
      1. A semicolon is required after each statement, even though it's not shown in this syntax diagram (it's shown in the syntax diagrams for other statements).
      2. The basic syntax allows only one statement in each branch of the if.
      3. In order to have more than one statement in either part, a block statement must be used.
    3. Syntax of a C++ block statement

  13. C++ logical expressions
    1. C++ provides two categories of operators for the logical expressions used in if statements and elsewhere in programs.
    2. The relational operators are:
      == Equal to
      != Not equal to
      > Greater than
      < Less than
      >= Greater than or equal to
      <= Less than or equal to
    3. The logical operators are
      && Logical and
      || Logical or
      ! Logical not
    4. The precedence of relational and logical operators, in comparison to arithmetic operators and assignment, is as follows:
      ! Highest precedence
      * / % |
      + - |
      < <= > >= |
      == != |
      && |
      || v
      = Lowest precedence

  14. A Boolean datatype for C++
    1. The type of all C++ logical expressions is int
      1. An integer value of zero represents the false outcome of a logical expression.
      2. An non-zero integer value represents a true outcome.
    2. In older versions of C++, there is no built-in datatype for boolean values, i.e., the values true and false.
      1. The central UNIX C++ compiler is for such older versions.
      2. Also, the textbook is written for the older versions of the language (see in particular pages 188-190).
    3. To define a boolean datatype for older C++, the following definitions are included in a program:
      typedef int Boolean;
      const Boolean TRUE = 1;
      const Boolean FALSE = 0;
      
    4. In the current version of C++, these definitions are no longer necessary, since a datatype bool and constants true and false are built-in to the language.

  15. Two very common C++ mistakes.
    1. Question: what's wrong with the following if statement?
      if (result <= 0)
          cout << "The result must be positive; program will force it." << endl;
          result = 1;
      else
          cout << "Result is good so far." << endl;
      
      result = result * 10;
      
    2. Answer: the curly braces are missing around the two statements in the if part.
    3. Question: what's wrong with the following if statement?
      if (result = 0) {
          cout << "The result must be non-zero; program will force it." << endl;
          result = 1;
      }
      else {
          cout << "Result is good so far." << endl;
      }
      
    4. Answer: the expression result = 0 should be result == 0.
    5. Recommendations:
      1. Always use curly braces around both if and else parts of an if statement, even if there is only one statement in the if and/or else part.
      2. Look very closely at if expressions to make sure that double equals is used to test for equality.




index | lectures | labs | handouts | assignments | solutions | grades | help

Footnotes:

1 It is possible in some circumstances for a program to ignore or even correct incorrect inputs, such that the program need not terminate. We will discuss such more sophisticated behavior later in the quarter.