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}
char ch
Field defined at line 23.
StringNode next
Field defined at line 24.
StringNode(c, n)
Constructor defined at line 29.
getNode(str, i)
Method defined at line 39.
charAt(str, i)
Method defined at line 59.
convert(s)
Method defined at line 77.
copy(str)
Method defined at line 98.
deleteChar(str, i)
Method defined at line 115.
insertChar(str, i, ch)
Method defined at line 139.
insertSorted(str, ch)
Method defined at line 165.
length(str)
Method defined at line 193.
numOccur(str, ch)
Method defined at line 205.
print(str)
Method defined at line 221.
read(in)
Method defined at line 234.
toString()
Method defined at line 254.
toUpperCase(str)
Method defined at line 271.
main(args)
Method defined at line 279.