Java: StringIndexOutOfBoundsException when using .charAt() in for-loop - java

thank you in advance for reading about my problem.
I am making a Hangman game where I want to print out a hidden version of the current word, but I would like to update it when a correct letter is guessed (on the right spot, too). I've been looking around StackOverflow but I just can't seem to find an explaination that I understand. If someone could help me, that would be great. :D
I'll post the for-loop that this is about. I can post more of the code if you might need it. The answerInput and guessInputString are both read from the console earlier in my code using a br.readLine() method.
for (int i = 0; i < inputAnswer.length(); i++) {
char inputAnswerChar = inputAnswer.charAt(i);
char guessInputChar =guessInputString.charAt(i);
if (inputAnswerChar == guessInputChar) {
replacementString.replace(replacementString.charAt(i), inputAnswerChar);
}
}
Thank you for any help that you can give me!

Your code is assuming that guessInputString and replacementString both have at least as many characters as inputAnswer, which is obviously wrong to assume, since your loop only guarantees that the i'th character exists for the inputAnswer String.
BTW, replacementString.replace(replacementString.charAt(i), inputAnswerChar) has no effect, since it cannot change the String it is executed for (since Strings are immutable). You must assign the new String returned by this method back to replacementString :
replacementString = replacementString.replace(replacementString.charAt(i), inputAnswerChar)

Related

Adding Char to Char Array in Java

I'm still pretty new to Java so bear with me. I'm making a simple hangman game that takes input from the user. I am trying to append the guessed letter to the knownLetters array but I get a type mismatch. I tried .concat() and got the same type error. Here is where I am now. Any ideas or documentation resources (that a novice can read) would be helpful. Thanks!
Edit: Thanks for the comments, everyone! These are very helpful.
public static boolean updateWithGuess(char[] knownLetters,
char guessedLetter,
String word) {
System.out.println(Arrays.toString(knownLetters));
int i = 0;
while(word.indexOf(i, guessedLetter) != -1) {
i = word.indexOf(i, guessedLetter) + 1;
knownLetters += guessedLetter;
Using arrays in that case is not the best choice because arrays have a fixed size and you cannot dynamically add and remove items, maybe rather choose lists.
If you need a simple introduction, here you are:
https://www.geeksforgeeks.org/list-interface-java-examples/
Others have mentioned StringBuilder and List which are a step in the right direction as they dynamic (in number of elements). However since this question is only concerned with keeping track of each letter that was guessed a set makes the most sense. One common example is HashSet. Sets do not allow duplicates. However sets will allow both the upper and lower case versions of a character to be present in the set (since they have different values). So you could normalize all the guesses and known letters to either uppercase or lowercase.

Why does this recursive Java method for counting two characters work?

Trying to learn Java at the moment. I was just solving a few recursion problems, and I came across one that asked me to count the occurrences the substring "hi" in another string. I was looking for recursive ways to do this, and I found a code that basically did what I wanted and I could paraphrase, but I didn't understand how/why it works. I had no issue with the other recursion problems, and I understand the concept of calling a function within its body, but the way this code works puzzles me. Stepping through it in a debugger just confused me.
public int countHi(String str) {
int n = str.length();
if(n <= 1) return 0;
if(str.substring(0, 2).equals("hi"))
return countHi(str.substring(1)) + 1;
return countHi(str.substring(1));
}
Typically all recursion breaks down to two main insights:
Base case (or terminating case): What is the simplest problem? Where do you not need to simplify?
Recursive case: How do you solve the current problem using a simpler problem's solution?
The base case here is when the string is too short - a string of less than two characters obviously can't contain "hi".
The recursive case here is that a string that starts with "hi" has one "hi" more than the rest of the string, but a string that doesn't has exactly as many "hi" when you chop off the start.
The code encodes these two insights.

Finding palindrome String throws StringIndexOutOfBoundsException, possible cause?

Provided a String, my objective is to check if I can make that String a palindrome string even after re-arranging the characters.
For eg: aaabbbb can be made palindrome by changing to : bbaaabb
So what I did try is to compare all the permutations of the string with its reverse, if it exists, print a YES! . And here is the code so far:
private static void permutation(String prefix, String str)
{
temp.setLength(0); //temp is a StringBuilder
int n = str.length();
if((n==0) && (str.charAt(0)==str.charAt(n-1)))
{
temp.append(prefix);
temp.reverse();
if(prefix.equals(temp.toString()))
{
System.out.println("YES");
System.exit(0);
}
}
else
{
for(int i=0;i<n;i++)
permutation(prefix+str.charAt(i),str.substring(0,i)+str.substring(i+1,n));
}
}
Now the problem is, at runtime I get a java.lang.StringIndexOutOfBoundsException at this line: permutation(prefix+str.charAt(i),str.substring(0,i)+str.substring(i+1,n));
What might be possibly causing this?
This line will give you the exception too:
if((n==0) && (str.charAt(0)==str.charAt(n-1)))
If n==0 then the string is empty, and charAt(0) will fail. Not sure what you're testing here.
I'm not going to debug this for you, but I will suggest a process for how to debug this kind of thing yourself.
Identify the problem. All of the detail about the palindromes is irrelevant. The problem is a java.lang.StringIndexOutOfBoundsException when calling one of the methods on the String.
Narrow in on exactly what's failing. There are several method calls in the line that is failing. If it's not obvious which method call is the problem, either single-step through it with a debugger or break that line into several lines, e.g. by creating intermediate variables to hold intermediate state.
Reproduce the problem in a simplified example. Create a new class with a main() method or write a unit test and write code that shows the problem. Remove everything that isn't absolutely essential to show the problem.
Fix your example. Once you've isolated the problem and read the documentation, it will probably be obvious how to fix it. If it's not, and you're still stuck, post the simple example on Stack Overflow and explain what you are expecting and what you're getting.
Fix your code. Apply the same fix to your original code.
String index out of bound exception -This exception is thrown by the methods of the String class, in order to indicate that an index is either negative, or greater than the size of the string itself.
In above code you are calling permutation() method recursively .
Let's say we passed String str="xy" and prefix as "" to permutation() method first time.
As its length is more than 0 it will come to the else block.
In else block we are looping str with its length.
Here length i.e n is 2.
In first loop, i=0. So prefix + str.charAt(i) will give "" + "x" = "x" and str.substring(0,i)+str.substring(i+1,n)
will give str.substring(0,0)+str.substring(0+1,2)=""+"y"="y".
Now again we are passing these values to permutation() method; i.e. permutation("x","y").
So the time when you passed these value in method, at that time instantly string str became "y" and string prefix became "x"
but still you are in loop, and in second loop i=1 and prefix+str.charAt(1) i.e. "x"+"y".charAt(1) will throw exception.
Here you can see string str="y", length is 1 and we are trying to get char at position 1. This is why you got this exception.

Java: Unexpected Type Error [duplicate]

This question already has answers here:
Replace a character at a specific index in a string?
(9 answers)
Closed 8 years ago.
Can someone help me understand why I'm getting an "Unexpected Type Error"?
if(s.charAt(i-1) == ' '){
String sub = s.substring(i, s.indexOf(' ')+1);
for(int j = 0; j < sub.length()/2; j++){
char temp;
temp = sub.charAt(j);
sub.charAt(j) = sub.charAt(sub.length()-1-j);
sub.charAt(sub.length()-1-j) = temp;
sub = sub+" ";
complete = complete+sub;
}
}
I'm getting the error on lines 6 and 7. I can't figure out why and I'd appreciate the help!
charAt() returns the character. It is not a left side operand aka you cannot assign a value to it.
Strings are immutable, which means you cannot change them (this seems to be your intention).
Instead: create a new String and add to that.
If this confused you, I try to elaborate a little: the assignment operator takes whatever is on the right and tries to shove it into whatever is on the left of it.
The problem here is that some things do not like it when you try to shove other things into them. You cannot put everything on the left that you want. Well, you can try:
"everything" = 5;
but this does not work, neither does this:
"everything" = 42;
Set aside what that last snippet failing implies to the universe and everything, your problem at hand is that charAt() is also one of those things that do not like it on the left side of the assignment operator.
I'm afraid there's no way to turn charAt() into one of those things that like it on the left side. A week after stranding on a deserted island without any plants but only solar powered refrigerators filled with steaks, this probably works:
vegetarian = meat;
Even though the vegetarian doesn't like it there, he'd accept his situation being on the left side of the = operator. He eats some steaks.
This does not hold true for what you are trying, though. There's no such deserted island for charAt().
In these lines you're trying to set the value of functions' return. This is illegal
sub.charAt(j) = sub.charAt(sub.length()-1-j);
sub.charAt(sub.length()-1-j) = temp;
as far as I see you're trying to change the characters of a String, but Strings are imutable objects. So you'll need to use a StringBuffer to set the values.

Printing an ArrayList of Strings to a PrintWriter with word wrap

Some classmates and I are working on a homework assignment for Java that requires we print an ArrayList of Strings to a PrintWriter using word wrap, so that none of the output passes 80 characters. We've extensively Googled this and can't find any Java API based way to do this.
I know it's generally "wrong" to ask a homework question on SO, but we're just looking for recommendations of the best way to do this, or if we missed something in the API. This isn't the major part of the homework, just a small output requirement.
Ideally, I'd like to be able to wordwrap the ArrayList's toString since it's nicely formatted already.
Well, this is a first for me, it's the first time one of my students has posted a question about one of the projects I've assigned them. The way it was phrased, that he was looking for an algorithm, and the answers you've all shared are just fine with me. However, this is a typical case of trying to make things too complicated. A part of the spec that was not mentioned was that the 80 characters limit was not a hard limit. I said that each line of the output file had to be roughly 80 characters long. It was OK to go over 80 a little. In my version of the solution, I just had a running count and did a modulus of the count to add the line end. I varied the value of the modulus until the output file looked right. This resulted in lines with small numbers being really short so I used a different modulus when the numbers were small. This wasn't a big part of the project and it's interesting that this got so much attention.
Our solution was to create a temporary string and append elements one by one, followed by a comma. Before adding an element, check if adding it will make the string longer than 80 characters and choose whether to print it and reset or just append.
This still has the issue with the extra trailing comma, but that's been dealt with so many times we'll be fine. I was looking to avoid this because it was originally more complicated in my head than it really is.
I think that better solution is to create your own WrapTextWriter that wraps any other writer and overrides method public void write(String str, int off, int len) throws IOException. Here it should run in loop and perform logic of wrapping.
This logic is not as simple as str.substring(80). If you are dealing with real text and wish to wrap it correctly (i.e. do not cut words, do not move comas or dots to the next line etc) you have to implement some logic. it is probably not too complicated but probably language dependent. For example in English there is not space between word and colon while in French they put space between them.
So, I performed 5 second googling and found the following discussion that can help you.
private static final int MAX_CHARACTERS = 80;
public static void main(String[] args)
throws FileNotFoundException
{
List<String> strings = new ArrayList<String>();
int size = 0;
PrintWriter writer = new PrintWriter(System.out, true); // Just as example
for (String str : strings)
{
size += str.length();
if (size > MAX_CHARACTERS)
{
writer.print(System.getProperty("line.separator") + str);
size = 0;
}
else
writer.print(str);
}
}
You can simply write a function, like "void printWordWrap(List<String> strings)", with that algorithm inside. I think, it`s a good way to solve your problem. :)

Categories

Resources