String index out of range, string input from File - java

Okay SO. I've got a try-catch block that has no issues but the thing is when I import the first line of a text file, it says that the String index is out of range:33.
That line is "The Dentist Pulled My Tooth Out"
What I'm doing is using a for loop to evaluate every character in a line until we reach the end of said line. If the character is a vowel, then I increment a vowel integer. Otherwise, if it is a blank space, then I change the blank space to a tilde(~). What I want to know is why it says my String is out of range and how would I change a blank space in the line of text from the file to a tilde. I can figure out outputting it to a different file(that's what I have to do) by myself. I'm just confused why its saying its out of range. I've pasted my entire program below.
The goal of the program is to evaluate a text file, character by character, and count the number of vowels. Also, I have to change any blank spaces to tildes, then reoutput to a different text file.
The code is below:
import java.io.File;
import java.util.Scanner;
import java.io.IOException;
import java.io.FileWriter;
public class Vowels {
public static void main(String[] args) {
Scanner inFile;
File dentist = new File("poetry.txt");
int vowels = 0;
try {
for (int i = 0; i >= 0; i++) {
inFile = new Scanner(new File("poetry.txt"));
String str1 = inFile.nextLine();
for (int a = 0; a >= 0; a++) {
String start;
start = str1.substring(a, a + 1);
if (start.equalsIgnoreCase("a") == true)
vowels++;
else if (start.equalsIgnoreCase("e") == true)
vowels++;
else if (start.equalsIgnoreCase("i") == true)
vowels++;
else if (start.equalsIgnoreCase("o") == true)
vowels++;
else if (start.equalsIgnoreCase("u") == true)
vowels++;
else if (start.equalsIgnoreCase(" "))
start = " ";
}
}
} catch (IOException i) {
System.out.println("Error");
}
}
}

You should take the new Scanner out of the loop, then change your loop to while(inFile.hasNextLine()) ... you're not using "i" at all.
Also, your inner loop will never end, and that's why you're getting an index exception. Instead of having a>=0, replace that with a<str1.length().
Replace that substring thing with str1.charAt(a), then compare that char (not String) to single quoted chars... 'a', 'e', 'i', etc. using a simple ==. char is a native datatype, so you can just do Character.toLowerCase(start) == 'a' Notice I forced the character to lowercase before comparing, which replaces the "ignore case". You don't have to do the Character.toLowerCase every time if you just say start = Character.toLowerCase(start) though.

