ArrayIndexOutOfBoundsException on a Split String in a array - java

So I am doing some problems on the UVa online problem judge, but on a relativity easy problem, I keep on getting a ArrayIndexOutOfBoundsException. To understand the code, here is the problem.
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
int sum = 0;
for (int i = 0; i <= t; i++){
String d = scan.nextLine();
if (d.equals("report")) {
System.out.println(sum);
} else {
String[] parts = d.split(" ");
int z = Integer.parseInt(parts[1]);
sum+=z;
}
}
}
}
The error message is:
reportException in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at Main.main(Main.java:16)
And I am using the sample input given.
Edit:
I have already tried added println statements in the code and figured out that the number is not being read. I am trying to understand why.

OK, after some messing around on my machine I think I found what might be at least part of the problem. The issue is that I'm not sure what the precise input is, so I'm going off of what I could get working on my machine.
So you start up your program, and it waits for a prompt at this line:
int t = scan.nextInt();
You enter your integer, and the program moves on as expected:
Input: 100 // Then press enter to continue
The input is parsed, and now t is set to 100.
Then when your program enters your for loop, it comes across this line:
String d = scan.nextLine();
Yet for some reason the program doesn't wait for input! (Or at least it didn't on my machine)
I believe the issue lies here:
Input: 100 // Then press enter to continue
^^^^^^^^^^^
What I think is happening is that your input is really
Input: 100\n
^^
That character (\r\n on Windows) is what's input when you hit enter. It's a newline character that tells the console to go to the next line.
So as a result, what I think happens is this:
Input: 100\n
Scanner parses 100, leaving the \n in the input stream
Then at the nextLine() call, the scanner sees \n on the input stream, which denotes end of line, so it thinks you already input the entire line! Because what it thought was your input was only the newline character, it returns an empty string, because your "input" was an empty string and the newline character. Your program then goes to split the newline character by spaces, rightly returns an array with a single element, and then your program promptly crashes when accessing an out-of-bounds index.
What might work better is reading an entire line first and parsing the integer so your scanner doesn't get ahead of itself, like this:
int t = Integer.parseInt(scan.nextLine());
Just as a warning: This is what I've been able to come up with based on using OP's code as-is on my machine. I was unable to get a situation where the only element in parts was "donate". I will update further as I get more info.

The error message means the array parts's length less than 2, sometimes.
It means the variable d does not always contain the string BLANK SPACE, " ", what you split by.
try this code:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int t = scan.nextInt();
int sum = 0;
for (int i = 0; i <= t; i++){
String d = scan.nextLine();
if (d.equals("report")) {
System.out.println(sum);
} else {
String[] parts = d.split(" ");
/*
* Add IF statement,
*/
if (parts.length() > 1) {
int z = Integer.parseInt(parts[1]);
sum+=z;
}
}
}
}
}

Related

I have specified the size of the array using user input but my for loop is taking input only size-1 time

I have specified the size of the array using user input but my for loop is taking input only size-1 time.
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int time=sc.nextInt();
String input[]=new String[time];
for(int i=0;i<time;i++)
{
input[i]=sc.nextLine();
}
for(int i=0;i<time;i++)
{
int len=input[i].length();
if(len>4)
{
System.out.println(input[i].charAt(0)+ Integer.toString(len-2)+input[i].charAt(len-1));
}
else
System.out.println(input[i]);
}
}
}
i changed my code and it is working fine
changed
int time=sc.nextInt();
with
int time=Integer.parseInt(sc.nextLine());
but i don't know the reason behind this . Please can anyone explain me
The Scanner.nextInt() method scans the next token of the input as an int, not the line. For example, if you give an int input and then hit enter, then it takes only the int, not the carriage return.
If you give a sample input like this:
2 xyz //hit enter and give the next input
abc
You'll see the nextInt() will take the 2 as input from that line and the upcoming first iteration for Scanner.nextLine() will consider the xyz as first input and in the next iteration, as we gave abc, it will be considered as the second. All these time you're code was working, but you couldn't see as it was taking the empty string as the first input due to the carriage return from the previous line.
However, The Scanner.nextLine() takes the whole line as input, along with the carriage return and then parses the int to the integer, so, you get the next lines for the string input for your array.
Hope that makes everything clear.
The problem is with the nextLine() method used in the first for loop. Because the method advances the scanner to the next line and returns the input that was skipped, it kind of "eats" one of your loop iterations and it ends up allowing you to input time - 1 elements into the array instead of time amount of elements. If you just use sc.next() instead, the program works perfectly fine, so you don't need to use
int time=Integer.parseInt(sc.nextLine());
as it may be a bit more complicated (in my opinion) than just replacing nextLine() with next(). Here is the code:
import java.util.*;
public class Main{
public static void main(String args[]){
Scanner sc = new Scanner(System.in);
int time = sc.nextInt();
String input[] = new String[time];
for(int i = 0;i < time;i++)
{
input[i] = sc.next();
}
for(int i = 0;i < time;i++)
{
int len = input[i].length();
if(len > 4)
{
System.out.println(input[i].charAt(0) + Integer.toString(len - 2) + input[i].charAt(len - 1));
}
else
System.out.println(input[i]);
}
sc.close();
}
}

