CS 12 -- Mid-term 1 Solutions


You will find that questions are in green, answers are in red, and discussion is in blue. Note that the answers given here are meant to be thorough in their presentation -- more thorough than I would necessarily expect from someone actually taking the exam.

  1. (15 points) For the following sequence of lines of Java code, which will fail for lack of an explicit cast?

        int i = 5;
        double d = i;
        char c = i;
        double d2 = c;
        int i2 = c + 3;
        char c2 = c + '3';

    The following of the above lines will not compile due to a lack of cast:

        char c = i;
        char c2 = c + 3;

    The two lines shown are the only ones for which the assignment may lose information because the space into which data is being stored is smaller that the data itself. The first faulty line tries to assign an integer value into a character space, which is smaller. The second line is more subtle, because the two items being added are both characters. However, the result of the addition is, in fact, an integer. Thus that line too is assigning an integer value into a character space.

    Not a single person correctly identified the second case. A number of people asserted that, given a compilation error generated by the first case, subsequent lines using c would also not compile. While nobody lost points for this assertion, it is false. The compiler does acknowledge that c is declared as a char, and will continue to compile later lines that use it.

  2. (15 points) What output will the following program generate?

        class ArrayStuff {
    
            private static void changeThings (int[] array) {
    
                array[3] = 100;
                array = new int[10];
                array[8] = -20;
    
            }
    
            public static void main (String[] args) {
    
                int[] x = new int [5];
                x[2] = 3;
                changeThings(x);
                for (int index = 0; index < x.length; index++) {
                    System.out.println("x[" + index + "] = " + x[index]);
                }
    
            }
        }

    The program will emit the following:

        x[0] = 0
        x[1] = 0
        x[2] = 3
        x[3] = 100
        x[4] = 0

    Within main(), an array of 5 int is allocated, and x is made to point at that array. When changeThings() is called, it is given a copy of x. It thus has its own pointer, named array, to point at the same array.

    Therefore, when changeArray() sets element 3 of that array to 100, that change will be ``visible'' through the pointer named x. However, when array is then made to point at a new, longer array, any other changes made through array will not be visible through x. Finally, note that a pointer to the new array is not passed back to main(); thus, main() never has access to the longer array.

    Few received full credit for this problem. Many assumed either that assignment of array[3] would not be visible through x. Others assumed that x would point to the longer array. A surprising number believed that the unassigned values of the array would contain null; some even asserted that the code would not execute as a consequence. This belief is false. An array of int must contain all int values. A primitive type cannot be assigned the value null. The initial value for each element in an array of int is 0, not null.

  3. (15 points) What output will the following program generate?

        class Scope {
    
            private int x;
    
            public static void main (String[] args) {
    
                x = 5;
                while (x > 0) {
                    System.out.println(x);
                    int x = 2;
                    System.out.println(x);
                    x--;
                    System.out.println(x);
                }
            }
        }

    The follow pattern will repeat endlessly:

        5
        2
        1
        ...

    There is an error in this question! Specifically, for this code to compile, the data member x would need be static. However, nobody picked up on that fact.

    Assuming that data member x were static (as I had intended), this problem does exactly as described during a lecture. The data member would be assigned the value of 5. The loop would then emit that value, create a new, local variable also named x, assign it 2, print that value, decrement the local x, print its new value, and then repeat. Specifically, the x being checked in the while terminating condition will always be the data member, and thus will always be 5.

    A number of people got the initial sequence of 5, 2, 1 correct. However, subsequent values were incorrect, often based on the belief that once the local x is used, it will remain ``in force'' indefinitely. Scope rules are applied during compilation, not run-time. Thus, once a particular line of code (such as the terminating condition) uses a particular variable's space, it will _always_ use that same space.

  4. (15 points) What output will the following program generate?

        class Fib {
    
            private static int fib (int n) {
    
                if ((n == 0) || (n == 1)) {
    
                    System.out.println("Base case " + n);
                    return 1;
    
                } else {
    
                    System.out.println("Beginning " + n);
                    int i = fib(n - 1);
                    System.out.println("Middle " + n);
                    int j = fib(n - 2);
                    System.out.println("End " + n);
                    return i + j;
    
                }
            }
    
            public static void main (String[] args) {
    
                fib(4);
    
            }
        }

    The following output will be produced:

        Beginning 4
        Beginning 3
        Beginning 2
        Base case 1
        Middle 2
        Base case 0
        End 2
        Middle 3
        Base case 1
        End 3
        Middle 4
        Beginning 2
        Base case 1
        Middle 2
        Base case 0
        End 2
        End 4

    You must traverse the order of recursive calls to answer this question. Drawing a diagram of the ordering was likely a necessary strategy. It is important to remember that the search with be ``depth first''. That is, when fib(4) is requested, it first performs a call to obtain fib(3). That, in turn, will perform a call for fib(2), etc. The entire work of the fib(3) must be completed before the top-level call to fib(2) can be performed to complete the call of fib(4).

    This question was one that tended either to be completely correct or completely incorrect. In rare cases, answers would have a correct subset of the output, but not all of the correct output.

  5. (20 points) Write a method that will repeatedly prompt the user for the name of a file to open until a valid filename is given. Here are the signatures and simple descriptions for static methods should be used in your code:

    • Within the User class:

      public static String readLine ();

      This method takes input from the keyboard and, after Return has been pressed, returns that input as a pointer to a String object.

    • Within the FileReader class:

      public FileReader (String filename) throws FileNotFoundException

      This method constructs a new FileReader object if it can open the given filename for reading. If it fails, it throws a FileNotFoundException.

        public static FileReader openUserFile () {
    
            FileReader f = null;
            do {
    
                System.out.print("Enter a filename: ");
                String filename = User.readLine();
                try {
                    f = new FileReader(filename);
                } catch (FileNotFoundException e) {
                    System.out.println("Invalid filename, try again.");
                }
    
            } while (f == null);
    
            return f;
    
        }

    The trick here is to correctly construct a loop that will prompt for a filename, try to open the given filename, catch the exception that opening the file may generate so as to emit an error message, and repeat until the file is successfully open. Note that it was not critical to return a pointer to the FileReader -- technically, the question did not ask for the method to do that.

    Everyone remembered the try-catch structure in some form or other. However, many failed to poll the user for a filename repeatedly. In these cases, code would poll the user a second time, but then fail to test the result from using that second input. Note that most performed the repetition, as above, with iteration. It was also possible to use recursion here -- be sure that you see how.

  6. (20 points) Write a class name Point that has the following properties:

    • It is instantiable.
    • A Point object stores a pair of real-valued Cartesian coordinates.
    • A Point object is immutable---once its coordinates have been set during construction, they cannot be changed.
    • The coordinates of a Point object can be obtained by calling its getX() and getY() methods.
    • The class contains a getNumberPoints() method that returns the number of Point objects that have been created so far.
        class Point {
    
            private double _x;
            private double _y;
            private static int _numberPoints;
    
            public Point (double x, double y) {
    
                _x = x;
                _y = y;
                _numberPoints++;
    
            }
    
            public double getX () {
                return _x;
            }
    
            public double getY () {
                return _y;
            }
    
            public static int getNumberPoints () {
                return _numberPoints;
            }
    
        }

    The key is to declare _numberPoints and getNumberPoints as static, as only one copy of each should exist for the whole class. The other key is to increment _numberPoints at each call to the constructor, thus keeping track of the number of point objects that have been created.

    The correct declaration of static elements was critical to this problem. It was the only key component that was typically missed.


Scott F. Kaplan
Last modified: Fri Oct 24 11:23:02 EDT 2003