There are several things going on in this piece of code.
for(int i = 0; i>=0; i++){
inFile = new Scanner(new File("poetry.txt"));
String str1 = inFile.nextLine();
That will loop almost 2^32/2 - 1 times.
That creates a new Scanner object everytime.
You are reading the first time everytime.
for(int a = 0; a >= 0; a++) {
String start;
start = str1.substring(a, a + 1);
}
This will again loop for 2^32/2 - 1 times.
Since the str1 is not as big as the variable 'a' can be, it crashes. You need to make this loop as
for(int a = 0; a < (str1.length() - 1); a++) {
String start = str1.substring(a, a + 1);
}
This should sorta fix your problem.

You can do away the long if-else structure by using
String STR_VOWELS = "aeiou";
if(STR_VOWELS.contains(start)) {
vowels++;
} else if (start.equals(" ")) {
// you can remove this else as well, as you are not doing any thing different here.
start = " ";
}
Hope this helps.

For replace blank,
When you get the input in to a one string then simply use
String my_new_str = my_str.replaceAll(" ", "~");
then write back to a file
String replace

try replacing second for loop with following code, this shall fix your problem
String str1 = inFile.nextLine();
for(int a = 0; a < str1.length()-1; a++){ // a< string.length() otherwise exception will occur

Related

What is the best way to replace a letter with the letter following it in the alphabet in Java?

I'm a programming newbie and I am doing a coderbyte exercise that says "
Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a)"
i'm thinking of the following methods:
declare a string called "abcdefghijklmnopqrstuvxyz" and compare each string's char index position with the alphabet's index position, and then just bring the alphabet char that is located at the i+1 index location. But I don't know how it would work from z to a.
I've seen some techniques using ASCII values for every char but I've never done that before and not sure how it works
convert the given string into a char[] array, but then I'm not sure how I would tell the system to get me the next alphabet char
What would be the easiest way to do this?
EDIT
this is my code so far, but it doesn't work.
import java.util.*;
import java.io.*;
class Main {
public static String LetterChanges(String str) {
// code goes here
String alphabet = "abcdefghijklmnopqrstuvwxyz";
String newWord = "";
for (int i = 0; i < str.length(); i++){
for (int j = 0; j < alphabet.length(); i++){
if (str[i] == alphabet[i]){
if (alphabet[i+1].isVowel()){
newWord = newWord + toUpperCase(alphabet[i+1]);
}
else{
newWord = newWord + alphabet[i+1];
}
}
}
}
return str;
}
public static void main (String[] args) {
// keep this function call here
Scanner s = new Scanner(System.in);
System.out.print(LetterChanges(s.nextLine()));
}
}
Can't I ask for the index position of a Char that is a part of a String? in C I could do that.
Other than that not sure why it doesn't work.
I would definitely go with method 1.
I believe what you're looking for is the indexOf method on a String.
First of, I would create a method that given a character finds the next letter in the alphabet and return that. This could be done by finding the letter in your alphabet string and then fetch the letter at index+1. As you also pointed out you would need to take care of the edge case to turn 'z' into 'a', could by done with an if-statement or by having an extra letter 'a' at the end of your alphabet string.
Now all that remains to do is create a loop that runs over all characters in the message and calls the previously made method on that character and constuct a new string with the output.
Hope this helps you figure out a solution.
Assuming that there would be only lower case English letters in the given String the most performant way would be to add +1 to every character, and use either if-statement checking whethe the initial character was z or use the modulo operator % as #sp00m has pointed out in the comment.
Performing a search in the alphabetic string (option 1 in your list) is redundant, as well extracting array char[] from the given string (option 3).
Checking the edge case:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = str.charAt(i);
if (next == 'z') result.append('a'); // checking the edge case
else result.append((char) (next + 1));
}
return result.toString();
}
Applying modulo operator:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = (char) ((str.charAt(i) - 'a' + 1) % 26 + 'a');
result.append(next);
}
return result.toString();
}
main()
public static void main(String[] args) {
System.out.println(shiftLetters("abc"));
System.out.println(shiftLetters("wxyz"));
}
Output:
bcd // "abc"
xyza // "wxyz"

Java exception error for Disemvowel [duplicate]

I have a bug in this block of code. The debugger suggest it´s cause is this line of code char chr = getSecretWord.charAt(i);
What this code does is look for a match between userInput and secretWord. I have the for loop to go through the length of the secretWord letters one by one, and if there is a letter matching return true. If not, return false... but the program crashes when it is suppose to just return false... I guess it is something with this line, but do not know exactly what getSecretWord.charAt(i);
private boolean isMatchingSecretWord(String userInput)
{
String secretWord = "";
String getSecretWord = getSecretWord();
for (int i = 0; i <= getSecretWord.length();i++)
{
char chr = getSecretWord.charAt(i);
secretWord = ""+chr;
if (secretWord.equals(userInput))
{
println("is true");
return true;
}
}
return false;
}
As an side note, is what I´ve done with this code correct, assigning the getSecretWorld() Method to a String so I can use the Strings method length()?
String getSecretWord = getSecretWord();
for (int i = 0; i <= getSecretWord.length();i++)
Debug code:
Exception in thread "Thread-4" java.lang.StringIndexOutOfBoundsException: String index out of range: 4
at java.lang.String.charAt(String.java:686)
at Hangman.isMatchingSecretWord(Hangman.java:49)
at Hangman.userInput(Hangman.java:34)
at Hangman.run(Hangman.java:20)*
for (int i = 0; i <= getSecretWord.length(); i++)
should be:
for (int i = 0; i < getSecretWord.length(); i++)
// ^^^
// see here
The valid indexes for an n-character string (or an n-element array) are 0 through n-1 inclusive.
So, if your secret word is xyyzy, the valid indexes are zero through four. Your original loop iterates with i set to zero through five, hence the problem.
But there seems to be a lot of unnecessary code in there, when you could get away with something simple.
First, I would remove a source of confusion - the function name sounds like the user input and the secret word have to match completely whereas your comment indicates otherwise:
Thanks, this works. But the reason for the loops is that the user enters one letter, I want to see if that letter is within the SecretWord. (it´s a hangman game).
In that case, you simply want to see if the single character exists in the secret word. I would change the function name to suit and, even then, it can be done with a lot less code:
private boolean isInSecretWord (String userInput) {
String secretWord = getSecretWord();
return secretWord.contains(userInput);
}
You were getting out of bounds error as your for loop wasn't looping correctly, I have modified it so that the loop doesn't go out of bounds and also your secretWord variable wasn't populating correctly, the code should now work as intended :)
private boolean isMatchingSecretWord(String userInput)
{
String secretWord = "";
String getSecretWord = getSecretWord();
for (int i = 0; i < getSecretWord.length();i++)
{
char chr = getSecretWord.charAt(i);
secretWord = secretWord + chr;
if (secretWord.equals(userInput))
{
println("is true");
return true;
}
}
return false;
}