Java Strange String Spacing Issue

I am creating a java program that uses a cipher to encode any message the user types in. It works flawlessly with single words like "hello" and "testing", but begins to fall apart when you add spaces, like the message "hello world." Here is the code:
import java.util.Scanner;
import java.util.ArrayList;
public class Code {
public static void main(String[] args) {
Scanner shiftValue = new Scanner(System.in);
System.out.print("Please enter shift value: ");
int shift = shiftValue.nextInt();
String alphabet = "abcdefghijklmnopqrstuvwxyz";
Scanner input = new Scanner(System.in);
String codeInput = "anything";
int index = 0;
while(!codeInput.equals("end")) {
System.out.println();
System.out.println("Please enter message: ");
codeInput = input.next();
for(int i = 0; i < codeInput.length(); i++){
if(Character.isWhitespace(codeInput.charAt(i))){
System.out.print(" ");
}
else {
while(alphabet.charAt(index) != codeInput.charAt(i)){
index++;
}
if(index > 25 - shift){
index = index - (26 - shift);
System.out.print(alphabet.charAt(index));
}
else {
System.out.print(alphabet.charAt(index + shift));
}
}
index = 0;
}
}
} //method
} //class
When I type start the program, it asks for a shift value, which decides how many letters to shift the cipher. After that, it goes into a while loop, forever asking the user for input, then outputting an encoded version of the input, until the word "end" is typed. In the eclipse console, it looks like this:
Please enter shift value: 3
Please enter message:
hello
khoor
Please enter message:
testing
whvwlqj
Please enter message:
However, when I type multiple words with spaces between them, it looks like this:
Please enter shift value: 3
Please enter message:
hello world
khoor
Please enter message:
zruog
Please enter message:
For some reason, instead of displaying both words in the same sentence format as the input, it encodes the first word, then goes through the entire while loop again before encoding the second word.
I have no idea why this happens, so I would appreciate any help or advice you guys could give me.
Thank you for reading my post, and have a wonderful day.
The Scanner splits the input for you already and by default by whitespaces.
JavaDoc:
A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace.

Why is my message printing twice when I break out of the inner if?

