CS140 Midterm 1 Solutions

Spring 2018


  1. (12 points) For each of the following questions, select the best answer from the following list:

    1. cd The Unix command that changes the directory.

    2. public The access protection you should use to declare the member functions of a class that are in the class's Application Programmer Interface (API).

    3. object files The name of the files produced when you execute g++ with the "-c" option (these files have a .o extension).

    4. mutator method The name of a method that modifies a class's data.

    5. linker The software that combines two or more object files (.o files) into an executable and replaces references to functions with jumps to functions that are defined in other files.

    6. header file The name of the file where you put class declarations that you wanted included in multiple files.

  2. (10 points) Suppose I want to declare a class named Picture and use it in a program named Photoshop.cpp. Answer the following questions:

    1. In what file should the class declaration for Picture be placed? Give the name of the file, following the naming conventions discussed in class.

      Picture.h

    2. In what file should the method definitions for Picture be placed? Give the name of the file, following the naming conventions discussed in class.

      Picture.cpp

    3. Using a single g++ statement, how could I compile all of these files into an executable named Photoshop?

      g++ -o Photoshop Photoshop.cpp Picture.cpp

    4. Suppose instead that I wanted to separately compile these files and then link together their object files into an executable named Photoshop. Write the set of statements that would be required to perform this separate compilation and then linking into the executable.

        g++ -c Photoshop.cpp
        g++ -c Picture.cpp
        g++ -o Photoshop Photoshop.o Picture.o
        

    5. Suppose I want to execute Photoshop from the command line by 1) redirecting stdin from a file named bvz.pgm, and 2) redirecting stdout to a file named edited_bvz.pgm. Write the command that I should use to execute Photoshop.

      ./Photoshop < bvz.pgm > edited_bvz.pgm

  3. (8 points) Which of the following two constructors is more efficient?
    (a)(b)
    Person::Person(string fn, string ln, string addr) {
        firstname = fn;	  
        lastname = ln;
        address = addr;
    }
    	
    Person::Person(string fn, string ln, string addr):
        firstname(fn), lastname(ln), address(addr) {}
    			
    Answer the following questions.

    1. (b) Which constructor is more efficient (a or b)?
    2. Why is your selected constructor more efficient?

      The initialization list in constructor (b) requires only one method call to initialize each string while the constructor in (a) requires two method calls to initialize each string. In addition to the assignment statements you see in (a), which require a call to the string assignment operator, the 0-argument constructors for each string variables are also called.

  4. (12 points) The following code fragment is trying to shift all elements in a vector 3 entries to the right and replace the vacated entries with 0:
        vector<int> v;
        int i;
        int originalSize;
    
        // (1) resize the vector
        originalSize = v.size();
        v.resize(v.size() + 3);
    
        // (2) shift the existing entries to the right
        for (i = 0; i < v.size(); i++) {
            v[i+3] = v[i];
        }
    
        // (3) fill the vacated entries with 0's
        for (i = 0; i < 3; i++) {		    
            v[i] = 0;
        }		    
    
    Suppose that v contains the contents:
    01234567
    1020304050607080

    The code fragment as written does not achieve its intended purpose. Answer the following questions:

    1. Show what the contents of the vector actually look like after the above code fragment executes. I have provided too many vector entries. Leave the undefined entries empty.

      0123456789101112
      0001020301020301020

    2. What is the code fragment doing wrong?

      It is starting to shift the entries from the left side of the vector rather than from the right side of the vector and as a result it is clobbering entries in the vector before it has a chance to move them.

    3. Rewrite one or more of the numbered code blocks so that the code fragment correctly shifts the existing vector elements and assigns 0's to the vacated entries. Clearly indicate which numbered code block(s) you are altering.

      You need to modify fragment 2 so that it starts shifting entries from the right side of the original vector (not the resized vector--that's why my code starts shifting from originalSize-1 rather than v.size()-1):

          for (i = originalSize-1; i >= 0; i--) {
              v[i+3] = v[i];
          }
      	  
  5. (24 points)

    1. Insert the keys 32, 12, 48, 19, 52, 58, 30, 25 into the following two hash tables using a) separate chaining, and b) quadratic probing. For separate chaining, use commas to separate the keys that would go into an entry. For example, if the keys x, y, and z all went into the same entry, you would write (x, y, z) in that entry. You should use the hash function:
      h(key) = key % 11
      
       Separate ChainingQuadratic Probing
      0  
      11212
      2  
      358, 2558
      44848
      5  
      6 30
      7 25
      819, 52, 3019
      9 52
      103232

    2. For quadratic probing please also complete the following table showing the comma, separated list of entries you would probe in order to insert each key (e.g., if you examined entries 2, 3, and 7 in order to insert 32, then you would write (2, 3, 7) next to 32 in the below table--this is only an example--it is not the actual set of entries you will probe for 32). This will allow us to assign you partial credit if you do not get the entries correct in the quadratic probing hash table.

      keyquadratic probing
      3210
      121
      484
      198
      528, 9
      583
      308, 9, 1, 6
      253, 4, 7
  6. (12 points) What is the hexadecimal result of each of the following operations. You can show your work in the blank spaces to get partial credit:
    1. 0x6D = 0110 1101

    2. 1001 0101 ^ 1010 1100 = 0x39
            ^ is bitwise exclusive or:
      	  
      	1001 0101
            ^ 1010 1100
              ---------
              0011 1001 = 0x39
            
    3. 1001 0101 | 1010 1100 = 0xBD
            | is bitwise or
      	  
      	1001 0101
            | 1010 1100
              ---------
              1011 1101 = 0xBD
      
      	
    4. 1010 1100 >> 3 = 0x15
          >> is the right shift operator:
      
          1010 1100 >> 3 = 0001 0101 = 0x15
      		  
  7. (5 points) Suppose that you search a maze collecting animals that are denoted by the letters A-Z. Each animal is worth points, with A standing for 2 points, B standing for 4 points, C standing for 6 points, etc. (Z stands for 52 points). You are given the following variable declarations:
        char animal;   // the letter of the most recently collected animal
        int totalPoints; // the total number of points earned thus far
      
    Write a single C++ statement that will convert the character stored in animal to the correct point value and add that point value to totalPoints
    totalPoints += (animal + 1 - 'A') * 2;
    

  8. (10 points) Given the following variable declarations, write a printf statement that outputs name in a right-justified field of 15 characters, salary in a left-justified field of 12 characters with 1 decimal digits, and age in a left-justified field of 6 characters. There should be a single space between each of the fields.
    string name;
    double salary;
    int age;
    
    printf("%15s %-12.1f %-6d\n", name.c_str(), salary, age);

  9. (12 points) Behold the following program that has been placed in a file named mystery.cpp. On the right are a set of Unix commands that will compile the program and run it on an input file. What is the output of the last Unix command?
    #include <iostream>
    #include <sstream>
    using namespace std;
    
    int main() {
      istringstream buffer;
      int num;
      double num1;
      int sum1 = 0;
      double sum2 = 0;
      string input;
    
      while (cin >> input) {
        buffer.clear();
        buffer.str(input);
        if (buffer >> num1) {
          if (input.find('.') == string::npos) {
    	buffer.clear();
    	buffer.str(input);
    	buffer >> num;
    	sum1 += num;
          }
          else {
    	sum2 += num1;
          }
        }
        else {
          cout << input << endl;
        }
      }
      
      cout << "sum1 = " << sum1 << endl;
      cout << "sum2 = " << sum2 << endl;
    }
    			       
    UNIX> g++ mystery.cpp
    UNIX> cat input.txt
    3.6 14.5
    -5 Brad
      Smiley
    20. Jill Nancy 17.4
    50
    UNIX> ./a.out < input.txt 10 Mario
    				     
    The command line arguments are ignored by cin. It only reads the standard input from input.txt. The code checks to see if the input is a number. If the input is a number, then the code checks to see if the number is an integer or a floating point number and adds the number either to an integer accumulator or a floating point accumulator. If the input is a string then the code immediately prints the string. Once all the input has been read, the code prints the integer total and the floating point total.
    Brad
    Smiley
    Jill
    Nancy
    sum1 = 45
    sum2 = 55.5
        