Can't seem to clone char in a string

I have this assignment in school to check input string (through BufferedReader), if that string contains any vowels (like, in my language, a, ā, e, ē etc) and if they are there, you have to put character 'p' after that vowel and even after that 'p' char you have to put that vowel, after which that 'p' was inserted.
Sounds like this: dog => dopog; snails => snapaipils and so on.
The thing is - I made it working so that this char 'p' is in the right spot, but I can't put that vowel after char 'p'. For now I am getting like, dog => dopg.
In my code here:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Ld2151rdb255 {
static char[] patskani = { 'a', 'ā', 'e', 'ē', 'i', 'ī', 'u', 'ū', 'o' };
static char character;
static StringBuilder input;
public static void main(String[] args) {
char charAtPosition;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
String valueEntered = br.readLine();
valueEntered = valueEntered.toLowerCase();
input = new StringBuilder(valueEntered);
// should use "String.contain"
for (int i = 0; i < input.length(); i++) {
for (int j = 0; j < patskani.length; j++) {
charAtPosition = input.charAt(i);
if (charAtPosition == patskani[j]) {
input.insert(i + 1, 'p');
// input.insert(i + 2, charAtPosition);
}
}
}
} catch (IOException e) {
System.out.println("input-output error");
}
// Rezultātu izvade
String result = input.toString();
System.out.println(result);
}
}
I tried to put input.insert(i + 2, charAtPosition);, but yea - it smells like IndexOutOfBoundary exception. It really is, no matter, how I changed the index and what method I approached to do the task.
Don't worry much about object 'patskani'. Just a 'vowels' in my language.
Any help would be appreciated, because I am kinda stuck there and don't know if there's a way of doing it just by continuing or I have to rewrite the logic.
Thanks in advance!
I would suggest that you build the output step by step, that will be easier.
So get the char, add it to the output, check if it's a patskani and if so append a p:
input = new StringBuilder(); // should be named output most likely
for (int i = 0; i < valueEntered.length(); i++) {
// get the i-th char
charAtPosition = valueEntered.charAt(i);
// append this char to "output"
input.append(charAtPosition);
// check if the char is in "patskani"
for (int j = 0; j < patskani.length; j++) {
if (charAtPosition == patskani[j]) {
// if so, append a "p" and no need to continue checking
input.append('p');
break;
}
}
}
Something like that (demo here). As a side note, note that there is something called enhanced for loop that can be handy.

Replace characters from a string with it's position

