Short Question 1: - Hong Kong University of Science and Technology

advertisement
Hong Kong University of Science and Technology
COMP104: Programming Fundamentals and Methodology
Fall 2003, Lecture Section 1, 2
Final Examination
Wednesday 17 December, 4:30 – 7:30PM
Student Name:
Student ID:
Lecture Section:
key
Lab Section/TA Name:
Instructions:
1. This is a closed-book, closed-notes examination.
2. Check that you have all 19 pages (including this cover page).
3. Write your name, student ID, lecture section, lab section/TA name on this page.
4. Please circle your answer.
5. Answer all questions in the space provided. Rough work should be done on the
back pages.
Question
Score
1
/6
2
/5
3
/4
4
/8
5
/3
6
/5
7
/3
8
/4
9
/8
10
/7
11
/6
12
/10
13
/4
14
/17
15
/10
Total
/100
1
Questions 1 & 2 – Pointers
Question 1: (6 marks)
a) (4 marks) What is the output of the following program?
#include <iostream>
using namespace std;
void main( ){
int a[3] = {1, 3, 5 }, b = 23, c = 48;
int *p1 = a,
*p2 = &b,
*p3 = 0;
p1++;
(*p1)++;
p3 = p2;
*p3 = p1[1];
for(int i = 0; i < 3; i++)
cout << a[i];
cout << endl;
cout << b << endl;
}
Answer:
145 (1 mark for each digit)
5
b) What is the output of the following program? (2 marks)
#include <iostream>
using namespace std;
void swap(int* left, int* right) {
int* p;
p = left;
left = right;
right = p;
}
void main( ){
int a = 3, b = 5;
swap(&a, &b);
cout << a << " " << b << endl;
}
Answer:
3 5
(1 mark each)
2
Question 2: (5 marks)
Please fill the blank part of the following code. Your task is to store the data of 2D array A to 1D
array P. Important: You must use pointer arithmetic to access the values of P instead of subscripts.
#include <iostream>
using namespace std;
const int m = 3;
const int n = 5;
void main( ){
int A[m][n] = {
{1, 2, 3, 4, 5},
{6, 7, 8, 9, 10},
{11, 12, 13, 14, 15}
};
int i, j;
int * P = new int[m * n];
// Store the data of 2D array a[3][5] to 1D array P[15]
// Add your code below
// -----------------------------------------for(i = 0; i < m*n; i++)
cout << P[i] << " ";
cout << endl;
}
Answer:
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
*(P + i*n + j) = A[i][j];
-1 for each mistake , -2 if P[i*n+j] = A[i][j]
-2 if the arithmetic formula P+i*n+j is incorrect
3
Questions 3 & 4 – Dynamic Objects
Question 3: (4 marks)
What is wrong with the following code?
#include <iostream>
using namespace std;
1
int main() {
2
int a = 5, *p = &a;
3
int *q = new int ;
4
*q = *p;
5
cout << a << “ “ << *p << “ “ << *q;
6
delete p;
7
return 0;
8
}
Answer:
2 marks - The memory unit pointed by p is not dynamically allocated, so
“delete p” (line 6) is wrong.
2 marks - We should delete the memory unit allocated by q to avoid memory
leak, so “delete q” is necessary before “return 0” (line 7).
Or a direct correction is also allowed: Replace “delete p” with “delete
q”.
4
Question 4: (8 marks)
Write a function that given a POSITIVE integer, returns a pointer to an integer array with the
following properties:
1.
The size of the array is equal to the length of this integer.
2.
Each element in the array contains a digit of this integer.
3.
The storage order should be like this: the most significant digit is stored in the 0th position of
the array, the second most significant digit is stored in the 1st position of the array, …, the
least significant digit is stored in the last position of the array.
For example, given 14582, your function should return a pointer to an array {1, 4, 5, 8, 2}.
The function prototype is given here:
int* decompose(int num);
Hint: Use dynamic objects and assume memory allocation is always successful.
Answer:
int* decompose (int num) {
int result = num;
int count = 1;
// Find count – 3 marks
while (result >= 10) {
result /= 10;
count ++;
}
int *p = new int[count];
// allocate dynamic array – 1 marks
result = num;
// set array values – 3 marks
for (int i = 0; i < count; i++) {
p[count-1-i] = result % 10; // -2 if reversed: p[i] = result%10
result /= 10;
}
return p;
// return result - 1 mark
}
also:
-4 if returns pointer to static local array
5
Question 5 & 6 – Struct
Question 5: (3 marks)
Find the errors in the following code. Give the line number and error description.
1
struct S1 {
2
int a;
3
S2 b;
4
};
5
struct S2 {
6
int a;
7
S1 b;
8
S2 c;
9
};
10 S2 s = 3;
Answer:
Line 3 : member b uses struct 'S2' before it is defined
Line 8 : recursive definition of S2 not allowed
Line 10 : assigning an integer value to a variable of type struct S2 is
illegal
6
Question 6: (5 marks)
Given the following declaration and definitions:
#include <string>
struct St_StudentName{
string EnglishName;
string ID;
};
struct St_StudentScore{
string ID;
int score;
};
St_StudentName stu1[100];
St_StudentScore stu2[100];
The array stu1 contains a list of all the students’ EnglishNames and IDs. The array stu2
contains a list of the same students (possibly in a different order) with their IDs and scores.
Complete the following code segment to output the score of all students with the name “Tom” (e.g.,
the score of “Tom” is output, but the score of “Tommy” is not).
for(int i = 0; i < 100; i++){
…
// add an if statement here
…
// add a for statement here
…
// add an if statement here
cout << stu2[j].score << endl;
}
Answer:
for(int i = 0; i < 100; i++){
if(stu1[i].EnglishName == "Tom")
for(int j = 0; j < 100; j++)
if(stu2[j].ID == stu1[i].ID)
// 2 marks
// 1 marks
// 2 marks
cout << stu2[j].score << endl;
}
7
Questions 7 to 10 – Linked List
Question 7: (3 marks)
The following program is supposed to allocate nodes, put them into a linked list, print them out
and then destroy them. Fix the bugs in the program.
#include <iostream>
using namespace std;
struct linkedList{
int number;
linkedList* next;
};
1
int main() {
2
linkedList* head=NULL;
3
linkedList* current;
4
for(int i=0;i<10;i++){
5
current = new linkedList;
6
current->number = i;
7
current.next = head;
8
head = current;
9
}
10
while(head->next!=NULL){
11
cout << head->number << endl;
12
current = head->next;
13
delete current;
14
head = current;
15
}
16
return 0;
17 }
Answer:
1 mark: line 7: change to “current->next = head;”
1 mark: line 10: change to “while(head!=NULL){”
1 mark: line 13: change to “delete head;”
(or lines 12-14 change to:
current = head;
head = head->next;
delete current;
)
8
Question 8: (4 marks)
What is the output of the following program?
#include <iostream>
using namespace std;
struct myList{
int data;
myList* next;
};
int main() {
myList* head;
myList* cur;
myList* previous=NULL;
for(int i=0;i<4;i++){
head=new myList;
head->data=0;
head->next=previous;
for(cur=previous;cur!=NULL;cur=cur->next)
head->data+=1+2*cur->data;
previous=head;
}
while(previous!=NULL){
cout<<previous->data<<endl;
cur=previous;
previous=previous->next;
delete cur;
}
return 0;
}
Answer:
13
4
1
0
(1 mark each)
9
Question 9: (8 marks)
The function below should insert a value as the head of a given UNORDERED linked list. Be
careful to first search for the given value. The value is inserted only if it does not exist in the list. If
the value exists, the function does nothing.
struct linkedList{
int data;
linkedList* next;
};
The function prototype is given. Implement the function.
void insert(linkedList* &head, int value);
Answer:
void insert(linkedList* &head, int value){
linkedList* cur;
for(cur=head; cur!=NULL; cur = cur->next) // 2 marks
if(cur->data == value)
return;
cur
= new
linkedList;
// 1 mark
// 1 mark
// 1 mark
cur->data = value;
// 1 mark
cur->next = head;
// 1 mark
head = cur;
// 1 mark
}
(-1 mark for each mistake)
10
Question 10: (7 marks)
Write a RECURSIVE function that searches for a given element in an unordered linked list (no
marks will be given unless it is recursive). The function should return true if the element is found
and false otherwise. The node definition and function prototype are:
struct Node {
int
data;
Node
*next;
};
bool recursiveSearch(Node* Head, int searchElement);
Answer:
bool recursiveSearch(Node* Head, int searchElement) {
if (Head == NULL)
// 2 marks
return false;
else if (Head->data == searchElement) // 2 marks
return true;
else
return recursiveSearch(Head->next, searchElement);
// 3 marks
}
11
Question 11 – Circular Linked List (6 marks)
Below is part of an insertion function for inserting a node at the rear of a circular linked list. Please
complete the missing part of this implementation.
void insertRear(NodePtr& Rear, int item) {
NodePtr New;
New = new Node;
New->data = item;
// answer the missing part using the space below
}
The node definition is:
struct Node {
int
data;
Node
*next;
};
Answer:
if(Rear == NULL){ // insert into empty list – 3 marks
Rear = New;
Rear->next = Rear;
return;
}
// insert to end of the list - 3 marks
New->next = Rear->next;
Rear->next = New;
Rear = New;
12
Question 12 – Doubly linked list (10 marks)
Given an unordered doubly linked list (without dummy head and not circular), where the node is
defined as:
struct Node {
int
data;
Node*
next;
Node*
prev;
};
typedef Node* NodePtr;
Write a function
void ReverseDoublyLinkedList(NodePtr& pHead)
that reverses the given list pHead. Note that:

Your function should accept the head pointer of the list and modify the pointers.

Your program must be short and simple; Note: marks will be deducted if your program has
more than 7 semicolons.

The original list is a doubly linked list that does NOT have a dummy head node, therefore it
is NOT a circular doubly linked list.
10
20
40
55
70
Head
Answer:
void ReverseDoublyLinkedList(NodePtr& head) {
if(head == NULL)
// do nothing empty list
return;
while(head->next != NULL) {
NodePtr temp = head->next;
head->next = head->prev;
head->prev = temp;
head = head->prev;
}
head->next = head->prev;
head->prev = NULL;
}
OR
13
void ReverseDoublyLinkedList(NodePtr& head) {
if(head == NULL)
// do nothing empty list
return;
NodePtr cur = head;
while(cur != NULL) {
//
reverse pointers
NodePtr temp = cur->next;
cur->next = cur->prev;
cur->prev = temp;
cur = cur->prev;
}
while(head->prev != NULL)
// move head pointer to other end
head = head->prev;
}
OR
void ReverseDoublyLinkedList(NodePtr& head) {
if(head == NULL)
// do nothing empty list
return;
NodePtr cur = head;
while(cur != NULL) {
//
reverse pointers
NodePtr temp = cur->next;
cur->next = cur->prev;
cur->prev = temp;
head = cur;
// move head behind cur
cur = cur->prev;
}
}
Marking scheme:
Overall scheme:
+10 marks if all correct (-1 for each minor bug if nearly all correct)
+5 if have swap idea (-1 for each minor bug related to swap)
+0 if nothing or long answer
Also:
-1 if fails for empty list
-1 if fails for list with one node
-2 if fails to reverse links on last node
-1 if Head not reset
-1 for each semicolon beyond 7
-1 for each additional unique mistake
14
Question 13 & 14 – Class / ADT
Question 13: (4 marks) What is the output of the following program?
#include <iostream>
using namespace std;
class cPoint {
public:
cPoint();
cPoint(int x1, int y1);
int getX();
int getY();
void print();
private:
int x;
int y;
};
cPoint::cPoint(){
x = y = 0;
cout << "Default Constructor called" << endl;
}
cPoint::cPoint(int x1, int y1){
x = x1;
y = y1;
cout << "Explicit-Value Constructor called" << endl;
}
void cPoint::print(){
cout << "(" << x << "," << y << ")" << endl; }
int cPoint::getX(){
return x;
}
int cPoint::getY(){
return y;
}
void sum(cPoint p1, cPoint p2){
cPoint( (p1.getX()+p2.getX()), (p1.getY()+p2.getY()) ).print();
}
void main(){
cPoint p1(1,2);
cPoint p2;
sum(p1,p2);
}
Answer:
Explicit-Value Constructor called
// 1 mark each
Default Constructor called
Explicit-Value Constructor called
(1,2)
15
Question 14: (17 marks)
A polynomial P(X) = C[0] + C[1]*X1 + … + C[i]*Xi + …+ C[99]*X99 can be represented by the class
below (where the highest power of the polynomial is limited to 99):
class Polynomial {
public:
Polynomial();
void set(string n, double *A, int numCoefficients);
void display();
int maximum_order() const;
Polynomial add(const Polynomial G) const;
private:
string name;
// name of the polynomial
double C[100]; // C[i] = coefficients of the term Xi
};
For example, assuming an object of type Polynomial T is declared with the name “T1” with C[0],
C[1], C[2] set to 1,2,3 respectively and C[j] = 0 for 99 >= j >=3, then T is equivalent to the
polynomial
T1(x) = 1 + 2*X1 + 3*X2.
a) (3 marks) Write the default constructor of this class, where the default name of the polynomial
is “F”, and all the coefficients are set as zero.
Polynomial::Polynomial() {
name = "F";
for (int i=0;i<100;i++)
C[i] = 0.0;
}
16
b) (4 marks) The program code below is supposed to define P as P(X) = 1 + 2*X1 + 3*X2
double A[ ] = {1,2,3};
Polynomial P;
P.set(“P”,A,3);
A Comp104 student implements the member function set() as below
void set(string n, double *A, int numCoefficients) {
int i;
name = n;
if(numCoefficients <= 100)
for(i=0; i<=numCoefficients; i++)
C[i] = A[i];
else
cout << "The index is too large, exiting program";
exit(0);
}
Correct the bugs.
Answer:
// 1 mark - the function should be void Polynomial::set(string n, double
*A, int numCoefficients)
// 1 mark - should be for(i=0; i < numCoefficients; i++)
// 1 mark - C[i] should be set as zero for numCoefficients <= i <= 99.
//
e.g., add the code below before if(numCoefficients <= 100)
for(int j=0;j<100;j++)
C[j] = 0;
// 1 mark - Add parenthesis (curly brackets) to the else statement
17
c) (7 marks) Write the member function add(). If polynomials p and q are P(x) = -3X + 2*X15 and
Q(x) = 7 + 3X - 3*X15 respectively, then r = p.add(q); set r as result(x) = 7 - 1*X15
Polynomial Polynomial::add(const Polynomial G) const {
Polynomial result;
// 1 mark
result.name = "result";
// 1 mark
for (int i=0;i<100;i++)
// 1 mark
result.C[i] = C[i] + G.C[i]; // 3 marks
return result;
// 1 mark
}
d) (3 marks) Write the member function maximum_order(), which returns the maximum order
of a polynomial. E.g., if polynomial p is P(x) = -3X + 2*X15, p.maximum_order() returns 15. If
polynomial q is Q(x) = 100, then q.maximum_order() returns 0.
int Polynomial::maximum_order() const {
int i;
for(i=99;i>0;i--)
if (C[i] != 0.0)
break;
return i;
}
-1 for each mistake
(0 marks if incorrectly starts scanning from beginning of array)
18
Question 15 – Dynamic Class (10 marks)
The following models a queue of passengers at a bus stop. The struct Passenger models a
passenger waiting for a bus, and the class BusStop models a bus stop. A BusStop has a linked
list of passengers.
struct Passenger {
int waitingTime;
// waiting time for passenger at bus stop
Passenger *next;
// pointer to next passenger
};
class BusStop {
public:
BusStop();
~BusStop();
void addPassenger(); // call when new passenger arrives & set waitingTime=0
void incrWaitingTimes(); // increment waitingTime of all Passengers by one
void pickupPassengers();
int length() const;
// call when bus arrives
// return number of passengers waiting
double averageWaitingTime() const; // calculate avg waiting time of
// all passengers currently at bus stop
private:
Passenger *head;
int size;
// pointer to linked list of passengers
// number of passengers
};
BusStop::BusStop () {
head = NULL;
size = 0;
}
a) (5 points) Implement the destructor BusStop::~BusStop(). Do not call any other member
functions.
BusStop::~BusStop () {
while(head != NULL) {
Passenger *cur = head;
head = head->next;
delete cur;
}
}
Minor mistake: -1 each
+1 if answer only deletes first node of list
0 marks if calls pickupPassengers()
19
b) (5 points) Implement BusStop::averageWaitingTime(). This function returns the
average waiting time of passengers currently at the bus stop.
double BusStop::averageWaitingTime() const {
double time = 0;
// either time or size must be double type
Passenger *cur = head;
while(cur != NULL) {
time += cur->waitingTime;
cur = cur->next;
}
if(size==0)
// 1 mark
return 0;
return time / size;
}
Each minor mistakes -1 mark
-3 marks if it destroys head
-3 marks if doesn’t access cur->waitingTime
-2 marks if both size and time are integers causing integer division
-1 if has division by zero when size=0
20
Download