//File: MyStringBuilder.java //Name: Trai Pham //Date: 03/09/2020 //Course: CSE 8B /** MyStringBuilder class contains all the methods that can manipulate a string **/ public class MyStringBuilder{ protected CharNode start; protected CharNode end; protected int length; public String emptyStr =""; public String spaceStr = " "; /** @param char variable @return nothing Constructor **/ public MyStringBuilder(char a){ this.length++; this.start = new CharNode(a); this.end = this.start; } /** @param String variable @return nothing Constructor **/ public MyStringBuilder(String str) throws BadInputException{ try{ if(str == null){ throw new BadInputException(Constants.FROM_CONSTRUCTOR, "bad input exception"); } //sets the charNode of the obj to null for empty strings else if(str == emptyStr){ this.start = null; this.end = null; this.length = 0; } else{ //adding charNode letter by letter this.length++; this.start = new CharNode(str.charAt(0)); this.end = this.start; for(int i =1; i < str.length(); i++){ this.append(str.charAt(i)); } } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } } /** @param MyStringBuilder object @return nothing Constructor **/ public MyStringBuilder(MyStringBuilder obj) throws BadInputException{ try{ if(obj == null){ throw new BadInputException(Constants.FROM_DEEPCOPY_CONSTRUCTOR, "bad input Exception"); } else{ //setting the first and last node with the object in the input this.length = obj.length(); this.start = obj.start; this.end = new CharNode(this.start.getData()); CharNode currNode = this.start.setNext(obj.start.getNext()); //goes through the references and nodes of the inputted obj for(int i = 1; i < this.length; i++){ CharNode newNode = new CharNode(currNode.getData()); this.end = newNode; newNode = currNode.setNext(currNode.getNext()); currNode = newNode; } } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } } /** @param nothing @return int gets length **/ public int length(){ return this.length; } /** @param char variable @return MyStringBuilder object This will add an additional charNode to the myStrinbBuilder object, that contains the character c **/ public MyStringBuilder append(char c){ if(this.start == null && this.end == null){ this.start = new CharNode(c); this.end = this.start; } else{ //this would create a new CharNode object with the char CharNode newNext = new CharNode(c); //this sets the next reference CharNode obj to the new Charnode obj this.end = this.end.setNext(newNext); //setting the last Charnode obj to the new this.end = newNext; this.length++; } return this; } /** @param String variable @return MyStringBuilder This will add a String to the MyStringBuilder, in which we're adding additional CharNodes to the called object. **/ public MyStringBuilder append(String str) throws BadInputException{ try{ if(str == null || str== spaceStr){ throw new BadInputException(Constants.FROM_APPEND_STR, "bad input Exception"); } //this will return the original string since an empty string is added if(str == emptyStr){ return this; } else{ //this will add the String to the object, adding to it CharNode by CharNode for(int i = 0; i< str.length(); i++){ this.append(str.charAt(i)); } } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } return this; } /** @param nothing @return String A to String method that would allow us to print out the MyStringBuilder object **/ public String toString(){ if(this.start == null){ return emptyStr; } //this will add the characters together in the CharNode String result = emptyStr; CharNode currNode = this.start; for(int i = 0; i < this.length(); i++){ result = result + Character.toString(currNode.getData()); currNode = currNode.getNext(); } return result; } /** @param char variable, int variable @return MyStringBuilder object inserting a character in a specific index within the object, which we're pushing the previous node at the index to the right, and shifting the other CharNodes after the index will be shifting to the right **/ public MyStringBuilder insert(char c, int index) throws MSBOutOfBoundsException{ try{ if(index > this.length() || index < 0){ throw new MSBOutOfBoundsException(Constants.FROM_INSERT_CHAR, "MSB Out of Bound Exception"); } //inserting the character at the very beginning of the object else if(index == 0){ CharNode newNode = new CharNode(c); newNode = newNode.setNext(this.start); this.start = newNode; this.length++; } //this will insert the character to a space after the last Node else if(index == this.length){ CharNode newNext = new CharNode(c); this.end = this.end.setNext(newNext); this.end = newNext; this.length++; } //this will insert a character within the bounds of the first node and the last //node else if(index > 0 && index < this.length){ CharNode newNode = new CharNode(c); CharNode newCurrNode = this.start; CharNode currNode = this.start; //this iterates till the index for(int i = 1; i < index; i++){ currNode = currNode.getNext(); } //iterates till the index for(int j = 1; j <= index; j++){ newCurrNode = newCurrNode.getNext(); } //adds the next node of the currNode to that of the added CharNodes // and link the new added CharNode to that of the next CharNode currNode = currNode.setNext(newNode); newNode = newNode.setNext(newCurrNode); this.length++; } } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } return this; } /** @param String variable, and int index @return MyStringBuilder object This will insert an entire String at a specific index, shifting every other Charnode after that index to the right **/ public MyStringBuilder insert (String str, int index) throws BadInputException, MSBOutOfBoundsException{ try{ if(str == null){ throw new BadInputException(Constants.FROM_INSERT_STR, "Bad input exception"); } if(index > this.length() || index < 0){ throw new MSBOutOfBoundsException(Constants.FROM_INSERT_STR, "MSB Out of Bound Exception"); } //when the index starts at the beginning of the object, the entire sstring will //be at the start of the object else if(index == 0){ for(int i =0 ; i < str.length(); i++){ this.insert(str.charAt(i),i); } } //this will insert a string at a certain index in between the start and end of //the MyStringBuilder object else if(index > 0 && index < this.length){ for(int i =0; i < str.length(); ++i){ this.insert(str.charAt(i), index+i); } } //this will add the string to the very end of the MyStringBuilder object else if(index == this.length){ for(int i =0; i < str.length(); i++){ this.insert(str.charAt(i), index+i); } } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } return this; } /** @param int index @return CharNode Finds CharNode at an index in the object **/ protected CharNode findIndex(int index) throws MSBOutOfBoundsException{ CharNode currNode = this.start; try{ if(this.start == null && this.end == null){ throw new MSBOutOfBoundsException(Constants.FROM_FIND_INDEX, "Out of Bound"); } if(index < 0 || index >= this.length){ throw new MSBOutOfBoundsException(Constants.FROM_FIND_INDEX, "Out of Bound"); } } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } //when the index is 0, it'll return the first CharNode if(index == 0){ return this.start; } //Iterates till index, returns the CharNode at that index else{ for(int i = 1; i <= index; i++){ currNode = currNode.getNext(); } return currNode; } } /** @param int index @return MyStringBuilder object remove the CharNode at a certain index **/ public MyStringBuilder remove (int index) throws MSBOutOfBoundsException{ try{ if(index < 0 || index >= this.length){ throw new MSBOutOfBoundsException(Constants.FROM_REMOVE, "Out of Bound"); } //when the index is 0, this will remove the first index of the object called else if(index == 0){ CharNode nextNode = this.start.getNext(); this.start = nextNode; this.length--; return this; } //when the index is between the first index and the last index, it'll remove //the CharNode within that boundary else if (index > 0 && index < this.length-1){ CharNode prevNode = this.start; CharNode nextNode = this.start; //iterates till the index for(int a = 1; a < index; a++){ prevNode = prevNode.getNext(); } //iterates till the index, including the index for(int c = 1; c <= index + 1; c++){ nextNode = nextNode.getNext(); } //this will connect the prevNode to that of the Next Node, which would Remove //the CharNode inbetween the two nodes prevNode = prevNode.setNext(nextNode); this.length--; return this; } //When removing the last index of the called object, we're iterating to the //very end of object, and make the last index to the previous node else if(index == this.length-1){ CharNode currNode = this.start; for(int i =1; i < this.length; i++){ currNode = currNode.getNext(); } this.end = this.end.setNext(currNode); this.length--; return this; } } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } return this; } /** @param int index @return MyStringBuilder object this will delete everything after the index **/ public MyStringBuilder delete (int startIndex) throws MSBOutOfBoundsException{ try{ if(startIndex < 0 || startIndex >= this.length){ throw new MSBOutOfBoundsException(Constants.FROM_DELETE_STARTINDEX, "Out Of Bound"); } //deleting all the CharNodes from the entire object else if(startIndex ==0){ this.end = this.end.setNext(this.start); this.length = startIndex; return this; } //removing the CharNodes within the boundaries of the starting index to last //index else if(startIndex > 0 && startIndex this.length || startIndex >= this.length){ throw new MSBOutOfBoundsException( Constants.FROM_DELETE_STARTINDEX_ENDINDEX,"Out Of Bound"); } if(endIndex < startIndex){ throw new BadInputException(Constants.FROM_DELETE_STARTINDEX_ENDINDEX, "Out Of Bound"); } //this will return the original MyStringBuilder without any edits else if(startIndex == endIndex){ return this; } else{ //this will iterate from the start Index til the end index CharNode currNode = this.start; CharNode nextNode = this.start; for(int i = 1; i < startIndex; i++){ currNode = currNode.getNext(); } for(int i =1; i <= endIndex; i++){ nextNode = nextNode.getNext(); } /**this will connect the CharNodes together, including the end Index in This this will connect the CharNode from the start index, to the charNode of the end Index **/ currNode = currNode.setNext(nextNode); this.length = this.length - (endIndex-startIndex); return this; } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } return this; } /** @param int index @return String This substring includes the character(s) from start index to the end charNode of the MyStringBuilder object **/ public String substring(int startIndex) throws MSBOutOfBoundsException{ String result = emptyStr; try{ if(startIndex < 0 || startIndex >= this.length){ throw new MSBOutOfBoundsException(Constants.FROM_SUBSTRING_STARTINDEX, "Out Of Bound"); } //this will iterate through the MyStringBuilder object til the start index else{ CharNode currNode = this.start; for(int i = 0; i < startIndex; i++){ currNode = currNode.getNext(); } //this is when we start grabbing the data from the startIndex to the very end //of the MyStringBuilder object for(int j = startIndex; j < this.length; j++){ result = result + Character.toString(currNode.getData()); currNode = currNode.getNext(); } return result; } } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } return result; } /** @param MyStringBuilder object @return nothing subString method that takes away the startIndex to the endIndex but not including the end index. **/ public String substring(int startIndex, int endIndex) throws MSBOutOfBoundsException, BadInputException{ String result = emptyStr; try{ if(startIndex < 0 || endIndex < 0 || endIndex > this.length || startIndex >= this.length){ throw new MSBOutOfBoundsException( Constants.FROM_SUBSTRING_STARTINDEX_ENDINDEX,"Out Of Bound"); } if(endIndex < startIndex){ throw new BadInputException( Constants.FROM_SUBSTRING_STARTINDEX_ENDINDEX,"Out Of Bound"); } //a empty string will be returned if the start index and end index are the same else if(startIndex == endIndex){ return result; } else{ //this will go through the reference from the zero index of the MyStringBuilder //object, and will continue to iterate til the CharNode before the start index CharNode currNode = this.start; for(int i =0; i < startIndex; i++){ currNode=currNode.getNext(); } //starts adding the characters between startIndex and end Index, including //start index for(int j = startIndex; j < endIndex; j++){ result = result + Character.toString(currNode.getData()); currNode = currNode.getNext(); } return result; } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } catch(MSBOutOfBoundsException msbEx){ System.out.println(msbEx.getMessage()); } return result; } /** @param MyStringBuilder second obj @return MyStringBuilder obj adds a new MyStringBuilder obj to the current MyStringBuilder obj **/ public MyStringBuilder concat(MyStringBuilder rightOperand) throws BadInputException{ try{ if(rightOperand == null){ throw new BadInputException(Constants.FROM_CONCAT, "Bad Input Exception"); } //we set the first and end CharNode of the second obj to that of the called //object if(this.length == 0){ this.start = rightOperand.start; this.end = rightOperand.end; this.length = rightOperand.length(); return this; } //we connect the end CharNode of the called object to the start CharNode of the //inputted object else{ this.end = this.end.setNext(rightOperand.start); this.end = rightOperand.end; this.length = this.length + rightOperand.length(); return this; } } catch(BadInputException badInputEx){ System.out.println(badInputEx.getMessage()); } return this; } //TESTING THE PROGRAM!!!! // public static void main(String[] args){ // String testStr = "testing"; // String divider = "_________"; // try{ // MyStringBuilder word = new MyStringBuilder('r'); // System.out.println("Testing regular toString char"); // System.out.println(word); // //testing ToString with obj Constructor // MyStringBuilder someWord = new MyStringBuilder("something"); // System.out.println("_________ testing Constructor(obj)"); // MyStringBuilder newWord = new MyStringBuilder(someWord); // System.out.println(newWord.toString()); // //testing insert() // MyStringBuilder insertTest = new MyStringBuilder("rest"); // System.out.println("___________ testing insert(Char)"); // insertTest.insert('e', 3); // System.out.println(insertTest); // System.out.println("length of InsertTest=" + insertTest.length); // System.out.println("All insert boundary cases worked!!!"); // System.out.println(divider); // insertTest.insert("best", 2); // System.out.println(insertTest); // System.out.println("InsertTest(String) Good!"); // } // catch(BadInputException ex){} // //testing ToString method // catch(MSBOutOfBoundsException ex){} // System.out.println("______________Append(string)"); // //testing append(string) // try{ // MyStringBuilder extra = new MyStringBuilder("Coming"); // extra.append("Home"); // System.out.println("Append(String) length=" + extra.length); // System.out.println(extra.toString()); // System.out.println(divider + "FindIndex(Int) return CharNode"); // System.out.println(extra.findIndex(9).getData()); // System.out.println(divider + "Remove(int index)"); // System.out.println(extra.remove(0)); // System.out.println("length=" + extra.length()); // System.out.println(divider + "Delete(int starterIndex)"); // System.out.println(extra.delete(5)); // System.out.println(divider + "Delete(int start, int end)"); // System.out.println(extra.delete(2,2)); // System.out.println(divider + "Substring(int start)"); // System.out.println(extra.substring(2)); // System.out.println(divider + "Substring(int start, int end)"); // System.out.println(extra.substring(0, 4)); // System.out.println(divider + "Concat(obj MyStringBuilder)"); // MyStringBuilder credit = new MyStringBuilder("together"); // // System.out.println(credit); // // extra.concat(credit); // // System.out.println(extra); // MyStringBuilder a = new MyStringBuilder(""); // MyStringBuilder b = new MyStringBuilder("bob"); // a.concat(b); // System.out.println(a); // } // catch(MSBOutOfBoundsException msbEx){} // catch(BadInputException badInputEx){} // // } }