I am having difficulty in the following, replacing certain characters from the string
There will be two inputs, first will be character and second will be string
then I need to replace all those characters from the string with it's position
for example ,
the input and output of my program are as follows which is absolutely correct as per the requirement
Input : i this is Ignite
( Here "i" is the first input and "this is Ignite" is the second input
Output : th2s 5s 8gn11te
Input : i this is ignite and i am pratik
Output : th2s 5s 8gn11te and 20 am prat30k
The replacement should not be case-sensitive.
I had written the following program but it's having some bugs, Bugs in the sense that I am actually doing some project online and the automated sytem is not accepting the program because of some logical error.The automated system does some test cases with different inputs and check the output ( not exceptions or invalid inputs) can someone help me identify it ?
import java.util.*;
import java.io.*;
class rplc
{
public static void main(String args[])
{
String str,temp="";
char ch, ch2;
int arr[]=new int[100];
int len,i,x=0;
Scanner input=new Scanner(System.in);
ch=input.next().charAt(0);
str=input.nextLine();
str=str.replaceAll("^\\s+","");
ch2=ch;
if(Character.isUpperCase(ch))
ch2=Character.toLowerCase(ch);
else if(Character.isLowerCase(ch))
ch2=Character.toUpperCase(ch);
len=str.length();
temp=str;
for(i=0;i<len;i++)
{
if(str.charAt(i)==(int)ch || str.charAt(i)==(int)ch2)
{
arr[x]=i;
x=x+1;
}
}
x=0;
for(i=0;i<len;i++)
{
if(str.charAt(i)==(int)ch || str.charAt(i)==(int)ch2)
{
temp=str.substring(0,i);
temp=temp+(arr[x]);
temp=temp+str.substring(i+1,len);
str=temp;
len=temp.length();
x=x+1;
}
}
System.out.print(temp);
}
}
Seems like your code should work. Just in case I tried writing a simpler program:
Scanner input=new Scanner(System.in);
char ch = Character.toLowerCase(input.next().charAt(0));
String str = input.nextLine().trim().toLowerCase();
input.close();
StringBuffer buf = new StringBuffer();
for (int i = 0; i < str .length(); i++) {
if (str.charAt(i) == ch) {
buf.append(i);
}
else {
buf.append(str.charAt(i));
}
}
System.out.println(buf.toString());
And the output seems to be same.
Perhaps your function should return the value instead of printing it?
From the comments I understand that there will be only 1 input from the user.
The following input:
i this is ignite and i am pratik
Where the first 'i' is the charcter which needs to be replaced in 'this is ignite and i am pratik'.
Modify following:
str=input.nextLine();
str=str.replaceAll("^\\s+","");
to
str = input.nextLine();
str = str.substring(1);
str = str.replaceAll("^\\s+", "");
Try Something like this,
Scanner s = new Scanner(System.in);
String Line = s.nextLine();
String ch = Line.substring(0,Line.indexOf(" ")).trim();
Line = Line.substring(Line.indexOf(" ")).trim();
String[] x= Line.split(ch);
String y="";
for(String t:x){
y=y.equals("")?t:y+y.length()+t;
}
System.out.println(y);
I did some code cleaning but the most important steps were to use a list of dynamic size instead of a fixed size array and a while-loop with dynamic termination instead of a for-loop. This is because the length of the output String will change (increase) when there a characters to be replaced at positions >9 and thus in your code the execution can stop in the middle of the result string and there are characters not being replaced.
There is even a special case, when the replaced character is a number itself. To avoid problems there I added this line
i = i + Integer.toString(list.get(pos)).length()-1;
in order to step over newly added number characters in the output String.
import java.util.*;
import java.io.*;
class rplc
{
public static void main(String args[])
{
List<Integer> list = new ArrayList<Integer>();
Scanner input=new Scanner(System.in);
char ch = input.next().charAt(0);
String str=input.nextLine().trim();
int len=str.length();
for(int i=0;i<len;i++)
{
if(str.charAt(i)==Character.toLowerCase(ch) || str.charAt(i)==Character.toUpperCase(ch))
{
list.add(i);
}
}
int pos = 0;
int i = 0;
while(i<str.length())
{
if(str.charAt(i)==Character.toLowerCase(ch) || str.charAt(i)==Character.toUpperCase(ch))
{
String start = str.substring(0,i)+Integer.toString(list.get(pos));
String end = i<=str.length() ? str.substring(i+1) : "";
i = i + Integer.toString(list.get(pos)).length()-1;
pos++;
str = start.concat(end);
}
i++;
}
System.out.print(str);
}
}
I can't see any special bugs. Could be that I lost sight of something. This is my first answer here and English is not my mother tongue, so please excuse any formal errors.
I liked the problem so I made my own answer. apologies for the dirty looking code. :)
Scanner input=new Scanner(System.in);
String firstInput=input.nextLine().charAt(0) + "";
//ensure its lower case
firstInput=firstInput.toLowerCase();
String secondInput=input.nextLine();
//ensure char in secondInput is lower cased too.
secondInput=secondInput.replaceAll(firstInput.toUpperCase(),firstInput);
String[] splitted=secondInput.split(firstInput);
String output="";
int current=0;
for(int i=0;i<splitted.length;i++){
String s=splitted[i];
current=current+ s.length();
if(i==splitted.length-1){
output=output+s;
}else{
output=output+s;
output=output+ current;
current++;
}
}
//edited part, as split doesn't split if firstinput is the last character of the string
if(secondInput.endsWith(firstInput)){
output=output+secondInput.length();
}
System.out.println(output);

