Assignment 7, due Mar 10

Solutions

Part of the homework for CS:2820, Spring 2017
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

On every assignment, write your name and section number. Write your name as it appears on your university ID card! Use the section number as it appears in your current registration! We will not do detective work to figure out who did what. Homework is due on paper at the start of your discussion section. Exceptions will be made only by advance arrangement with your TA (excepting "acts of God"). Never push homework under someone's door!

  1. Background: The code distributed with Lectures 18 and 19 on March 1 and 3 contains ScanSupport.nextName() for pulling a name from the input line without crossing line boundaries the way sc.next() does. The code continues to use sc.nextFloat(), though, and as a result, it sees nothing wrong with this input:
    road A B
             1.5 -- this is on the next line!
    

    a) Give a regular expression that recognizes floating-point numbers such as 1, 12, 12.3, 12.34 and .345 (ignore exponential notation). (0.5 points)

    This is a start: It matches all of the above except .345, and it also matches 10. with no trailing digits:
    \d+\.\d*

    This pattern matches numbers that start with a point followed by some digits:
    \.\d+

    We can combine these as follows to solve the problem:
    \d+\.\d*|\.\d+

    Of course, we can use [0123456789], [0-9] or \p{Digit} instead of \d to match digits in the above. And for the following part, we assume that we apply Pattern.compile() to the above to create the pattern floatPattern.

    b) Write a method ScanSupport.nextFloat() patterned after the existing nextName routine that returns a floating-point value if there is one or the special value Float.NaN if there isn't. (0.5 points)

    /** Get next float without skipping lines (unlike sc.nextFloat())
     *  @param sc the scanner from which end of line is scanned
     *  @return the name, if there was one, or NaN if not
     */
    public static Float nextFloat( Scanner sc ) {
            sc.skip( whitespace );
    
            // the following is weird code, it skips the name
            // and then returns the string that matched what was skipped
            sc.skip( floatPattern );
            string f = sc.match().group();
    
            // now convert what we can or return NaN
            if ("".equals( f )) {
                    return Float.parseFloat( sc.match().group() );
            } else {
                    return Float.NaN;
            }
    }
    
  2. Background: All of the ScanSupport methods take a parameter sc, for example ScanSupport.nextName(sc). It would be nicer to write sc.nextName().

    a) Describe how to use Java's class hierarchy to permit the above change. (Do not write code to answer this, write a description of hierarchic class relationships.) (0.5 points)

    It would be nice to be able to define class MyScanner as a subclass of Scanner.

    public class MyScanner extends Scanner ...
    

    That was the solution I intended but sadly, the definition of Scanner in the Java library is final, forbidding creation of subclasses. That doesn't make the problem insoluable, but it makes it ugly. We have to define MyScanner as a new class that implements the same interfaces as class Scanner and includes constructors and methods that are clones of class Scanner, plus the new methods we need. Each MyScanner object would contain exactly one real Scanner, and most of the methods of MyScanner would simply invoke the corresponding Scanner methods.

    public class MyScanner implements Closeable, AutoCloseable, Iterator {
            private final Scanner realScanner;
            ...
    

    This is so ugly that it is noth worth the effort, but it does demonstrate that a determined programmer can create code that defeats at least some of the intended restrictions of final classes in Java.

    b) How would the the header for Intersection.newIntersection() have to be changed to allow use of this new form. (0.5 points)

    public static Intersection newIntersection( MyScanner sc ) {
    

    This answer applies regardless of the issues with part a.

  3. Background: On the exam, it was suggested that the keyword private could usually be deleted without causing any problems. Note the word usually. There are exceptions that occur when there is a class hierarchy and the parent class contains a private final method.

    A problem: Construct a small example that demonstrates this. It can be done in 10 lines of totally useless code. (1.0 points)

    class A {
            private final void x() {
            }
    }
    class B extends A {
            public void x() {
            }
    }
    

    The above code compiles with no errors, but if you delete the keyword private from the above code and then compile it, you get this error:

    B.java:6: error: x() in B cannot override x() in A
            public void x() {
                        ^
      overridden method is final