StringNode.java

Download
1/*2 * StringNode.java3 *4 * Computer Science S-22, Harvard University5 */6 7import java.io.*;8import java.util.*;9 10/**11 * A class for representing a string using a linked list.12 * Each character of the string is stored in a separate node.  13 *14 * This class represents one node of the linked list.  The string as a15 * whole is represented by storing a reference to the first node in16 * the linked list. The methods in this class are static methods that17 * take a reference to a string linked-list as a parameter. This18 * approach allows us to use recursion to write many of the methods,19 * and it also allows the methods to handle empty strings, which are 20 * represented using a value of null.21 */22public class StringNode {23    private char ch;24    private StringNode next;25 26    /**27     * Constructor28     */29    public StringNode(char c, StringNode n) {30        this.ch = c;31        this.next = n;32    }33 34    /**35     * getNode - private helper method that returns a reference to36     * node i in the given linked-list string.  If the string is too37     * short or if the user passes in a negative i, the method returns null.38     */39    private static StringNode getNode(StringNode str, int i) {40        if (i < 0 || str == null) {    // base case 1: not found41            return null;42        } else if (i == 0) {           // base case 2: just found43            return str;44        } else {45            return getNode(str.next, i - 1);46        }47    }48 49    /*****************************************************50     * Public methods (in alphabetical order)51     *****************************************************/52 53    /**54     * charAt - returns the character at the specified index of the55     * specified linked-list string, where the first character has56     * index 0.  If the index i is < 0 or i > length - 1, the method57     * will end up throwing an IllegalArgumentException.58     */59    public static char charAt(StringNode str, int i) {60        if (str == null) {61            throw new IllegalArgumentException("the string is empty");62        } 63          64        StringNode node = getNode(str, i);65 66        if (node != null) {67            return node.ch;     68        } else {69            throw new IllegalArgumentException("invalid index: " + i);70        }71    }72 73    /**74     * convert - converts a standard Java String object to a linked-list75     * string and returns a reference to the linked-list string76     */77    public static StringNode convert(String s) {78        if (s.length() == 0) {79            return null;80        }81 82        StringNode firstNode = new StringNode(s.charAt(0), null);83        StringNode prevNode = firstNode;84        StringNode nextNode;85 86        for (int i = 1; i < s.length(); i++) {87            nextNode = new StringNode(s.charAt(i), null);88            prevNode.next = nextNode;89            prevNode = nextNode;90        }91 92        return firstNode;93    }94    95    /**96     * copy - returns a copy of the given linked-list string97     */98    public static StringNode copy(StringNode str) {99        if (str == null) {100            return null;101        }102 103        // make a recursive call to copy the rest of the list104        StringNode copyRest = copy(str.next);105           106        // create and return a copy of the first node, 107        // with its next field pointing to the copy of the rest108        return new StringNode(str.ch, copyRest);109    }110 111    /**112     * deleteChar - deletes character i in the given linked-list string and113     * returns a reference to the resulting linked-list string114     */115    public static StringNode deleteChar(StringNode str, int i) {116        if (str == null) {117            throw new IllegalArgumentException("string is empty");118        } else if (i < 0) { 119            throw new IllegalArgumentException("invalid index: " + i);120        } else if (i == 0) { 121            str = str.next;122        } else {123            StringNode prevNode = getNode(str, i-1);124            if (prevNode != null && prevNode.next != null) {125                prevNode.next = prevNode.next.next;126            } else {127                throw new IllegalArgumentException("invalid index: " + i);128            }129        }130 131        return str;132    }133 134    /**135     * insertChar - inserts the character ch before the character136     * currently in position i of the specified linked-list string.137     * Returns a reference to the resulting linked-list string.138     */139    public static StringNode insertChar(StringNode str, int i, char ch) {140        StringNode newNode, prevNode;141 142        if (i < 0) { 143            throw new IllegalArgumentException("invalid index: " + i);144        } else if (i == 0) {145            newNode = new StringNode(ch, str);146            str = newNode;147        } else {148            prevNode = getNode(str, i - 1);149            if (prevNode != null) {150                newNode = new StringNode(ch, prevNode.next);151                prevNode.next = newNode;152            } else {153                throw new IllegalArgumentException("invalid index: " + i);154            }155        }156 157        return str;158    }159 160    /**161     * insertSorted - inserts character ch in the correct position162     * in a sorted list of characters (i.e., a sorted linked-list string)163     * and returns a reference to the resulting list.164     */165    public static StringNode insertSorted(StringNode str, char ch) {166        StringNode newNode, trail, trav;167 168        // Find where the character belongs.169        trail = null;170        trav = str;171        while (trav != null && trav.ch < ch) {172            trail = trav;173            trav = trav.next;174        }175 176        // Create and insert the new node.177        newNode = new StringNode(ch, trav);178        if (trail == null) {179            // We never advanced the prev and trav references, so180            // newNode goes at the start of the list.181            str = newNode;182        } else { 183            trail.next = newNode;184        }185            186        return str;187    }188 189    /**190     * length - recursively determines the number of characters in the191     * linked-list string to which str refers192     */193    public static int length(StringNode str) {194        if (str == null) {195            return  0;196        } else {197            return 1 + length(str.next);198        }199    }200 201    /**202     * numOccur - find the number of occurrences of the character203     * ch in the linked list to which str refers204     */205    public static int numOccur(StringNode str, char ch) {206        if (str == null) {207            return 0;208        }209     210        int numInRest = numOccur(str.next, ch);211        if (str.ch == ch) {212            return 1 + numInRest;213        } else {214            return numInRest;215        }216    }217 218    /**219     * print - recursively writes the specified linked-list string to System.out220     */221    public static void print(StringNode str) {222        if (str == null) {223            return;224        } else {225            System.out.print(str.ch);226            print(str.next);227        }228    }229 230    /**231     * read - reads a string from an input stream and returns a232     * reference to a linked list containing the characters in the string233     */234    public static StringNode read(InputStream in) throws IOException { 235        char ch = (char)in.read();236 237        if (ch == '\n') {    // the string ends when we hit a newline character238            return null;         239        } else {240            StringNode restOfString = read(in);241            StringNode first = new StringNode(ch, restOfString);242            return first;243        }244    }245    246    /*247     * toString - creates and returns the Java string that248     * the current StringNode represents.  Note that this249     * method -- unlike the others -- is a non-static method.250     * Thus, it will not work for empty strings, since they251     * are represented by a value of null, and we can't use252     * null to invoke this method.253     */254    public String toString() {255        String str = "";256        257        StringNode trav = this;   // start trav on the current node    258        while (trav != null) {259            str = str + trav.ch;260            trav = trav.next;261        }262         263        return str;264    }265    266    /**267     * toUpperCase - converts all of the characters in the specified268     * linked-list string to upper case.  Modifies the list itself,269     * rather than creating a new list.270     */271    public static void toUpperCase(StringNode str) {        272        StringNode trav = str; 273        while (trav != null) {274            trav.ch = Character.toUpperCase(trav.ch); 275            trav = trav.next;276        }277    } 278              279    public static void main(String[] args) throws IOException {280        StringNode copy, str, str1, str2, str3;281        String line;282        int n;283        char ch;284 285        // convert, print, and toUpperCase286        str = StringNode.convert("fine");287        System.out.print("Here's a string: "); 288        StringNode.print(str);289        System.out.println();290        System.out.print("Here it is in upper-case letters: "); 291        StringNode.toUpperCase(str);292        StringNode.print(str);293        System.out.println();294        System.out.println();295 296        Scanner in = new Scanner(System.in);297        298        // read, toString, length, and printReverse.299        System.out.print("Type a string: ");300        String s = in.nextLine();301        str1 = StringNode.convert(s);302        System.out.print("Your string is: "); 303        System.out.println(str1);        // implicit toString call304        System.out.println("\nIts length is " + StringNode.length(str1) + 305            " characters.");306 307        // charAt308        n = -1;309        while (n < 0) {310            System.out.print("\nWhat # character to get (>= 0)? ");311            n = in.nextInt();312            in.nextLine();313        }314        try {315            ch = StringNode.charAt(str1, n);316            System.out.println("That character is " + ch);317        } catch (IllegalArgumentException e) {318            System.out.println("The string is too short.");319        }320           321        // deleteChar and copy322        n = -1;323        while (n < 0) {324            System.out.print("\nWhat # character to delete (>= 0)? ");325            n = in.nextInt();326            in.nextLine();327        }328        copy = StringNode.copy(str1);329        try {330            str1 = StringNode.deleteChar(str1, n);331            StringNode.print(str1);332        } catch (IllegalArgumentException e) {333            System.out.println("The string is too short.");334        }335        System.out.print("\nUnchanged copy: ");336        StringNode.print(copy);337        System.out.println();338 339        // insertChar340        n = -1;341        while (n < 0) {342            System.out.print("\nWhat # character to insert before (>= 0)? ");343            n = in.nextInt();344            in.nextLine();345        }346        System.out.print("What character to insert? ");347        line = in.nextLine();348        ch = line.charAt(0);349        try {350            str1 = StringNode.insertChar(str1, n, ch);351            StringNode.print(str1);352            System.out.println();353        } catch (IllegalArgumentException e) {354            System.out.println("The string is too short.");355        }356        357        // insertSorted358        System.out.print("\nType a string of characters in alphabetical order: ");359        s = in.nextLine();360        str3 = StringNode.convert(s);361        System.out.print("What character to insert in order? ");362        line = in.nextLine();363        str3 = StringNode.insertSorted(str3, line.charAt(0));364        StringNode.print(str3);365        System.out.println();366    }367}