Coding Solutions

  1. Tail
    #include <iostream>
    #include <vector>
    #include <sstream>
    using namespace std;
    
    int main(int argc, char *argv[]) {
      istringstream buffer;
      vector<string> file;
      int numLines;
      string line;
      int i;
    
      // use a stringstream to convert the command line argument for the number
      // of lines to print to an integer
      buffer.str(argv[1]);
      buffer >> numLines;
    
      // add all the lines in the input to the vector
      while (getline(cin, line)) {
        file.push_back(line);
      }
    
      // If the number of lines in the file is less than the number of lines
      // to print then we will print all the lines in the file
      if (file.size() < numLines) {
        numLines = file.size();
      }
    
      // print the last numLines in the file
      for (i = file.size() - numLines; i < file.size(); i++) {
        cout << file[i] << endl;
      }
    }
      
      
    		       
  2. Teams
    1. readTeams
      void readTeams(string& group, vector<SVec> &teams) {
          string name;
          istringstream buffer;
          SVec row;
      
          // put the group into an istringstream so we can break it into team members
          // and then add the team members to our row. Finally add the new row to
          // our teams vector
          buffer.str(group);
          while (buffer >> name) {
            row.push_back(name);
          }
          teams.push_back(row);
      }
      	    
    2. printTeam
      void printTeam(string &name, vector<SVec> &teams) {
        int i, numNames;
        int numMembers;
      
        // do a linear search of teams to find the team leader
        for (i = 0; i < teams.size(); i++) {
      
          // if we find the team leader, then print all the team members, 3
          // per line. We reach the end of a line whenever the number of names
          // we have printed is a multiple of 3. numNames counts the number of names
          // printed, but it starts at 0 so we must add 1 to it to get the correct
          // number of names we have printed. We then use the mod operator (%) to
          // test whether (numNames+1) is a multiple of 3, and if it is, we print
          // a newline character so that we start a new line.
      
          if (teams[i][0] == name) {
            for (numNames = 0; numNames < teams[i].size(); numNames++) {
      	printf("%10s", teams[i][numNames].c_str());
      	if (((numNames+1) % 3) == 0) {
      	  printf("\n");
      	}
            }
            // when we finish printing all the team members, we need to print a
            // newline character if we did not complete the line. We did not
            // complete the line if the number of names printed is not a multiple of 3.
            // Please note that we incremented numNames as we exited the loop and therefore
            // it now accurately reflects the number of names that we printed.
            if ((numNames % 3) != 0)
      	printf("\n");
            printf("\n"); // print an extra blank line
            return;
          }
        }
        printf("no team found whose leader is %s\n\n", name.c_str());
      }