25-Comp-A4 Program Design and Data Structures · December 2014
Nivaar worked solution (AI-drafted; not reviewed by a licensed engineer)
Paper format. 98-Comp-A4 Program Design and Data Structures, December 2014 — 3 hours, closed book, no calculator permitted. Nine questions, each of equal weight (20 marks); candidates answer any six, so a complete paper is 120 marks. Pseudocode or any high-level language is accepted, and the examiner's note states explicitly that marking emphasises the operation of the program, not syntactic details. All nine questions are answered below, because the whole set is the more useful revision resource. Answers are given in C or C++ as the question dictates; each is compilable as written, but a clear, correctly reasoned pseudocode answer would earn the same marks.
Reference texts for this subject.
The Computer Engineering citation list is built around architecture and networking texts (Patterson & Hennessy, Tanenbaum, Mano); this subject is programming and data structures, so the works above are cited instead.
Question text not reproduced: the examination questions are © Engineers and Geoscientists BC. Open the official past paper (linked at the top of this page) to read the question, then follow the worked solution below.
Given. A required class name, a required split into a header and an implementation file, and a required feature list: construction with and without initialisation, read and write access to both parts, addition, subtraction, multiplication, and printing.
Find. The two files, with an interface that supports every listed operation and an implementation whose arithmetic is correct for all signs.
Approach. Treat Complex as a value type: two
double members, no dynamic memory, compound assignment as members
and binary operators as free functions built on them, with the multiplication
identity written out explicitly.
double members suffice. Because the
class owns no pointer, no file handle and no other resource, the
compiler-generated copy constructor, assignment operator and destructor are all
correct as they stand and none should be written — the “rule of
zero”. This is a deliberate design decision, not an omission.Complex z; and sets the number to
$0 + 0i$; a two-argument constructor with a default for the imaginary part
covers both Complex z(3.0, 4.0); and Complex z(3.0);.
Leaving that constructor implicitly convertible is what makes
2.0 + z legal, matching how the standard library's own
std::complex behaves./* ---------- Complex.h ---------- */
#ifndef COMPLEX_H
#define COMPLEX_H
#include <iostream>
class Complex {
public:
/* Declaration WITHOUT initialisation: Complex z; -> 0 + 0i */
Complex();
/* Declaration WITH initialisation: Complex z(3.0, 4.0); or Complex z(3.0);
Deliberately NOT marked explicit, so that a real number converts to a
Complex and expressions such as 2.0 * z compile. */
Complex(double re, double im = 0.0);
/* Read access */
double real() const;
double imag() const;
/* Write access */
void setReal(double re);
void setImag(double im);
/* Compound arithmetic: members, because they modify the left operand */
Complex &operator+=(const Complex &rhs);
Complex &operator-=(const Complex &rhs);
Complex &operator*=(const Complex &rhs);
void print(std::ostream &os = std::cout) const;
private:
double re_;
double im_;
};
/* Binary arithmetic as FREE functions so that the left operand converts too:
2.0 + z works here, but would not if these were member functions. */
Complex operator+(Complex lhs, const Complex &rhs);
Complex operator-(Complex lhs, const Complex &rhs);
Complex operator*(Complex lhs, const Complex &rhs);
std::ostream &operator<<(std::ostream &os, const Complex &z);
#endif /* COMPLEX_H *//* ---------- Complex.cc ---------- */
#include "Complex.h"
Complex::Complex() : re_(0.0), im_(0.0) {}
Complex::Complex(double re, double im) : re_(re), im_(im) {}
double Complex::real() const { return re_; }
double Complex::imag() const { return im_; }
void Complex::setReal(double re) { re_ = re; }
void Complex::setImag(double im) { im_ = im; }
Complex &Complex::operator+=(const Complex &rhs)
{
re_ += rhs.re_;
im_ += rhs.im_;
return *this;
}
Complex &Complex::operator-=(const Complex &rhs)
{
re_ -= rhs.re_;
im_ -= rhs.im_;
return *this;
}
Complex &Complex::operator*=(const Complex &rhs)
{
/* (a + bi)(c + di) = (ac - bd) + (ad + bc)i.
a and b MUST be saved first: writing re_ before im_ is computed would
feed the new real part into the imaginary part. */
const double a = re_, b = im_;
const double c = rhs.re_, d = rhs.im_;
re_ = a * c - b * d;
im_ = a * d + b * c;
return *this;
}
void Complex::print(std::ostream &os) const
{
os << re_;
if (im_ < 0.0) os << " - " << -im_ << "i";
else os << " + " << im_ << "i";
}
/* Take lhs BY VALUE: the copy is the result, so no temporary is named. */
Complex operator+(Complex lhs, const Complex &rhs) { return lhs += rhs; }
Complex operator-(Complex lhs, const Complex &rhs) { return lhs -= rhs; }
Complex operator*(Complex lhs, const Complex &rhs) { return lhs *= rhs; }
std::ostream &operator<<(std::ostream &os, const Complex &z)
{
z.print(os);
return os;
}/* ---------- example use ---------- */
#include "Complex.h"
int main()
{
Complex z0; /* no initialisation -> 0 + 0i */
Complex z1(3.0, 4.0);
Complex z2(1.0, -2.0);
z0.setReal(-1.5); /* write access */
std::cout << z1.real() << '\n'; /* read access -> 3 */
std::cout << z1 + z2 << '\n'; /* 4 + 2i */
std::cout << z1 - z2 << '\n'; /* 2 + 6i */
std::cout << z1 * z2 << '\n'; /* 11 - 2i */
std::cout << 2.0 + z1 << '\n'; /* 5 + 4i, via the converting ctor */
return 0;
}| Requirement | Provided by | Check |
|---|---|---|
| Declaration without initialisation | Complex() | Complex z; → 0 + 0i |
| Declaration with initialisation | Complex(double, double = 0.0) | Complex z(3,4); → 3 + 4i |
| Read access | real() const, imag() const | returns 3 and 4 |
| Write access | setReal(), setImag() | mutates in place |
| Addition | operator+ via operator+= | (3+4i) + (1−2i) = 4 + 2i |
| Subtraction | operator- via operator-= | (3+4i) − (1−2i) = 2 + 6i |
| Multiplication | operator* via operator*= | (3+4i)(1−2i) = 11 − 2i |
| Printing | print() and operator<< | prints “11 - 2i” |
| File split | Complex.h / Complex.cc | declaration and definition separated |