Name (2 pts):
Section (2 pts):
Question 1 (10 pts):
int doSomething(int &x, int y) { int temp = y; y = x/2; x = temp/2; cout << x << " " << y << endl; return y; }Indicate whether each of the following code snippets will compile. If so, state what the program will print. If not, state the reason.
cout << doSomething(20, 30) << endl; cout << 20 << " " << 30 << endl; Does not compile. You can't pass an integer literal by reference.
int a = 10; const int b = 20; cout << doSomething(a, b) << endl; cout << a << " " << b << endl; 10 5 5 10 20
int a = 20; cout << doSomething(a, a) << endl; cout << a << " " << a << endl; 10 10 10 10 10
Functions are an abstraction; abstraction within the implementation of a class, but not available to clients of that class, is just as important in managing the complexity of the program as is the abstraction modeled by the class itself. Helper functions used by public methods to simplify the code, or allow code reuse, should be private methods, especially if they must manipulate private data members.
Question 3 (12 pts):
switch(color) { case red: cout << "Your lips are like sweet roses" << endl; break; case blue: cout << "Your eyes are limpid pools of loveliness" << endl; case green: cout << "Your hair is like a waterfall," << " only with Mountain Dew(tm)," << " except on the sides, where it is more like the green on" << " hole 5 at Pebble Beach." << endl; case black: cout << "That's the coolest shirt I've ever seen." << " Einstuerzende Neubauten rule!" << endl; default: cout << "How can I describe your beauty?" << endl; }Choose the best method of defining color, red, blue, green, and black, such that the above code will compile. Give a brief justification of your method.
enum COLOR { red, blue, green, black }; COLOR color;Enumerated types have the advantages that the compiler will type check them, and only valid values can get assigned (as opposed to integer constants, where color would be defined as an int and could therefore take on an unexpected value).
Question 4 (10 pts):
Consider the following definition of class Fraction:
class Fraction { public: ... // all the member functions go here private: char *value; // a dynamically allocated string containing the value of the // Fraction, such as "22/7" }What advantages does this representation have over using two C++ ints? What disadvantages does it have? Does the client care which implementation you use? Why or why not?
There is (practically) no possibility of overflow in terms of storage and operations performed on fractions. Implementation of arithmetic operators and the expand function will be more difficult (and slower). The client should not care, since the differences are hidden behind the abstraction barrier, although it is acceptable to say that the client might care because this implementation might be slower etc.
Question 5 (12 pts):
void Dog::eat(Food f) { if(like(f)) { tail.wag(); } else { bite(owner); } }Which of the following could tail be? Check all that apply
XX a public data member of Dog
XX a private data member of Dog
__ a public member function of Dog
__ a private member function of Dog
XX a global variable
__ a local variable
__ an enumerated type
Circle the answer that is most appropriate, and give a brief justification.
If tail were a global variable, all dogs would have to share the same tail. If tail were a public data member, clients of the dog class would be able to access a dog's tail directly, which is probably not the intent of the dog class.
Question 6 (8 pts):
void swap(int* x, int* y) { int temp = *x; *x = *y; *y = temp; } void sneakySwap(int x, int y) { swap(&x, &y); cout << x << " " << y << endl; }What is printed by the following code?
int a = 10; int b = 20; sneakySwap(a, b); cout << a << " " << b << endl; 20 10 10 20Question 7 (20 pts):
class IntList2 { public: IntList2(); isEmpty(); getSize(); void start(); void advance(); bool atEnd(); int getData(); void insertBefore(int item); void insertAfter(int item); void deleteItem(); private: IntStack front; IntStack rear; int size; }; bool IntList2::isEmpty() { return front.isEmpty() && rear.isEmpty(); } void IntList2::advance() { assert(!atEnd()); front.push(rear.pop()); } bool IntList2::atEnd() { return rear.isEmpty(); } int IntList2::getData() { assert(!rear.isEmpty()); return rear.top(); } void IntList2::insertAfter(int item) { assert(!atEnd()); front.push(rear.pop()); rear.push(item); size++; } void IntList2::deleteItem() { assert(!atEnd()); rear.pop(); size--; }Implement the following:
void IntList2::insertBefore(int item) { rear.push(item); size++; } void IntList2::start() { while(!front.isEmpty()) { rear.push(front.pop()); } } int IntList2::getSize() { // this may involve adding to the private // part of the class and/or the implementations of // the above functions return size; }Question 8 (16 pts):
int factorial(int x) { assert(x >= 0); if(x == 0) { return 1; } int total = x--; while(x > 0) { total *= x--; } return total; }Assume the above function will be used by developers who are instructed never to use it on negative values. Should you include any error handling code? Why or why not? If so, add the most appropriate type of error handling code above.
Error handling code will aid developers in finding bugs should they misuse the function, so it is probably a good idea to include it. However, assuming the input is valid is consistent with the scenario given and is just as correct.
Now, assume that the code might get called on negative values, but you would like to allow the program to recover gracefully. Add error handling code to the function below. Why did you choose this method of error handling?
Returning a safe value (zero or some negative number) seems the best choice because such a value can easily be distinguished from a valid answer, does not require changing the interface (which would be bad or impossible), and is simple for a developer to use. Those who pointed out that the code already returns the negative value if one is given (i.e. does the same thing as the three lines of added code), and that the programmer could check this return value to see if it had worked, received full credit.
int factorial(int x) { if(x < 0) { return x; } if(x == 0) { return 1; } int total = x--; while(x > 0) { total *= x--; } return total; }