2007 Midterm ECE106
2007 Midterm ECE106
ECE 106S
PROGRAMMING FUNDAMENTALS
Spring 2007
Midterm Test
This exam is open textbook and open notes. Use of computing and/or communicating
devices is NOT permitted.
Do not remove any sheets from this test book. Answer all questions in the space provided.
No additional sheets are permitted.
Work independently. The value of each part of each question is indicated. The total value
of all questions is 100.
Write your name and student number in the space below. Do the same on the top of each
sheet of this exam book.
Name: ___________________________________
(Underline last name)
Page 1 of 22
Question 1. (7 marks). General.
Answer the following questions either by Yes or No, or by providing a very brief and direct
answer when indicated.
(a) Yes or No? Suppose that all memory that is allocated using new is correctly de-allocated using
delete. Then program memory can never be exhausted.
(b) Yes or No? A single next instruction in the DDD debugger allows running a function to
completion.
(c) Yes or No? The following code ensures that the value of xp cannot be modified in main().
class X {
int x;
int get() const;
};
int main()
{
class X *xp;
xp->get();
}
(d) Yes or No? An object file (e.g., main.o) can be executed by changing its name to
main.exe and typing the command ./main.exe at the Linux command prompt.
(e) What is the name of the software tool you use in the lab to convert your C++ code into an
executable program?
(f) Yes or No? One should always use delete to destroy memory allocated with new before
returning from a function?
(g) Yes or No? If you do not provide a copy constructor for your class, a default one will be
created for you.
Page 2 of 22
Question 2. (12 marks). The Make Utility.
The following table shows several invocations of the Make utility using the above correct
Makefile. For each invocation, indicate the commands that are executed as a result of the
invocation, in the order in which they are invoked. To simplify providing an answer, the lines of
the Makefile are numbered as shown above; just indicate the line number corresponding to a
command in the table provided below. The invocations of Make are in the order shown in the
table.
Assume that the Makefile exists in the same directory as all the .cc and .h files.
Recall that the touch command simply updates the timestamp of its argument to the current
time.
Page 3 of 22
Make Invocation Commands Executed (indicate line number)
make clean
make recurse.o
make difftool
make all
touch difftool
make
touch diffdata.h
make
Page 4 of 22
Question 3. (9 marks). Pointers and Memory Management.
Assume that the following code will compile and run properly.
1 int a = 6;
2 int *b = &a;
3
4 int *
5 foo(int **c)
6 {
7 (**c)++;
8 *c = b;
9 int *d = new int;
10 *d = 10;
11 // Point #1
12 return d;
13 }
14
15 int
16 main()
17 {
18 int e = 7;
19 int *f = &e;
20
21 f = foo(&f);
22 (*f)++;
23 // Point #2
24 return 0;
25 }
(a) (3.5 marks). Complete the following diagram by showing the values of variables and/or
pointers when execution reaches the point labeled “Point #1”. For an integer variable,
simply show the integer value inside the corresponding box. For a pointer, indicate the value
of the pointer by drawing an arrow from the box corresponding to the pointer to the box
corresponding to the variable the pointer points to.
a b c
d e f
new int
Page 5 of 22
(b) (3.5 marks). Complete the following diagram by showing the values of variables or pointers
when execution reaches the point labeled “Point #2”. For an integer variable, simply show
the integer value inside the corresponding box. For a pointer, indicate the value of the
pointer by drawing an arrow from the box corresponding to the pointer to the box
corresponding to the variable the pointer points to. Cross out any variables, pointers or
memory allocations that no longer exist.
a b c
d e f
new int
(c) (2 marks). While the program will run correctly as written, it contains a non-fatal memory
allocation problem. Write the single line of code that will fix the error. Specify the line
number in the program after which the line of code should be inserted.
Page 6 of 22
Question 4. (8 marks). Scopes.
The following class definition describes a simple C++ class called sampleClass.
#include <iostream>
using namespace std;
class sampleClass {
private:
int val;
public:
sampleClass();
sampleClass(int v);
~sampleClass();
};
sampleClass::sampleClass()
{
val = 0;
cout << "Constructing " << val << endl;
}
sampleClass::sampleClass(int v)
{
val = v;
cout << "Constructing " << val << endl;
}
sampleClass::~sampleClass()
{
cout << "Destructing " << val << endl;
}
Page 7 of 22
Consider the following code, which uses sampleClass:
sampleClass a(1);
void f1()
{
sampleClass a[2];
cout << "Leaving f1()" << endl;
return;
}
sampleClass *f2()
{
sampleClass *a = new sampleClass(2);
cout << "Calling f1()" << endl;
f1();
cout << "Leaving f2()" << endl;
return a;
}
int main()
{
sampleClass a(3);
if ((2 + 2) == 4) {
cout << "Calling f2" << endl;
sampleClass *a = f2();
cout << "Back from f2" << endl;
delete a;
}
cout << "Leaving main" << endl;
return 0;
}
Page 8 of 22
In the space provided below, write the output that an execution of the above program would
produce in the order in which it is produced. Use one entry in the table for each line of output
produced.
Page 9 of 22
Question 5. (12 marks). Classes and Objects.
struct triplet {
int first;
int second;
int third;
};
class mystery {
private:
int x;
int y;
struct triplet* the_triplet;
public:
mystery(int f, int s, int t);
~mystery();
mystery & mystery_member(const mystery & other) const;
};
mystery::~mystery() {
delete the_triplet;
}
Page 10 of 22
(a) (6 marks). Indicate by placing an X in the appropriate column whether each of the following
statements that appear in the body of a main() function that uses mystery is valid, or not
valid given the definition of mystery above. A statement is valid if it compiles and
executes correctly. A statement is not valid if it either generates a compile-time error, or if it
compiles correctly, but produces a run-time error (i.e., the programs stops with an error as
soon as the statement is executed). Assume that each of the statements is independent of the
others.
mystery g;
mystery f(1,2,3);
cout << f.y;
mystery f(1,2,3);
mystery g(4,5,6);
g=f;
mystery f(1,2,3);
mystery g(4,5,6);
if(g<f) return (0);
mystery f(1,2,3);
mystery g(4,5,6);
mystery_member(g) = f;
(b) (6 marks). Indicate by placing an X in the appropriate column whether each of the following
statements that appear in the body of the member function mystery_member is valid, or
not valid given the definition of mystery above. A statement is valid if it compiles
and executes correctly. A statement is not valid if it either generates a compile-time error, or
if it compiles correctly, but produces a run-time error (i.e., the programs stops with an error
as soon as the statement is executed). Assume that each of the statements is independent of
the others.
Page 11 of 22
Question 6. (8 marks). Memory Management.
Consider the following definition of the two classes, database and element.
class database {
private:
int count;
element** thearray;
public:
:
:
:
};
class element {
private:
int count;
char* name;
public:
:
:
:
};
The public functions of each of the two classes include the constructors, accessor methods and
the destructor.
A main function uses these class definitions to construct a database object called
mydatabase and many element objects as shown in the figure below.
means NULL
count
thearray
0 1 2 3 dynamically allocated array n-1
mydatabase
dynamically
allocated count count count
name name name
objects of type
element
Page 12 of 22
(a) (4 marks). Write the following constructors for the two classes, database and element.
The constructor for element should initialize count to 0 and name to an empty string. The
constructor for database should initialize count to 0 and dynamically create an n element
array as shown in the figure above. Each element of the array should be initialized to NULL.
database::database(int n) {
element::element() {
(b) (4 marks). Write the destructors of the two classes, database and element such that no
memory leaks exist when the object mydatabase goes out of scope. Note that all variables
are dynamically allocated as indicated in the above figure, except mydatabase, which is an
automatic variable. Write your code in the space provided below.
database::~database() {
element::~element() {
Page 13 of 22
Question 7. (12 marks). Objects.
struct pair {
int first;
int second;
};
class usePair {
private:
bool valid;
struct pair* thepair;
public:
usePair();
usePair(int f, int s);
~usePair();
void setFirst(int f);
void setSecond (int s);
usePair & operator= (usePair rhs);
void print();
};
#include "usepair.h"
#include "iostream"
using namespace std;
usePair::usePair() {
valid = true;
thepair = new struct pair;
thepair->first = 0;
thepair->second = 0;
}
usePair::usePair(int f, int s) {
valid = true;
thepair = new struct pair;
thepair->first = f;
thepair->second = s;
}
usePair::~usePair() {
delete thepair;
}
void usePair::setFirst(int f) {
thepair->first = f;
}
void usePair::setSecond(int s) {
thepair->second = s;
}
Page 14 of 22
usePair & usePair::operator= (usePair rhs) {
valid = rhs.valid;
thepair->first = rhs.thepair->first;
thepair->second = rhs.thepair->second;
rhs.thepair->first = thepair->second;
rhs.thepair->second = thepair->first;
return (*this);
};
void usePair::print() {
cout << “(“ << thepair->first
<< “,” << thepair->second
<< “)” << endl;
}
Now consider the following main function, which uses the above class.
#include “iostream”
#include “usePair.h”
using namespace std;
int main () {
usePair a(1,1);
usePair b(4,16);
usePair c = b;
usePair d;
a.print(); // Statement # 1
b.print(); // Statement # 2
c.print(); // Statement # 3
d.print(); // Statement # 4
a.setFirst(0);
b.setFirst(8);
c.setSecond(20);
d.setFirst(5);
d.setSecond(10);
a.print(); // Statement # 5
b.print(); // Statement # 6
c.print(); // Statement # 7
d.print(); // Statement # 8
a=b;
d=c;
a.print(); // Statement # 9
b.print(); // Statement # 10
c.print(); // Statement # 11
d.print(); // Statement # 12
return (0);
Page 15 of 22
Indicate what is being printed by each statement in the above main function. For simplicity, each
statement that produces output has been given a number, and you can write the output of each
statement in the table below.
Statement # Output
10
11
12
Page 16 of 22
Question 8. (9 marks). Linked Lists.
(a) (3 marks). You are given two pointers P and Q to the singly-linked list shown below.
Assume that each node in the list contains a data field (of type integer) and a next field.
Use the P and Q pointers to switch the positions of the nodes B and C so that the nodes
occur in the order A, C, B and D. Do not simply swap the integer values associated with
nodes B and C. Also, do not change the values of P and Q and do not use any additional
variables.
A B C D
1 2 3 4
data next
P Q
(b) (6 marks). You are again given two pointers P and Q to the list shown below. Use these
pointers to switch the positions of the nodes B and E so that the nodes occur in the order A,
E, C, D, B and F. Do not simply swap the integer values associated with nodes B and E, and
do not change the values of P and Q. You can declare and use one additional variable.
A B C D E F
1 2 3 4 5 6
data next
P Q
Page 17 of 22
Question 9. (6 marks). Tree Traversals.
(a) (3 marks). Give the inorder, preorder, and postorder traversals of the tree shown below. The
tree represents the mathematical expression x – y + z.
- z
x y
Inorder Traversal:
Preorder Traversal:
Postorder Traversal:
(b) (3 marks). The following tree is a Binary Search Tree (BST) that contains all integers
between 1 and 14. Give the inorder traversal of the tree.
10
6 11
2 7 12
1 3 9 14
5 8
13
Inorder Traversal:
Page 18 of 22
Question 10. (5 marks). Tree Traversals.
Write a recursive function to perform the triple-order traversal of a binary tree, meaning that for
each node of the tree, the function first visits the node, then traverses its left subtree (in triple-
order), then visits the node again, then traverses its right subtree (in triple-order), then visits the
node again. Hence, the triple-order traversal of the tree shown below is:
3 4 2 2 2 4 1 1 1 4 3 5 5 5 3.
4 5
2 1
Write a recursive function to perform the triple-order traversal of a binary tree. Assume that
visiting a node simply prints its key to cout. Your code should be very short (5-6 lines)!
Excessively long code will be penalized.
class treenode {
public:
int data;
treenode *left;
treenode *right;
};
treenode *Root; // root of the tree
Page 19 of 22
Question 11. (6 marks). C++ I/O.
Your task is to expand the command parser from Lab 3 to implement an additional operation,
printmultiple, which accepts multiple student numbers and prints out a record for each
student. The command format is:
The first parameter, N, indicates the number of student numbers that follow on the line. The
following examples are both valid commands:
printmultiple 0
Done.
printmultiple 2 987654321 987654320
OUTPUT FOR STUDENT 987654321 APPEARS HERE
OUTPUT FOR STUDENT 987654320 APPEARS HERE
Done.
If any of the numbers are invalid (e.g., “foo” or “-12”), you should skip processing the
remainder of the line without printing an error message. You may assume that you have
access to the following function, which handles the printing of the student record:
The printStudent function will return a false value if the student number does not exist in
the database; in this event, you should skip the remaining student numbers, without printing
an error message. When you are finished processing the printmultiple command (whether
there were errors or not) you should print “Done”. You are not expected to handle any other
errors, or produce any additional output.
Using only the cin operator for input, complete the following code fragment for processing a
single printmultiple command:
char buffer[MAX_COMMAND_SIZE];
// ...
if (!strcmp(buffer, “printmultiple”)) {
Page 20 of 22
Question 12. (6 marks). Recursion.
A tail-recursive function is a special kind of recursive function in which after completing all
other operations, the function simply calls itself and returns the result of this call. Below, the
factorial function is shown on the left. Write a tail-recursive factorial function. A template for
this function is shown on the right.
int int
factorial(int n) factorial( )
{ {
if (n <= 1) return 1;
return n * factorial(n-1);
}
return factorial( );
}
Page 21 of 22
THIS PAGE IS INTENTIONALLY BLANK FOR ANSWER OVERFLOWS
Page 22 of 22