I am having a little problem with my code. Compiling and running works well, however, when I attempt to break out of the inner loop,
System.out.println("Type which category you want to add to.");
System.out.println("Homework, Classwork, Labs, Test, Quizzes, Midterm, Final");
The code above is printing twice to the terminal when I only want it to print once.
I have a feeling that is a simple mistake with the way my brackets are aligned but I am having difficulty with figuring out how to do it. Any help would be greatly appreciated!
import java.util.Scanner;
public class GetGrade {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
final int MAX = 15;
int[] homework = new int[MAX];
int[] classwork = new int[MAX];
int[] lab = new int[MAX];
int[] test = new int[MAX];
int[] quizzes = new int[MAX];
int[] midterm = new int[MAX];
int[] fin = new int[MAX];
int hwCount, clCount, labCount, testCount, quizCount, midCount, finCount;
double hwTotal, clTotal, labTotal, testTotal, quizTotal, midTotal, finTotal;
double grade = 0;
String selection = "";
System.out.println();
System.out.println("Welcome to GetGrade!");
System.out.println();
while (true) {
System.out.println("Type which category you want to add to.");
System.out.println("Homework, Classwork, Labs, Test, Quizzes, Midterm, Final");
selection = input.nextLine();
if (selection.equals("homework")) {
System.out.print("What percentange of your grade is homework? > ");
double hwPercent = input.nextDouble();
System.out.println("Now begin typing your grades. When you are finished, type -1.");
for (int i = 0; i < homework.length; i++) {
homework[i] = input.nextInt();
hwTotal = homework[i] * hwPercent;
grade += hwTotal;
if (homework[i] == -1) break;
}
}
}
}
}
It's just as trivial as it seems:
The call to input.nextInt(); in your inner loop does not include the newline.
So you are breaking of the innerloop, receiving the next line which only contains the newline - character in input.nextLine(); which is the remaining input of your "-1\n" line and proceed with the main loop again as it does not match "homework".
Try setting the conditional variable in your while loop to an actual boolean rather than true.
Also, when you invoke "break", you are only breaking out of the for loop. If you reassign a boolean variable to false at this point, you would exit the while loop completely.
Just before while loop ends, add a "Do you want to continue? (Y/N)" functionality.
If user enters "N" or anything else, execute another break. And that break will make you get out of the while loop.
The simple way to get your code working is to change
selection = input.nextLine();
to
selection = input.next();
next() only reads in a string value (which is what you are actually doing in your code) instead of the newline character as Peter has suggested.
So the an extra iteration of the while does not take place when you read the newline character.
When you use a scanner to read a line from the keyboard, it reads everything up to and including the newline character the user types to submit their input. So for example:
Type which category you want to add to.
Homework, Classwork, Labs, Test, Quizzes, Midterm, Final
>
If you type "homework" and then ENTER, the actual input becomes "homework\n". input.nextLine() will scan the input until it encounters the first newline character, '\n', which it will consume and then it returns everything up to that point (i.e. "homework").
Your problem here is that input.nextInt() does NOT consume a newline character, and so there is still a newline character in the input buffer by the time your while loop starts another round.
Now begin typing your grades. When you are finished, type -1.
> ...
> -1
=> User input is "-1\n"
-------------------------------
// Meanwhile, back in the code...
for (int i=0;i<homework.length;i++) {
homework[i] = input.nextInt(); // <--- This call consumes "-1" but leaves '\n'
hwTotal = homework[i] * hwPercent;
grade += hwTotal;
if (homework[i] == -1) break;
}
That newline is consumed by the next call to input.nextLine(), leaving the input buffer empty.
while (true) {
System.out.println("Type which category you want to add to.");
System.out.println("Homework, Classwork, Labs, Test, Quizzes, Midterm, Final");
selection = input.nextLine(); // <--- This call consumes the leftover '\n' and returns the empty string
...
And because "" is not equal to "homework", the while loop goes around one more time, but this time the input buffer is empty, and so the call to input.nextLine() behaves as you would expect.
// selection is empty, so this condition fails and the program loops back around
if (selection.equals("homework")) {
...
There are two easy solutions to this problem. You can
Use Integer.parseInt(input.nextLine()) instead of input.nextInt()
Add an extra call to input.nextLine() at the end of your while loop to consume the final newline character
The first option is probably the most robust, and you get the added benefit of a run-time error being thrown if they do not give you a valid integer as input.

Space Replacement for Float/Int/Double

I am working on a class assignment this morning and I want to try and solve a problem I have noticed in all of my team mates programs so far; the fact that spaces in an int/float/double cause Java to freak out.
To solve this issue I had a very crazy idea but it does work under certain circumstances. However the problem is that is does not always work and I cannot figure out why. Here is my "main" method:
import java.util.Scanner; //needed for scanner class
public class Test2
{
public static void main(String[] args)
{
BugChecking bc = new BugChecking();
String i;
double i2 = 0;
Scanner in = new Scanner(System.in);
System.out.println("Please enter a positive integer");
while (i2 <= 0.0)
{
i = in.nextLine();
i = bc.deleteSpaces(i);
//cast back to float
i2 = Double.parseDouble(i);
if (i2 <= 0.0)
{
System.out.println("Please enter a number greater than 0.");
}
}
in.close();
System.out.println(i2);
}
}
So here is the class, note that I am working with floats but I made it so that it can be used for any type so long as it can be cast to a string:
public class BugChecking
{
BugChecking()
{
}
public String deleteSpaces(String s)
{
//convert string into a char array
char[] cArray = s.toCharArray();
//now use for loop to find and remove spaces
for (i3 = 0; i3 < cArray.length; i3++)
{
if ((Character.isWhitespace(cArray[i3])) && (i3 != cArray.length)) //If current element contains a space remove it via overwrite
{
for (i4 = i3; i4 < cArray.length-1;i4++)
{
//move array elements over by one element
storage1 = cArray[i4+1];
cArray[i4] = storage1;
}
}
}
s = new String(cArray);
return s;
}
int i3; //for iteration
int i4; //for iteration
char storage1; //for storage
}
Now, the goal is to remove spaces from the array in order to fix the problem stated at the beginning of the post and from what I can tell this code should achieve that and it does, but only when the first character of an input is the space.
For example, if I input " 2.0332" the output is "2.0332".
However if I input "2.03 445 " the output is "2.03" and the rest gets lost somewhere.
This second example is what I am trying to figure out how to fix.
EDIT:
David's suggestion below was able to fix the problem. Bypassed sending an int. Send it directly as a string then convert (I always heard this described as casting) to desired variable type. Corrected code put in place above in the Main method.
A little side note, if you plan on using this even though replace is much easier, be sure to add an && check to the if statement in deleteSpaces to make sure that the if statement only executes if you are not on the final array element of cArray. If you pass the last element value via i3 to the next for loop which sets i4 to the value of i3 it will trigger an OutOfBounds error I think since it will only check up to the last element - 1.
If you'd like to get rid of all white spaces inbetween a String use replaceAll(String regex,String replacement) or replace(char oldChar, char newChar):
String sBefore = "2.03 445 ";
String sAfter = sBefore.replaceAll("\\s+", "");//replace white space and tabs
//String sAfter = sBefore.replace(' ', '');//replace white space only
double i = 0;
try {
i = Double.parseDouble(sAfter);//parse to integer
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
System.out.println(i);//2.03445
UPDATE:
Looking at your code snippet the problem might be that you read it directly as a float/int/double (thus entering a whitespace stops the nextFloat()) rather read the input as a String using nextLine(), delete the white spaces then attempt to convert it to the appropriate format.
This seems to work fine for me:
public static void main(String[] args) {
//bugChecking bc = new bugChecking();
float i = 0.0f;
String tmp = "";
Scanner in = new Scanner(System.in);
System.out.println("Please enter a positive integer");
while (true) {
tmp = in.nextLine();//read line
tmp = tmp.replaceAll("\\s+", "");//get rid of spaces
if (tmp.isEmpty()) {//wrong input
System.err.println("Please enter a number greater than 0.");
} else {//correct input
try{//attempt to convert sring to float
i = new Float(tmp);
}catch(NumberFormatException nfe) {
System.err.println(nfe.getMessage());
}
System.out.println(i);
break;//got correct input halt loop
}
}
in.close();
}
EDIT:
as a side note please start all class names with a capital letter i.e bugChecking class should be BugChecking the same applies for test2 class it should be Test2
String objects have methods on them that allow you to do this kind of thing. The one you want in particular is String.replace. This pretty much does what you're trying to do for you.
String input = " 2.03 445 ";
input = input.replace(" ", ""); // "2.03445"
You could also use regular expressions to replace more than just spaces. For example, to get rid of everything that isn't a digit or a period:
String input = "123,232 . 03 445 ";
input = input.replaceAll("[^\\d.]", ""); // "123232.03445"
This will replace any non-digit, non-period character so that you're left with only those characters in the input. See the javadocs for Pattern to learn a bit about regular expressions, or search for one of the many tutorials available online.
Edit: One other remark, String.trim will remove all whitespace from the beginning and end of your string to turn " 2.0332" into "2.0332":
String input = " 2.0332 ";
input = input.trim(); // "2.0332"
Edit 2: With your update, I see the problem now. Scanner.nextFloat is what's breaking on the space. If you change your code to use Scanner.nextLine like so:
while (i <= 0) {
String input = in.nextLine();
input = input.replaceAll("[^\\d.]", "");
float i = Float.parseFloat(input);
if (i <= 0.0f) {
System.out.println("Please enter a number greater than 0.");
}
System.out.println(i);
}
That code will properly accept you entering things like "123,232 . 03 445". Use any of the solutions in place of my replaceAll and it will work.
Scanner.nextFloat will split your input automatically based on whitespace. Scanner can take a delimiter when you construct it (for example, new Scanner(System.in, ",./ ") will delimit on ,, ., /, and )" The default constructor, new Scanner(System.in), automatically delimits based on whitespace.
I guess you're using the first argument from you main method. If you main method looks somehow like this:
public static void main(String[] args){
System.out.println(deleteSpaces(args[0]);
}
Your problem is, that spaces separate the arguments that get handed to your main method. So running you class like this:
java MyNumberConverter 22.2 33
The first argument arg[0] is "22.2" and the second arg[1] "33"
But like other have suggested, String.replace is a better way of doing this anyway.

why's this program giving a runtime error on jcreator but not on netbeans?

This is my solution for sphere's online judge palin problem. It runs fine on Netbeans, but the judge is rejecting my answer saying it gives a RuntimeError. I tried it on JCreator and it says:
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:468)
at java.lang.Integer.parseInt(Integer.java:497)
at Main.main(Main.java:73)
I'm not passing an empty string for it to parse, why is this?
The code:
import java.io.*;
import java.util.*;
class Main {
public static int firstPalinLargerThanNum(int num){
int foundPalin =0;
int evalThisNum = ++num;
while (true){
if (isPalin(evalThisNum))
break;
evalThisNum++;
}
foundPalin = evalThisNum;
return foundPalin;
}
public static boolean isPalin(int evalThisNum){
boolean isItPalin = false;
int dig=0;
int rev=0;
int n = evalThisNum;
while (evalThisNum > 0)
{
dig = evalThisNum % 10;
rev = rev * 10 + dig;
evalThisNum = evalThisNum / 10;
}
if (n == rev) {
isItPalin=true;
}
return isItPalin;
}
public static void main(String args[]) throws java.lang.Exception{
BufferedReader r1 = new BufferedReader(new InputStreamReader(System.in));
/*BufferedReader r1 = new BufferedReader (new FileReader(new File ("C:\\Documents and Settings\\Administrator\\My Documents\\NetBeansProjects\\Sphere\\src\\sphere\\sphere\\PALIN_INPUT.txt")));*/
String read = r1.readLine();
int numberOfTestCases = Integer.parseInt(read);
for (int i=0; i<numberOfTestCases;i++){
read = r1.readLine();
if (read!=null){
int num = Integer.parseInt(read);
System.out.println(firstPalinLargerThanNum(num));
}
}
}
}
Input:
2
808
2133
line 73 is: int num = Integer.parseInt(read);
You will get that error if you hit <Enter> when the program is expecting a number.
Suppose your input is
2
3
<Enter>
You will receive the error you have indicated after processing the number 3, as you have told your routine to iterate twice.
As an aside, on top of error handling around the number parsing, you might also want to introduce a trim() to the readLine() method calls:
String read = r1.readLine().trim();
This will allow you to handle gracefully the input in the event that the user to put in whitespace around the numbers.
Just a wild guess: Could there be a problem with different end-of-line separators.
E.g. your program actually gets 2<CR><LF>808<CR><LF>2133<CR><LF>, thinks that the line ends at the <CR> and processes the line.
Now when it tries to process the next line it finds <LF> which makes it think it read an empty String.
You cannot assume that the user knows how to use your program and will give you correct input. The judge probably hit enter, without typing any number. How is he/she supposed to know the input that your program requires? A program should fail gracefully, not blow up in the user's face with cryptic errors.
You should be doing something like the following, so that the user knows what to do:
private static function readInt(BufferedReader reader) throws IOException
{
boolean done = false;
int result = -1;
while ( ! done ){
System.out.print("Please enter an integer: ");
String str = reader.readLine();
try{
result = Integer.parseInt(str);
done = true;
}catch(NumberFormatException cantconvert){
System.out.println("That isn't an integer. Try again.");
}
}
return result;
}
Additionally, you shouldn't use an exception specifier with the main function (that is, don't use "throws" in the signature of "main"). You should handle those IOExceptions and print a pretty and intelligible message to the user, even if there is nothing you can do about the exception to fix it or make it go away.
I just ran your example code under Eclipse 3.4 without error. I was only able to induce a similar error when I did not provide the specified number of test cases, i.e.:
6
56
87
[Enter]
So I am inclined to agree with akf that there must be an extra Enter happening somewhere, because this error will only be generated when there are insufficient lines of input.

Categories

Resources