Practice midterms

The two midterms below are meant to give a feel for the length and difficulty of the actual midterm, and for the breadth/depth of possible midterm questions. The specific topics/nature of the actual midterm will of course vary: particularly with respect to which questions are discussion style and which involve a coding component.


Practice midterm 1

  1. Pointers and dynamic allocation/deallocation:
    1. First, provide code to dynamically allocate an array of size floats (assuming size is a variable that has already been declared and initialized).
      Then provide the code to deallocate that same array.
    2. First, provide a function profile (i.e. just header line for the function, not the entire body) where the function takes two pointers to string as parameters, but both passed by reference.
      Then suggest circumstances under which this might be useful - when/why might you want to pass pointers by reference?
    3. Suppose you have a struct type named MyData, and a variable named X of type MyData.
      If a function named doStuff expected a pointer to a MyData item as its parameter, how would you pass the address of X to it? (Provide the actual call to doStuff.)

  2. Sorting and searching:
      Study the quicksort partition code below, and show what changes the partition routine would make to the array contents on the first pass (just the first pass) through the do-while loop assuming the array contents were { 17, 3, 23, 91, 4, 87, 11 } and lower was 0, upper was 6.
      
      // partition the specified array segment,
      //    returning the crossover point determined by partioning
      int partition(int arr[], int lower, int upper)
      {
         if (lower >= upper) return lower;
      
         int partValue = arr[lower];
      
         int low = lower+1;
         int high = upper;
      
         do {
            while ((arr[low] <= partValue) && (low < high)) low++;
      
            while ((arr[high] >= partValue) && (low < high)) high--;
      
            if (low < high) {
               swap(arr[low], arr[high]);
               low++;
               high--;
            }
         } while (low < high);
      
         int crossover = high;
         if (arr[lower] <= arr[crossover]) crossover--;
         swap(arr[lower], arr[crossover]);
         return crossover;
      }
         

  3. Command line arguments and file i/o:
      Write a complete program that takes two filenames as command line arguments: the first for an input file and the second for an output file.

      The program should open the input file for reading and the output file for writing, and (assuming both opened successfully) copy all the digits from the input file to the output file. (Reminder: the isdigit(c) function will return true if the passed character is a digit, false otherwise.)

      The program should display an error message if passed an incorrect number of command line arguments or either file fails to open, and be sure to close any successfully-opened files before the program ends.

  4. Arrays of structs:
      Suppose we have a Fraction struct defined as follows:
         struct Fraction {
            unsigned long numerator;
            unsigned long denominator;
         };
      
      Based on that definition, provide an implementation for the GreaterThanOne function below:
      // display all the Fractions in the array for which the numerator is greater than the denominator,
      // outputting them in the form numeratorvalue/denominatorvalue, e.g. 17/12
      void GreaterThanOne(Fraction arr[], int size)
      


Practice midterm 2

  1. Pointers and dynamic allocation/deallocation:
    1. First, study the program below and explain the point/purpose of each use of & and * within the code. (Remember, the goal is to make it clear you understand what is happening: when we need to use a pointer/address and when we do not.)
    2. Second, as accurately as possible, show the complete output that would result from running the program.
    3. Third, correct the program so that it explicitly deallocates the dynamically allocated data at an appropriate point in the code.
      #include <iostream>
      using namespace std;
      
      struct MyInts {
         int x;
         int *y;
      };
      
      void print1(int* i)
      {
         cout << (*i) << endl;
      }
      
      void print2(int i)
      {
         cout << i << endl;
      }
      
      int main()
      {
         int data = 25;
      
         MyInts* moreData = new MyInts;
         moreData->x = 6;
         moreData->y = &data;
      
         print1(moreData->y);
         print1(&moreData->x);
      
         print2(*moreData->y);
         print2(moreData->x);
      }
         

  2. Command line arguments and file i/o:
      Write a main routine that expects one command line argument: a positive integer.

      The routine should attempt to open a file named "mydata" for writing (output), and write the integers 1..N into the file, where N is the integer from the command line argument.

      Be sure to generate an error message if the file fails to open or an incorrect number of command line arguments are passed or if the value passed isn't a positive integer, and to close the file before ending the program (if it opened successfully).

      Tip: atoi(somechararray) will return the integer equivalent of the contents of the character array, and returns 0 if the contents don't represent a valid integer.

  3. Arrays of structs:
      Suppose we have the following struct definition:
      struct CarInfo {
         string make;
         string model;
         int year;
      };
      
      (i) Assuming the array has been filled with N valid CarInfo structs, complete the oldestMake function described below.
      // return the make for the car with the oldest (smallest/earliest) year
      // Error handling: return "" if N is less than one
      string oldestMake(CarInfo allcars[], int N)
      
      (ii) If all the cars in the array had the same year but different models, which one would your code return? (E.g. the first one, the last one, ...?)

  4. Sorting and searching:
      Suppose we had a program that gets a series of numbers from the user and then performs one or more searches on the data (the user decides how many values to store and how many searches they want to perform).

      Further, suppose the program uses logic similar to the following:

      • Find out how many values the user wants to store.
      • Read them in and store them in an array, but as you read them keep track of whether or not they have been received in sorted order (i.e. is each new number at least as big as the previous number).
      • If they didn't come in entirely sorted, then sort them now based on the following criteria:
        • If it was a small number (<100) then call a bubblesort routine to do the sorting.
        • If it was a larger number then call a quicksort routine to do the sorting.
      • Finally, perform each of the searches desired by the user.

    1. First, describe the potential advantages of this approach over an approach that always simply read the values and did a quicksort before moving on to the sequence of searches.

    2. Next, describe the potential disadvantages.

    3. Did the number of searches the user performs factor into your answers? Why or why not?