5CCYB041 Object-Oriented Programming 2022
Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit
EXAMINATION PERIOD 2 2022
5CCYB041 Object-Oriented Programming
Part A
Compulsory part. Answer all questions in Part A.
Question A.1
(a) Briefly explain what is meant by:
• a public method
• a protected data member
• a private static data member
(b) In the following code snippet, what does the const keyword mean?
1 const double pi = 3 . 14159265359;
(c) In the following code snippet, what does the const keyword mean?
1 double compute _mean ( const std::vector <double >& array);
(d) In the following code snippet, what does the const keyword on line 3
mean?
1 class Square {
2 public :
3 float get _ size() const { return _x; }
4 void set _ size( float s) { _x = s; }
5 private :
6 float _x; 7 };
Question A.2
The following is a UML diagram of a class hierarchy for handling computer pointing devices. These could implement the low-level functionality (software drivers) necessary for the computer to use a mouse, whether connected via PS/2 (old-style connector), USB, or BlueTooth.
It demonstrates how computer peripherals (e.g. a mouse) can share generic properties and behaviours despite their different hardware implementations. The implementation for using the device depends on its specific type (PS/2, USB or BlueTooth), yet the interface provided is identical from the program- mer’s point of view.
Write class definitions for the Mouse and USBMouse classes in the diagram. You only need to include the data members and member functions listed in the diagram (you do not need to provide any implementations for the member functions).
Question A.3
Write a function that evaluates the following equation:
N − 1
s =工 b(i) × x(N − 1 − i),
i=0
where b and x are two arrays and have the same length (equal to N). The function should take two input arguments (b and x) of type std::vector<double>. If b and x have different lengths, an exception should be thrown. The func- tion should return s as a variable of type double. Make sure to add all the necessary include statements.
Question A.4
A developer decides to test the C++ random number generator function and assess the distribution of generated samples. They write the following code to sample many random decimal values within a user-defined range, then bin
and display the result.
1 # include < iostream >
2 # include < vector >
3 # include <cmath >
4
5 template < class DTYPE >
6 class RandomNumber 7 {
8 public :
9 RandomNumber(DTYPE min _ value , DTYPE max _ value)
10 _min _ value = min _ value;
11 _max _ value = max _ value;
12 }
13 DTYPE Get() {
14 DTYPE v=(DTYPE)rand()/( RAND _ MAX) 15 * ( _max _ value - _min _ value) + 16 _min _ value;
17 return v; 18 }
19 private :
20 int _min _ value;
21 int _max _ value; 22 };
23
24 int main()
25 {
26 // Set the min and max value for the generator
27 int min _ value = - 10;
28 int max _ value = 10;
29 int total _ sample = 1000;
30 // Set the value to generate to stop the process
31 float stopping _ value = 0;
32 // Set the variable to store the sample occurrence
33 int range = max _ value - min _ value; 34
35 // Set and initialise bin array
36 int binned _ values[range];
37 for ( int i = 0; i < range; i++)
38 binned _ values[i] = 0;
39
40 // Generate a random value
41 RandomNumber *randNumber =
42 new RandomNumber(min_value , max_value); 43
44 // Sample values until reaching stopping criteria
45 for ( int i = 0; i < total_sample; i++) {
46 float val = randNumber ->Get();
47 // Compute the corresponding bin and update its value
48 int bin = floor(val) - min_value;
49 // cout << bin << " " << val << endl ;
50 binned_values[bin] += 1;
51 }
52
53 // Display the number of occurrence in each bin
54 for ( int i=0; i<range; ++i) {
55 cout << " [ " << i+min_value << " : " ;
56 cout << i+min_value+1 << "]␣ = ␣ " ;
57 cout << binned_values[i]/( float )total_sample << endl; 58 }
59 return 0; 60 }
The code contains five errors. Identify these errors and explain how to fix them.
Question A.5
Examine the following code. A class Trajectory1D is defined by its list of
1D positions representing the displacement of an object over time. This code
contains 5 errors. Identify, describe and correct those errors.
1 # include < iostream >
2 using namespace std; 3
4 class Trajectory1D {
5 protected :
6 vector <double > _ positions; 7
8 public :
9 Trajectory1D() {}
10
11 ∼Trajectory1D() {
12 delete _ positions; 13 }
14
15 void setPositions( const vector <double > &positions) const { 16 _ positions . clear();
17 for ( int i =0; i < positions . size(); i++) 18 _ positions[i] = positions[i];
19 }
20
21 void display() const {
22 for ( int i = 0; i < _ positions . size(); i++)
23 cout << _ positions[i] << endl; 24 }
25 };
26
27 int main() {
28 vector <double > positions;
29 positions . push _ back (1);
30 positions . push _ back (1 . 3);
31 positions . push _ back (11 . 5);
32 Trajectory1D t;
33 t - >setPositions(positions);
34 return 0; 35 }
Part B
Answer any 2 of the following 4 questions.
Question B.1
As part of a project, a student would like to evaluate which of two down- sampling techniques best preserve the information contained in a 1D signal containing integer values.
The first down-sampling technique simply extracts every other value. The intensity in the down-sampled signal D at position i is equal to the intensity in the original signal O at position 2i, so that D[i] = O[2i]. An example is shown below:
The second down-sampling technique extracts the mean value from a 3-point neighbourhood so that the value D[i] is equal to mean intensity of O[2i + j] with j ∈ [ −1, 0, 1].
To compute the information H within the signal, the student decides to use Shannon’s entropy theorem:
H =工 p(e) × log(p(e))
e
where e denote an event and p(e) its probability of occurrence. In the present case, the events correspond to the discretised signal values. In other words, each p(e) term in the equation above corresponds to the frequency of oc- curence of each possible value for the signal. If the value 1 occurs 11 times
in a signal of length 100, then its corresponding p(e) = 11/100 = 0.11. They started to implement the solution below but did not complete it.
1 # include < iostream >
2 # include < vector >
3 # include < algorithm >
4 # include < cstdlib >
5
6 class Signal{
7 public :
8 Signal( unsigned int d) : _ data (d) { } 9
10 void Random( int min _val , int max _ val) {
11 for ( unsigned int i=0; i < GetDim(); ++i) {
12 _ data[i] = min _ val + rand() % (max _ val - min _ val);
13 }
14 };
15
16 float GetEntropy() {
17 // Extract the min and max value intensity in the signal
18 int min _ value , max _ value;
19 GetIntensityRange (min _ value , max _ value); 20
21 // Create an histogram to store all occurence
22 int histo _ dim = max _ value - min _ value;
23 std::vector < int > histogram (histo _ dim , 0); 24 // Accumulate each intensity ’ s occurrence :
25 for ( unsigned int i=0; i < GetDim(); ++i){
26 histogram[ _ data[i] - min _ value ]++; 27 }
28 // Compute the entropy
29 float entropy = 0 . 0; 30 // TO COMPLETE
31 }
32
33 Signal Downsample() {
34 Signal new _ signal ((GetDim ()+1)/2);
35 for ( unsigned int i=0; i < new _ signal . GetDim(); ++i){
36 new _ signal . _ data[i] = _ data[2*i]; 37 }
38 return new _ signal;
39 }
40
41 protected :
42 std::vector < int > _ data; 43 };
44
45 int main()
46 {
47 Signal sig(50);
48 sig .Random(0,63); 49
50 std::cout << "Original␣entropy␣ value ␣ = ␣ " ;
51 std::cout << sig .GetEntropy() << std::endl;
52 std::cout << " Original␣dim␣ value ␣ = ␣ " ;
53 std::cout << sig .GetDim() << std::endl; 54
55 Signal sig2 = sig .Downsample ();
56 std::cout << "Downsampled␣dim␣ value ␣ = ␣ " ;
57 std::cout << sig2 .GetDim() << std::endl;
58 std::cout << "Downsampled␣entropy␣ value ␣ = ␣ " ;
59 std::cout << sig2 .GetEntropy() << std::endl; 60
61 Signal sig3 = sig .DownsampleMean ();
62 std::cout << "Mean␣downsampled␣dim␣ value ␣ = ␣ " ;
63 std::cout << sig3 .GetDim() << std::endl;
64 std::cout << "Mean␣downsampled␣entropy␣ value ␣ = ␣ " ;
65 std::cout << sig3 .GetEntropy() << std::endl;
66
67 return 0; 68 }
(a) The code assumes that the member function GetDim() exists, but this is currently missing. The purpose of this function is to return the number of samples in the signal (i.e. the number of elements in the variable _data). Write code to implement this function, and state where it should be placed to form part of the Signal class.
(b) The code assumes that the member function GetIntensityRange() ex-
ists (see line 19), whose purpose is to extract the minimum and maximum values in the signal, but this is currently missing. Write this function for the Signal class.
(c) The GetEntropy() member-function of the Signal class is incomplete (from line 30). Finalise it to return the signal’s Shannon entropy. En- sure that your code accounts for the potential presence of a probability of zero.
(d) Only the simple downsampling approach has been implemented. Add the corresponding DownsampleMean() member function for the Signal class
to implement the aforementioned second strategy relying on a 3-point- neighborhood.
(e) The class is missing functionality to get values at a given index. The stu- dent decides to use operator overloading to implement the square bracket operator, to make it possible to write constructs such as signal[n] to re-
trieve the nth signal value. Add the operator[] overload to implement this functionality.
Question B.2
A research team is developing a cheap wearable device to monitor cardiac function. This device measures a single electrocardiogram (ECG) signal con- tinuously at a fixed sample rate of 100Hz, and aims to perform real-time anal- ysis of the signal for early detection of problems. As part of their risk assess- ment, they identify two possible failure modes:
1. Loss of contact with the electrode. In this case, there is no effective mon- itoring, and there is a risk of problems going undetected. If this happens, the device needs to raise an alarm so the electrode can be correctly re-positioned.
2. Failure of the algorithms used in the analysis. These involve complex methods that are still under development, and could crash or hang for a variety of reasons, such as coding errors or unforeseen flaws in the algorithms used. In this case, there would be no warning issued in case of serious problems, such as cardiac arrest. As a fail-safe, the device could perform a much simpler analysis in parallel and raise an alarm if this detects any obvious abnormalities.
To guard against these failures, they decide to set up a simple independent monitoring program to run in parallel with the main analysis. Its function is purely to inspect the signal and verify that the expected level of variation is observed over a reasonable time window.
They write a small C++ program to monitor the signal, shown below. The program reads a batch of sequential measurements from its standard in- put (std::cin), then computes the range between the maximum and min- imum values observed, and issues a warning on its standard error stream
(std::cerr) if the range falls below the specified threshold.
monitor .h:
1 # include < iostream >
2 # include <fstream >
3 # include < vector >
4
5
6 class Monitor 7 {
8 public :
9 Monitor ( int batch _ size = 1024) :
10 _ size (batch _ size) {
11 _batch = new int [ _size];
12 }
13
14 bool get_next_batch () {
15 for ( int n = 0; n < _size; ++n) {
16 std::cin >> _batch[n];
17 if (!std::cin)
18 return false ; 19 }
20 return true ;
21 }
22
23 private :
24 int _size;
25 int * _batch; 26 };
main .cpp:
1 # include "monitor .h "
2
3 using namespace std; 4
5 int main () 6 {
7 const int threshold = 100; 8
9 Monitor monitor;
10 while (monitor .get_next_batch ()) {
11 int min = monitor .get_value (0);
12 int max = min;
13 for ( int n = 1; n < monitor .get_batch_size (); n++) {
14 if (monitor .get_value(n) < min)
15 min = monitor .get_value(n);
16 if (monitor .get_value(n) > max)
17 max = monitor .get_value(n);
18 }
19 if ((max -min) < threshold)
20 cerr << "WARNING : ␣signal␣variation␣too␣low " << endl; 21 }
22
23 return 0; 24 }
In each of the following questions, you do not need to write out the whole updated program. You only need to write down each change required and
state exactly where it would take place in the program. Make sure to take all your previous changes into account.
(a) The program will currently not compile as the get_batch_size() and
get_value() methods are missing. Add these to the relevant part of the program.
The get_batch_size() method should return the number of measure- ments in the batch that the program read from standard input, and the get_value() method should return the ith value in the batch, where i is passed as an argument to the method.
(b) The program is currently at risk of memory leaks as memory is allocated
but never freed. Add a destructor to the Monitor class to address this concern.
(c) The code has been reviewed by other developers on the team, and they recommend the use of the standard library’s std::vector class to hold the batch of data, rather than relying on manual memory management. Modify the code accordingly.
(d) Another recommendation from the code review is to add a method to the Monitor class to compute the range within the batch, to simplify the code in the main() function and make it more readable. Modify the code accordingly.
Question B.3
Electro-anatomical (EAM) systems are routinely used for the guidance of catheter-based ablation of cardiac arrhythmias. These systems are connected to one or several catheters which are used to map and/or ablate heart tis- sues. EAM systems enable real-time 3D visualisation of the catheters loca- tions, heart anatomy and tissue electrical properties. In this design, standard catheters can be defined by their number of electrodes and capability to mea- sure contact force (yes or no). A more specific kind of catheter has been recently developed to perform such procedures in an MRI scanner. Such MRI-compatible catheters have the same properties as standard catheters but are also defined by their number of integrated micro-coils which are used for active tracking (i.e. real-time localisation of the catheter). MR-compatible catheters can only have one of the following configurations: none, one, or two active tracking coils.
(a) Produce a UML class diagram to represent an EAM system. It should be possible to display the characteristics of the system: number of con- nected catheters and their corresponding properties. The design should allow the catheters to be simultaneously connected to other guidance systems in the future. You should use information hiding when defining your classes, but you don’t need to include inspector/mutator functions for any attributes. You also don’t need to provide any constructors in your design.
(b) Write all c++ code required to implement your design. You can assume that all class definitions will be in the same source file.
Question B.4
For their research, a group of students is required to develop a database to store information about patients. This information includes demographic in- formation about the patient (year of birth, gender, height, weight), as well as some imaging information in the form of Computer Tomography (CT), Mag- netic Resonance Imaging (MRI) and Ultra-sound (US) scans. Each scan is completed by a radiological read (analysis from a radiologist). It also includes some clinical information such as medication and disease history. Lastly, some genetic information about the patient will also need to be stored. Each patient can have several investigations of each type: imaging, clinical, genetic information. Another requirement is that the database can be stored and re- trieved from disk.
They decide to set up their database as a list of patients and produce the following UML diagram for their design:
The students need to write a small program that prints out the PatientID of each male individual who underwent an MRI scan when aged between 50 and
70 years old and who also has genetic information available in the database. They start writing the code below to match the UML design.
In the code, GenderType is an enum that can take the values Male or Female. Likewise, ImagingModality is an enum that can take the values MRI, CT and
US.
1 # include <string >
2 # include < iostream >
3 # include " Database . h "
4
5 int main()
6 {
7 // Load the existing database from disk
8 Database db;
9 db . load( " database . db " );
10
11 for ( unsigned int i=0; db . GetNumberOfPatients (); ++i) 12 {
13 // Complete the code
14 }
15 return 0; 16 }
(a) Complete their initial code of the main function (assuming all classes of
the above UML diagram have been implemented) to help them retrieve the required information.
(b) The students need to modify the program written in (a) so that they can specify the target age range, gender and modality at runtime (which were hard-coded in (a) to 50-70 years old, Male, and MRI, respectively), either via the command-line or typed in from standard input. Modify your initial code to implement this functionality (you only need to implement one of the two options between command-line and typed in from standard input).
2022-07-29