mkdir ~/6.170/lab2 cp /mit/6.170/www/labs/lab2/*.java ~/6.170/lab2Once you have copied the files try to compile them. They should compile without any errors.
NullPointerException:
NullPointerExceptions occur typically when you attempt to
call a method on a null reference or attempt to access a field of a
null reference. Some methods also throw them explicitly when they are
passed a null argument. ArrayIndexOutOfBoundsException: This exception
occurs when you are accessing an element of an array with an index
value which is either larger than the size of the array or less than
zero.IndexOutOfBoundsException:An
IndexOutOfBoundsException in the analogue of
ArrayIndexOutOfBoundException except that it occurs when
accessing Vectors or Lists as opposed to arrays.ClassCastException: This exception occurs when
you attempt to cast an object to a subclass of which it is not an
instance. For example if you are using a Vector and you retrieve an
element of the Vector which will be of type Object and attempt to cast
it to a String when it is actually an Integer, a ClassCastException
will be thrown at run time. IllegalArgumentException: This exception is
commonly thrown by methods when they are passed illegal arguments.
You should consult the documentation for the function throwing the
exception to determine the valid domain of arguments.
athena% java lab2.HuffmanMain
Exception in thread "main" java.lang.NullPointerException
at lab2.HuffmanCodec.encode(HuffmanCodec.java:137)
at lab2.HuffmanMain.main(HuffmanMain.java:14)
The first line of output tells you that an exception has been thrown
and tells you the type of the exception. In this case it is a
NullPointerException. The following lines show you a
snap shot of what methods were calling what other methods at the time
the exception was thrown. In this case (starting from the bottom) we
see that the program started out executing
lab2.HuffmanMain.main. The main method then, on line 14,
called HuffmanMain.encode which threw the
NullPointerException on line 137 of the source file.
If, when debugging, you want to find out about which methods are
calling certain code you can have the Java runtime print out a stack
trace on demand without halting the program by throwing an exception.
To do this call Thread.dumpStack().
toString method which returns a
String representation of the object. This provides a
convenient way for you to dump information about the state of your
program helping you understand what is going on.
As you may have noticed all java.lang.Object provides an
implementation of toString() which will return the name
of the class as well as an implementation-specific hash value. In
most cases, therefore, you'll find it in your best interest to
override the toString method with one of your own which
returns a more useful string, perhaps identifying the class.
information.
In fact because the toString() is available for all
objects, the Java language provides special support to automatically
call it in certain circumstances. For instance the string
concatenation operation, +, can automatically call the
toString method on one of it's arguments. In fact it can also be used
to convert Java primitives to strings. For instance you could write
the following line in Java:
System.out.println("My vector has " + v.size() + " elements which are " + v);
When compiling the above line the Java compiler will automatically
insert the appropriate code to convert the result of
size, which is an int to a
String as well as automatically calling
toString() on v to produce a
String. This will cause the program to output something
akin to the following:
My vector has 5 elements which are [A, B, C, D, E]
In fact the compiler is even slightly trickier than that in that when
converting an object to a String it will only call
toString() if the reference to the object is non-null,
else it will produce the string "null".
In order for these features to work you must make sure you have the following line in your .emacs file:
(load "/mit/6.170/etc/emacs/6170.el")If you do not, add it and restart Emacs.
Start a shell from within Emacs: M-x shell RET
Within the shell buffer, type
java lab2.Thrownullwhich will result in a
NullPointerException:
athena% java lab2.Thrownull Exception in thread "main" java.lang.NullPointerException at lab2.Thrownull.printHashCode(Thrownull.java:12) at lab2.Thrownull.main(Thrownull.java:8)Click, with your middle mouse button, anywhere on the line containing "Thrownull.java:8". Notice that Emacs reads lab2/Thrownull.java into a buffer (if the file had already been read into a buffer, it would have skipped that step) and puts the cursor on line 8, which is the line that threw the exception. Now middle-click anywhere on the line containing "Thrownull.java:12" It can be very convenient to simply click up and down a stack trace, seeing which code was in the middle of executing, much like a debugger would permit you to do, or to go directly to the code of interest.
Place the cursor on a method name, and type C-h f again. Notice that the method name that the cursor is in is the default, but you can still type any method name you like. Note that this works for methods defined in the problem sets (such as "heading") as well as for those defined in the JDK and those from JUnit, and that it works for field names as well as for method names.
HuffmanSymbol is used to
associate a symbol in the alphabet that is to be encoded with a value
representing how frequently it occurs since Huffman encoding attempts
to use the fewest bits for the most frequently occurring symbols.
HuffmanTree is a simple
data structure which can be used to build a tree which is used to
decode a bit stream. The process of decoding a bit stream involves
looking at each bit in series and choosing the left subtree if the bit
is 0 and the right subtree if the bit is a 1. When a leaf of the tree
is reached the symbol corresponding to that leaf can be output.
The file HuffmanCodec is
used to both build the encoding table and decoding tree as well as to
perform the actual encoding and decoding. A separate instance of
HuffmanCodec is created for a given set of symbols and
frequencies after which it can be used for any input so long as the
input only uses symbols that were used when constructing the codec.
Finally HuffmanMain
contains a short driver to encode/decode two simple strings as well as
some useful methods for converting data types.
lab2.HuffmanMain you'll find the program
dies by throwing a NullPointerException. Alas the
Huffman encoder/decoder is broken and now you get to try to fix it.
In some sense this might be a bit more difficult than debugging your
own code since you are not familiar with how it works, but on the other
hand you don't already have a notion of what you think is
going on stuck in your head preventing you from seeing what really is
going on.A very important tip before you start trying to debug the code: read the code and think about it. Thinking turns out to be a far more efficient way of debugging than littering code with System.out.println's, using a debugger, or anything else. These other tools are often useful as you try to get a grasp as to what is going on, or to verify what you think is happening, but they won't substitute for some good reasoning about the code.
It may also at some point in the debugging process also become useful to modify the main method slightly so that you can try out other test cases.
Some things you may want to look at is verifying that methods preconditions are met. You might also find it useful to add toString methods to classes to allow you to print out intermediate values. You should also consider adding code to verify that rep invariants are being maintained.
Here's a hint: The correct encoding for "set" is "1001111110". You should first try to get the encoding and decoding functions to decode to the same strings you input. Once that is done you will have a functioning encoder/decode but it won't quite be Huffman encoding since it won't be using the fewest bits possible for the least used symbols, so you should then look into fixing that using the above encoded string to help.