CSE 701 Practice Test 2: Chapters 4 & 5
McMaster University, Fall 2023

Table of contents

Instructions ^

You have 1 hour to solve the exam. The only allowed material is the course lecture notes. You are not allowed to write anything on the printed notes or modify them in any way before or after printing, but you can use a highlighter. Computers, phones, tablets, and other digital devices cannot be used during the exam.

Introduction ^

We are going to write a C++ class rectangle, which represents a rectangle. The class has the following prototype:

class rectangle
{
public:
    rectangle();
    rectangle(const double);
    rectangle(const double, const double);
    double get_x() const;
    double get_y() const;
    void set(const double, const double);
    rectangle& operator*=(const double);
    friend ostream& operator<<(ostream&, const rectangle&);

private:
    double x = 0;
    double y = 0;
};
rectangle operator*(rectangle, const double);
rectangle operator*(const double, rectangle);

The class has three constructors:

  1. rectangle(): Constructs a degenerate rectangle with all its sides equal to zero.
  2. rectangle(x): Constructs a square with all its sides equal to x.
  3. rectangle(x, y): Constructs a rectangle with horizontal sides x and vertical sides y.

Note that a rectangle has 4 sides, but we only need to store 2 values, since the top and bottom sides are both equal to x and the left and right sides are both equal to y.

The class has four member functions:

  1. get_x(): Gets the horizontal side length.
  2. get_y(): Gets the vertical side length.
  3. set(): Sets both side lengths to new values.
  4. operator*=: Scales all sides of the rectangle by a given scalar and returns a reference to it.

The class also has one friend function:

  1. operator<<: Inserts the sides of the rectangle into a stream in the format [x, y] and returns a reference to the stream.

Finally, the class has two related external functions:

  1. operator* (2 overloads): Returns a copy of the rectangle scaled by a given scalar, without modifying the rectangle itself. Note that this functions has two overloads, to allow multiplication from both sides.

In each part of the test, please make sure to use correct syntax and to closely follow all the guidelines we learned in class!

Part 1: Setter function (20 points) ^

The class is encapsulated, meaning that the user cannot set the private x and y data members directly. Instead, we require the user to use set(), and ensure that it maintains the following class invariants:

  1. None of the sides can be negative.
  2. If one side is zero, the other must also be zero (i.e. there is exactly one degenerate rectangle).

If any of the invariants are not satisfied, set() should throw an invalid_argument exception with the appropriate error message instead of changing the data members.

Write down the code for the set() function, ensuring that the class invariants are checked appropriately. The user should not be able to call this function with any invalid input without generating an exception.

Part 2: Constructors (15 points) ^

Write down the code for the three constructors, ensuring that the class invariants are checked upon construction.

Part 3: Getter functions (10 points) ^

Write down the get_x() and get_y() member functions.

Part 4: Insertion operator (15 points) ^

Write down the operator<< friend function.

Part 5: Scaling operators (20 points) ^

Write down the operator*= member function and the two external operator* functions. Ensure that the class invariant is preserved when using any of these operators by checking for input that would result in a violation of the invariant and throwing an invalid_argument exception with the appropriate error message. You may wish to check section 5.2 of the lecture notes for the correct way to overload the *= and * operators.

Part 6: Test program (20 points) ^

Write down the main() function of a program to test and demonstrate the use of your new class. You can assume that the class has been defined and all relevant headers have been included; there is no need to write anything except the main() function.

Your test program should do the following:

  1. Create a degenerate rectangle A using the default constructor and print it out.
  2. Create a square B using the second constructor with sides of length 2 and print it out.
  3. Create a rectangle C using the third constructor with sides of length 3 and 4 and print it out.
  4. Attempt to create a rectangle D with sides of length -5 (negative) and 6 and print it out. This should be inside a try-catch block and the thrown exception must be caught and printed out.
  5. Attempt to create a rectangle E with sides of length 7 and 0 and print it out. This should be inside a try-catch block and the thrown exception must be caught and printed out.
  6. Change the sides of C to 8 and 9 using set() and print it out.
  7. Get the side lengths of C using get_x() and get_y() and print them out.
  8. Scale C by 10 using operator*= and print it out.
  9. Attempt to scale C by -11 (negative) using operator*= and print it out. This should be inside a try-catch block and the thrown exception must be caught and printed out.
  10. Print out C * 12 and 13 * C.

The output of your program is expected to be exactly as follows:

[0, 0]
[2, 2]
[3, 4]
Error: Sides cannot be negative!
Error: In a degenerate rectangle, both sides must be zero!
[8, 9]
x: 8, y: 9
[80, 90]
Error: Scalar cannot be negative!
[960, 1080]
[1040, 1170]

Note for the practice test ^

The real test will be very similar to the practice test. You will also be asked to create a class according to specified parameters. It is highly recommended to solve the practice exam on paper, so you can get used to writing code on paper. However, once you are done you should copy your code to a computer and make sure it compiles and the test program produces the expected output.

© 2024 Barak Shoshany