CS140 Midterm Exam - October 15, 2019 Answers and Grading

James S. Plank

Question 1: 16 Points

Grading:

0.75 points for parts A through Q, and parts S through U. 1 point for part R. Here are counts of correct answers (91 students):

A: 89 F      B: 44 F      C: 55 T      D: 68 F      E: 61 F      
F: 86 F      G: 89 T      H: 72 T      I: 85 F      J: 86 F      
K: 81 F      L: 68 F      M: 67 T      N: 60 F      O: 55 F      
P: 78 F      Q: 77 T      R: 89 F      S: 64 T      T: 81 F      
U: 73 T      


Question 2: 10 Points

I know, no one likes to trace through code, but how else to get you to demonstrate to me that you understand the basics of try/catch? Let's walk through it: So the answer is: 0, 3, 5, 10, 12

Grading: 2 points per correct answer, -0.75 per incorrect answer. Minimum = 0.


Question 3: 10 Points

Grading: 2.5 points per answer.


Question 4: 16 Points

Since the table size is 16, the last hex digit is the hash index.

Grading:


Question 5: 14 Points

This is a question that tests argc/argv, stringstreams and stdout/stderr. Here's an example answer:

#include <iostream>
#include <sstream>
using namespace std;

int main(int argc, char **argv)
{
  istringstream ss;
  int i, j;

  for (i = 1; i < argc; i++) {
    ss.clear();                 // You have to clear the stringstream between uses.
    ss.str(argv[i]);
    if (ss >> j) {              // The boolean is true only if the string represents an integer.
      cout << j << endl;
      return 0;
    }
  }
  cerr << "No integer" << endl; // If we exit the for loop, we haven't found an integer.
  return 0;
}

I didn't care if you started the loop at 0 or 1, since I didn't specify in the problem description.

Grading:

The grading for this question (and most of the coding questions), uses the following rubric: Either you start with zero points (and your grading file will say "Please see the answer") and then you get points for things that are correct. Or, you start with 14 points, and then receive deductions for things that are incorrect.

Common deductions:

Regardless, if you mixed code and variable declarations (with the exception of declaring an integer inside a for loop), you received a 1 point deduction.


Question 6: 14 Points

You can solve this in a variety of ways. Here are a few:

void vreverse(vector <int> &v)
{
  size_t i;
  int j;

  for (i = 0; i < v.size()/2; i++) {
    j = v[i];
    v[i] = v[v.size()-i-1];
    v[v.size()-i-1] = j;
  }
}
void vreverse(vector <int> &v)
{
  vector <int> v2;
  int i;

  for (i = v.size()-1; i >= 0; i==) {
    v2.push_back(v[i]);
  }
  v = v2;
}
void vreverse(vector <int> &v)
{
  deque <int> q;
  int i;

  for (i = 0; i < v.size(); i++) {
    q.push_front(v[i]);
  }
  v.clear();
  for (i = 0; i < q.size(); i++) {
    v.push_back(q[i]);
  }
}

Personally, I think that the first is the best.

Grading:

The grading is like the previous question. Here are the major deductions -- there are others:


Question 7: 10 Points

Here's a correct answer: qlist.cpp

int dmiddle(list <string> *l)
{
  list <string>::const_iterator lit, lit2;
  size_t i;
  
  if (l->size() == 0) return 0;
  lit = l->begin();
  for (i = 0; i < l->size()/2; i++) lit++;
  if (l->size() % 2 == 0) {
    lit2 = lit;
    lit2--;
    l->erase(lit);
    l->erase(lit2);
    return 2;
  } else {
    l->erase(lit);
    return 1;
  }
}

The grading for this is like the last question. Here are the major deductions -- there were others.


Question 8: 13 Points

/* Part A */
bool Data::Print_By_Decade(int decade)
{
  size_t i;

  if (decade < 0 || decade >= Decades.size()) return false;
  for (i = 0; i < Decades[decade].size(); i++) {
    cout << Decades[decade][i]->name << endl;
  }
  return true;
}

/* Part B -- you need to delete the things that you have allocated with new.
   Those are the People.  So, simply run through the All vector and delete
   the people. */

Data::~Data() 
{
  size_t i;

  for (i = 0; i < All.size(); i++) delete All[i];
}

/*  Or you can do it with Decades, but that is more of a pain:

Data::~Data() 
{
  size_t i, j;

  for (i = 0; i < Decades.size(); i++) {
    for (j = 0; j < Decades[i].size(); j++) delete Decades[i][j];
  }
}
*/

Part C: Since Print_By_Decade() doesn't change anything, you should declare it as const. So, change line 11 to "bool Print_By_Decade(int decade) const;"

Part D: You handle errors in constructors by throwing exceptions The best exceptions to throw are strings. You need to throw the exception before the new call, to avoid a memory leak. So, either before line 25 or 26, add "if (a < 0) throw ((string) "Data::Data() - Bad age.".

That's actually an incomplete answer. You should really run through All and delete all of the people, too. However, I accepted the above as an answer.

Grading:

Part A is like the other coding questions, with a maximum of 5 points.

Part B is worth three points. You received 1.8 points of you deleted the pointers twice (traversing All and Decades). You received 1 point if you deleted Decades[i].

Part C is worth two points. Here are the answer keys and their values:

Part D was 3 points, and I treated it like the coding questions, but with deductions. The following were all one-point deductions: