Java Substring Out of Bounds Error: Solution? - java

This lab for my intro class requires us to return any user input in pig latin.
The error I seem to keep getting when I run it and type any string into the console is this:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
The error is found here:
thisWord = x.substring(indexOfCurrentNonLetter +1, indexOfNextNonLetter);
I understand from another post this is the problem:
IndexOutOfBoundsException -- if the beginIndex is negative, or endIndex is >larger than the length of this String object, or beginIndex is larger than >endIndex.
Actually, your right edge of your substring function may be lower than the left >one. For example, when i=(size-1) and j=size, you are going to compute >substring(size-1, 1). This is the cause of you error. (Answer By Bes0ul)
My question is, what is the solution to this problem?
Here are the methods I am using:
public String pigLatin(String x)
{
String thisWord = "";
x += " ";
int indexOfNextNonLetter = 0, indexOfCurrentNonLetter = 0;
for(int i = 0; i < x.length(); i++)
{
System.out.println("At least the loop works"); //Let's play a game called find the issue
if(x.charAt(i) < 65 || x.charAt(i) > 90 && x.charAt(i) < 97 || x.charAt(i) > 122) //if it isn't a letter
{
phrase += x.charAt(i); // add our non character to the new string
for(int j = 0; j < x.substring(i).length(); j++) // find the next character that isn't a letter
{
if(x.charAt(i) < 65 || x.charAt(i) > 90 && x.charAt(i) < 97 || x.charAt(i) > 122)
{
indexOfNextNonLetter = j + i;
if(j+i > x.length())
System.out.print("Problem Here");
indexOfCurrentNonLetter = i;
System.out.println("noncharacter detected"); //I hope you found the issue
j = x.length();
thisWord = x.substring(indexOfCurrentNonLetter +1, indexOfNextNonLetter);//between every pair of nonletters exists a word
}
}
phrase += latinWord(thisWord); // translate the word
i = indexOfNextNonLetter - 1;
}
}
return phrase;
}
/*
* This converts the passed word to pig latin
*/
public String latinWord(String word)
{
String lWord = "";
String beforeVowel = "";
String afterVowel = "";
boolean caps = false;
char first = word.charAt(0);
if(first > 'A' && first < 'Z')
{
first = Character.toLowerCase(first); //If the first char is capital, we need to account for this
caps = true;
}
if(containsNoVowels(word))
lWord = Character.toUpperCase(first) + word.substring(1) + "ay"; //If we have no vowels
if(word.charAt(0) == 'A' || word.charAt(0) == 'a' || word.charAt(0) == 'E' || word.charAt(0) == 'e' || word.charAt(0) == 'I' || word.charAt(0) == '0'
|| word.charAt(0) == 'O' || word.charAt(0) == 'O' || word.charAt(0) == 'o' || word.charAt(0) == 'U' || word.charAt(0) == 'u')
{
lWord = Character.toUpperCase(first) + word.substring(1) + "yay"; //If the first char is a vowel
}
if(word.charAt(0) != 'A' || word.charAt(0) != 'a' || word.charAt(0) != 'E' || word.charAt(0) != 'e' || word.charAt(0) != 'I' || word.charAt(0) != '0'
|| word.charAt(0) != 'O' || word.charAt(0) != 'O' || word.charAt(0) != 'o' || word.charAt(0) != 'U' || word.charAt(0) != 'u')
{ //If the first letter isnt a vowel but we do have a vowel in the word
for(int m = 0; m < word.length(); m++)//if we have a vowel in the word but it doesn't start with a vowel
{
if(word.charAt(m) == 'A' || word.charAt(m) == 'a' || word.charAt(m) == 'E' || word.charAt(m) == 'e' || word.charAt(m) == 'I' || word.charAt(m) == 'm'
|| word.charAt(m) == 'O' || word.charAt(m) == 'O' || word.charAt(m) == 'o' || word.charAt(m) == 'U' || word.charAt(m) == 'u')
{
for(int l = 0; l < word.substring(m).length(); l++)
{
afterVowel += word.substring(m).charAt(l); //Build the part after the first vowel
}
m += word.length();
}
else
beforeVowel += word.charAt(m);
}
if(caps == false)
lWord = afterVowel + beforeVowel + "ay";
else
{
first = Character.toUpperCase(afterVowel.charAt(0));
}
}
return lWord;
}
/*
* This function checks the string letter by letter to see if any of the letters are vowels.If there are none it returns true
*/
public boolean containsNoVowels(String wrd)
{
for(int h = 0; h < wrd.length(); h++)
{
if(wrd.charAt(h) == 'A' || wrd.charAt(h) == 'a' || wrd.charAt(h) == 'E' || wrd.charAt(h) == 'e' || wrd.charAt(h) == 'I' || wrd.charAt(h) == 'h'
|| wrd.charAt(h) == 'O' || wrd.charAt(h) == 'O' || wrd.charAt(h) == 'o' || wrd.charAt(h) == 'U' || wrd.charAt(h) == 'u')
return false;
else
return true;
}
return false;
}

I think the error lies inside your second for loop within pigLatin():
for (int j = 0; j < x.substring(i).length(); j++) // find the next character that isn't a letter
{
if(x.charAt(i) < 65 || x.charAt(i) > 90 && x.charAt(i) < 97 || x.charAt(i) > 122)
The last line shown above starts checking at char i. This is the same char you just checked in the outer loop. So the test will succeed. And I think the logic breaks down either in this iteration or a subsequent one.
I think what you want is:
for(int j = 1; j < x.substring(i).length(); j++)
{
if (x.charAt(j) < 65 || x.charAt(j) > 90 && x.charAt(j) < 97 || x.charAt(j) > 122)
Note, there are two changes:
Initialise j at 1 to test the next character in the for statement
Test the jth character, not the ith in the if statement

Related

Vowel substring

I have to write a program that takes a String as user input and then prints a substring that starts with the first vowel of the String and ends with the last. So for instance if my String is : "Hi I have a dog named Patch", the printed substring would be : "i I have a dog named Pa"
This is the code I have now:
import java.util.Scanner;
import java.util.*;
public class SousChaineVoyelle {
private static Scanner sc;
public static void main (String[] args) {
sc = new Scanner(System.in);
System.out.print("Enter a String: ");
String str = sc.nextLine();
int pos1 = 0;
int pos2 = 0;
int i;
int j;
boolean isVowel1 = false;
boolean isVowel2 = false;
for (i = 0; i < str.length(); i++){
if (str.charAt(i) == 'A' || str.charAt(i) == 'a' ||
chaine.charAt(i) == 'E' || str.charAt(i) == 'e' ||
str.charAt(i) == 'I' || str.charAt(i) == 'i' ||
str.charAt(i) == 'O' || str.charAt(i) == 'o' ||
str.charAt(i) == 'U' || str.charAt(i) == 'u' ||
str.charAt(i) == 'Y' || str.charAt(i) == 'y'){
isVowel1 = true;
break;
}
}
if (isVowel1){
pos1 = str.charAt(i);
}
for (j = str.length() - 1; j > i; j--){
if (str.charAt(j) == 'A' || str.charAt(j) == 'a' ||
str.charAt(j) == 'E' || str.charAt(j) == 'e' ||
str.charAt(j) == 'I' || str.charAt(j) == 'i' ||
str.charAt(j) == 'O' || str.charAt(j) == 'o' ||
str.charAt(j) == 'U' || str.charAt(j) == 'u' ||
str.charAt(j) == 'Y' || str.charAt(j) == 'y'){
isVowel2 = true;
break;
}
}
if (isVowel2){
pos2 = str.charAt(j);
}
String sub = chaine.substring(pos1, pos2);
System.out.print(The substring from the first vowel to the last is "\"" + sub +"\"");
}
}
this got me this:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:55)
at java.base/jdk.internal.util.Preconditions$1.apply(Preconditions.java:52)
at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:213)
at java.base/jdk.internal.util.Preconditions$4.apply(Preconditions.java:210)
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
at java.base/java.lang.String.checkIndex(String.java:4557)
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:46)
at java.base/java.lang.String.charAt(String.java:1515)
at SousChaineVoyelle.main(SousChaineVoyelle.java:33)
One way of looking at it is you have a lot of code to do a simple thing, which means more chances for bugs and errors.
Here's a "less code" solution:
str = str.replaceAll("(?i)^[^aeiou]*|[^aeiou]*$", "");
See live demo.
This works by matching all leading and trailing non-vowels (if any) and replacing them with nothing, effectively deleting them.
(?i) makes the match case insensitive.
After the first for loop, i will be str.length() no matter what. You may want to create another variable to hold I when it's found to remedy this.

How to check if a certain character is present in the String?

I have wrote a below code to find a keyword co_e in the below string, where _ represents any other character.
It works good if I change the String to "aaacodebbb" or "codexxcode"
but if I change it to "xxcozeyycop" it throws StringIndexOutOfBoundsException
public int countCode(String str) {
int count = 0;
String result = "";
boolean yes = true;
for (int i = 0; i < str.length(); i++) {
// yes = str.charAt(i+3);
if (str.length() >= 3) {
if (str.charAt(i) == 'c' && str.charAt(i + 1) == 'o' && str.charAt(i + 3) == 'e')
count++;
}
}
return (count);
}
Your out-of-bounds error occured in this line:
if (str.charAt(i) == 'c' && str.charAt(i + 1) == 'o' && str.charAt(i + 3) == 'e')
The error happened at str.charAt(8) for str = "xxcozeyycop", because str.length() is 11, and str.charAt(11) is clearly out of bounds (and so are all str.charAt(str.length()))
Here is one possible solution. Note that if str.length() < 4, the for loop cannot run, as i + 3 will always go out of bounds. Also, when i == str.length() - 4 for all strings longer than four chars, i+3 would equal the last index of the string, str.length() - 1.
for (int i = 0; i < str.length() - 3; i++) {
char c1 = str.charAt(i);
char c2 = str.charAt(i + 1);
char c4 = str.charAt(i + 3);
if (c1 == 'c' && c2 == 'o' && c4 == 'e')
count++;
}
In the loop, you are checking accessing i+3. So, you have to stop when i is at 4th last position.
Replace if(str.length()>= 3) with if(str.length()>= 3 && str.length() - i >3)
OR
You can put the following as the first condition in your for loop:
if(str.length() - i <=3){
break;
}

Java word counting [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I'm trying to count words by using whitespace as my indicator for when there is a new word.
My current code is returning crazy results for wordCounter, but my vowelCounter is working perfectly.
I apologize if this is a basic or simple question...I'm just starting out with Java and I would really appreciate any assistance!
System.out.println("Please enter some text: ");
String fileContent = input.nextLine().toLowerCase();
int vowelCounter = 0;
int wordCounter = 0;
for (int i = 0; i < fileContent.length(); i++) {
if(fileContent.charAt(i) == 'a' || fileContent.charAt(i) == 'e' || fileContent.charAt(i) == 'i'|| fileContent.charAt(i) == 'o' || fileContent.charAt(i) == 'u')
vowelCounter++;
for (int j = 0; j < fileContent.length(); j++) {
if (Character.isWhitespace(fileContent.charAt(j))) {
wordCounter++;
}
}
}
System.out.println("\nVowel Counter: " + vowelCounter);
System.out.println("Word Counter: " + wordCounter);
That is what happens when you have bad indentation. You are having nested for-loops instead of 2 separate for-loops.
Separate your loops like:
for (int i = 0; i < fileContent.length(); i++) {
if(fileContent.charAt(i) == 'a' || fileContent.charAt(i) == 'e' || fileContent.charAt(i) == 'i'|| fileContent.charAt(i) == 'o' || fileContent.charAt(i) == 'u')
vowelCounter++;
}
for (int j = 0; j < fileContent.length(); j++) {
if (Character.isWhitespace(fileContent.charAt(j)))
wordCounter++;
}
Or have them in 1 single for-loop:
for (int i = 0; i < fileContent.length(); i++) {
if(fileContent.charAt(i) == 'a' || fileContent.charAt(i) == 'e' || fileContent.charAt(i) == 'i'|| fileContent.charAt(i) == 'o' || fileContent.charAt(i) == 'u')
vowelCounter++;
else if (Character.isWhitespace(fileContent.charAt(i))) {
wordCounter++;
}
}
Above all, to check that specific characters (such as vowels) exist in your string, you can do it as:
char ch = fileContent.charAt(i);
if("aeiou".contains("" + ch))
You have a redundant loop inside your loop. Just add the second if to the same loop:
for (int i = 0; i < fileContent.length(); i++) {
if(fileContent.charAt(i) == 'a' || fileContent.charAt(i) == 'e' || fileContent.charAt(i) == 'i'|| fileContent.charAt(i) == 'o' || fileContent.charAt(i) == 'u')
vowelCounter++;
else if (Character.isWhitespace(fileContent.charAt(i)))
wordCounter++;
}
You might wanna add 1 to the wordcount because it ia counting the number of whitespaces. For eg: in "apple banana", there is 1 whitespace but 2 words. Besides that, counting whitespaces has shortcomings, for instance, when there are two or more consecutive whitespaces between the words.

Ignoring digits, blank spaces and read String input, using Character.isLetter & Character.isDigit

I have been stuck for quite some time. I would need to ignore digits entered, blank spaces and special characters like $^%##&! and just read the other letters a-z, using Character.isDigit & Character.isLetter.. I have tried using the both methods, it didn't work out for me.. Please advice..
The error:
The normal output (without spaces and digits) :
The expected output should be 438-5626 even when I entered 123$#GetLoan.. They should ignore the first few characters '123$#' and read only GetLoan..
Full Question: Write a program that prompts the user to enter a telephone number expressed in letters and outputs the corresponding telephone number in digits. If the user enters more than seven letters, then process only the first seven letters. Also output the – (hyphen) after the third digit. Allow the user to use both uppercase and lowercase letters as well as spaces between words.
public class Question3 {
public static void main(String[] args) {
String letters;
char phoneDigit;
Scanner kb = new Scanner(System.in);
System.out.println("Enter letters : ");
letters = kb.next();
for (int i = 0; i < 7; i++) {
phoneDigit = letters.charAt(i);
if (Character.isLetter(phoneDigit) == true) {
if (i == 3) {
System.out.println("-");
} //If
if (phoneDigit >= 'A' && phoneDigit <= 'C'
|| phoneDigit >= 'a' && phoneDigit <= 'c') {
System.out.println("2");
} else if (phoneDigit >= 'D' && phoneDigit <= 'F'
|| phoneDigit >= 'd' && phoneDigit <= 'f') {
System.out.println("3");
} else if (phoneDigit >= 'G' && phoneDigit <= 'I'
|| phoneDigit >= 'g' && phoneDigit <= 'i') {
System.out.println("4");
} else if (phoneDigit >= 'J' && phoneDigit <= 'L'
|| phoneDigit >= 'j' && phoneDigit <= 'l') {
System.out.println("5");
} else if (phoneDigit >= 'M' && phoneDigit <= 'O'
|| phoneDigit >= 'm' && phoneDigit <= 'o') {
System.out.println("6");
} else if (phoneDigit >= 'P' && phoneDigit <= 'S'
|| phoneDigit >= 'p' && phoneDigit <= 's') {
System.out.println("7");
} else if (phoneDigit >= 'T' && phoneDigit <= 'V'
|| phoneDigit >= 't' && phoneDigit <= 'v') {
System.out.println("8");
} else if (phoneDigit >= 'W' && phoneDigit <= 'Z'
|| phoneDigit >= 'W' && phoneDigit <= 'z') {
System.out.println("9");
} // If
} // If
} // For loop
} //PSVM
Below fragment is probably the problem:
for (int i = 0; i < 7; i++) {
phoneDigit = letters.charAt(i);
if (Character.isLetter(phoneDigit) == true) {
You are taking first 7 characters, and printing only the ones that are letters. So for input string 123getloan you will iterate over 123getl, and then isLetter will reject 123, so your program later will deal only with getl.
To iterate over only 7 letters you would need to change it to increment i only if given character is a letter e.g. by doing the below:
int i = 0;
for (char phoneDigit : letters.toCharArray()) {
if (Character.isLetter(phoneDigit)) {
i++;
// other ifs here
if (i == 3) {
System.out.println("-");
}
}
if (i >= 7) {
break;
}
}
EDIT: Fixed problem mentioned by #Andreas

Number of vowels within an array

I'm trying to write a program which declares and initializes an array of characters (char[] word) and calls the method:
public static int countVowels(char[])
which returns the number of vowels in word.
Can anyone tell me where im going wrong? Getting this error
java:11: error: char cannot be dereferenced
for (int j=0; j < word[i].length(); j++) {
^
array.java:12: error: char cannot be dereferenced
char c = word[i].charAt(j);
^
2 errors
 
public class array {
public static void main(String[] args) {
char[] word = {'a','b','f','u','g','i','o','r'};
}
public static int countVowels(char[] word) {
int vowelCount = 0;
for (int i = 0; i < word.length; i++)
{
for (int j=0; j < word[i].length(); j++) {
char c = word[i].charAt(j);
if ( (c == 'a')
|| (c == 'e')
|| (c == 'i')
|| (c == 'o')
|| (c == 'u')
|| (c == 'A')
|| (c == 'E')
|| (c == 'I')
|| (c == 'O')
|| (c == 'U')
)
vowelCount++;
}
}
}
}
You don't really need the inner loop. Try this:
public class array {
public static void main(String[] args) {
char[] word = {'a','b','f','u','g','i','o','r'};
}
public static int countVowels(char[] word) {
int vowelCount = 0;
for (int i = 0; i < word.length; i++)
{
char c = word[i];
if ( (c == 'a')
|| (c == 'e')
|| (c == 'i')
|| (c == 'o')
|| (c == 'u')
|| (c == 'A')
|| (c == 'E')
|| (c == 'I')
|| (c == 'O')
|| (c == 'U')
)
vowelCount++;
}
return vowelCount;
}
}
When you call word[i], you're getting the value stored at the ith position in the array word. So, word[i].length returns the length of the value stored in the ith position. You're getting an error because the value stored is a char, which doesn't have a length attribute. Instead, try just word.length. This will give you the length of the array.
With this information, you should have enough to fix your for loop code. Remember, word[i] returns a char.
Try word.length. The code should not run in the browser, because it's not javascript. instead it is java.
You have more than one error;
Just use these;
for (int j=0; j < word.length; j++) {
char c = word[i];
instead of these down below (these are invalid);
for (int j=0; j < word[i].length(); j++) {
char c = word[i].charAt(j);
To get the length of the array, length is enough, you don't have to put the paranthesis. And also when you assign the ith char element of the word array, c = word[i]; is valid.
I've just corrected your method and just have written a test code for it. You also used unnecessary outer for-loop, which causes invalid result.
Additional to your corrected method, I've added my method for counting vowels, which uses a secondary array for storing the vowels. It's much more readable but the choice is yours ;)
public class TestCountVowels {
public static void main(String[] args) {
char[] word = {'a','b','f','u','g','i','o','r'};
//I advice calling geVowelCount(char[]) method
System.out.println("Vowel count: " + getVowelCount(word) );
//Calling your method with my corrections
System.out.println("Vowel count: " + yourCountMethod(word) );
}
//My method for comparing char arrays and counting
public static int getVowelCount(char[] inputWord) {
char[] vowels = {'a','A','e','E','i','I','o','O','u','U'};
int vowelCount = 0;
for( int i = 0; i < inputWord.length; i++ ) {
for( int j = 0; j < vowels.length; j++ )
if ( inputWord[i] == vowels[j] ) {
vowelCount++;
continue;
}
}
return vowelCount;
}
//Your method with corrections
public static int yourCountMethod(char[] word) {
int vowelCount = 0;
for (int i = 0; i < word.length; i++)
{
char c = word[i];
if (
(c == 'a') ||
(c == 'e') ||
(c == 'i') ||
(c == 'o') ||
(c == 'u') ||
(c == 'A') ||
(c == 'E') ||
(c == 'I') ||
(c == 'O') ||
(c == 'U')
)
vowelCount++;
}
return vowelCount;
}
}
Hope that it helps.

Categories

Resources