What's wrong with my if-else statement?

I made this simple GUI program that counts the vowels and consonants of a particular sequence of characters. The counter is okay, but I'm having a problem with the if-else statement where I had to display a message when that character is neither a vowel nor consonant... Here's the code:
//I initialized these variables:
public static int vowels = 0, consonants = 0, charac = 0;
public static String outputStr;
public static String conso = "bcdfghjklmnpqrstvwxyz";
public static String vow = "aeiou";
//Here's the code for my "count" button
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
String userInput = jTextField1.getText();
userInput = userInput.toUpperCase();
conso = conso.toUpperCase();
vow = vow.toUpperCase();
String wordInput[] = userInput.split("");
vowels = 0;
consonants = 0;
charac = 0;
for(int i=0; i<wordInput.length; i++) {
for(int j=0; j<5; j++) {
char v = vow.charAt(j);
String VL = Character.toString(v);
if(VL.equals(wordInput[i])) {
vowels ++;
charac = 0;}
else {
charac += 1; }
}
for(int h=0; h<21; h++) {
char c = conso.charAt(h);
String CL = Character.toString(c);
if(CL.equals(wordInput[i])) {
consonants ++;
charac = 0; }
else {
charac += 1; }
}
}
String totalVow = Integer.toString(vowels);
String totalCons = Integer.toString(consonants);
jLabel5.setText(totalVow);
jLabel6.setText(totalCons);
//here's the if-else statement:
if (charac == 0) {
jLabel7.setText(" ");
}
else if (charac >= 1) {
jLabel7.setText("The sequence contains invalid characters.");
}
if (userInput.isEmpty()) {
jLabel7.setText("No input.");
}
}
Here's what it looks like:
I entered a "sequence" of characters that does not have any special characters or digits. But it still displays the message wherein it has other characters other than the vowels and consonants. Is there something wrong with the if-else statement? Thanks for the help :)
The problem is in the inner for loop. Every character is tested with each of 5 different vowels, so surely it will fail to match at least 4 of them, and charac will be incremented
for(int j=0; j<5; j++) {
char v = vow.charAt(j);
String VL = Character.toString(v);
if(VL.equals(wordInput[i])) {
vowels ++;
charac = 0;}
else {
charac += 1;
}
}
Instead, you can use the String.contains() method in place of the inner loop.
You put irrelevant code in your loop. Your loop should like:
for(int i=0; i<wordInput.length; i++) {
char ch=wordInput.charAt(i);
if(Character.isLetter(ch)){
if(isVowel(ch)){// make a method which return true if char is vowel.
vowel++;
}
else{
consonent++;
}
}
}
Your logic for counting invalid characters if wrong. What you do is: you increase the counter each time the character is not the character you just tested, that is, for each character in your input, the charac variable is increased 25 times! But then, the next time the character matches the currently tested vowel or consonant, you reset the charac variable to 0!
Instead of using two for loops to check for each of your vowels and consonants individually, you can use builtin String methods to check whether the current character is one of the vowels or consonants, e.g., indexOf. This way, the checks are reduced to a single if-statement each, making it much easier to have the "else" case for when it's neither a vowel nor a consonant.
for (int i = 0; i < userInput.length(); i++) {
char c = userInput.charAt(i);
if (vow.indexOf(c) != -1) {
vowels++;
} else if (conso.indexOf(c) != -1) {
consonants++;
} else {
charac++; // invalid character
}
}
Also, note that instead of splitting the string to an array of strings you can also use the charAt method.
You're adding to charac in both loops: one that looks up the consonants and the one that looks up the vowels. You'd want to use an if/else-if/else here, where only if a character is not a consonant or a vowel you add to charac.
Also, take a look Guava utilities. For instance, this is how you get all vowels and all consonants:
String vowels = "aeiou";
String consonants = "bcdfghjklmnpqrstvwxz";
String input = "mary had a little lamb";
String allVowels = CharMatcher.anyOf(vowels).retainFrom(input);
String allConsonants = CharMatcher.anyOf(consonants).retainFrom(input);

Categories

Resources