Hi I wanted to know how to write up a try and catch block to stop from getting the below error.
java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
I have this method which takes a sentence and splits it into an ArrayList. I then use that to store values into a hashmap, where index 1 is the key and the words after become the value. I use the below method to split the user input into an array.
private Scanner reader;
/**
* Create a new InputReader that reads text from the text terminal.
*/
public InputReader()
{
reader = new Scanner(System.in);
}
public ArrayList<String> getInput()
{
System.out.print("> "); // print prompt
String inputLine = reader.nextLine().trim().toLowerCase();
String[] wordArray = inputLine.split(" "); // split at spaces
// add words from array into ArrayList
ArrayList<String> words = new ArrayList<String>();
for(String word : wordArray) {
words.add(word);
}
return words;
}
}
and the below method uses the class above to detect user input. So when the user types in write they can write into a hashmap but if they press return before they type in a key and value I get the out of bounds exception. So How can i rewrite the below method to avoid this?
public void start()
{
boolean finished = false;
printWelcome();
while(!finished) {
ArrayList<String> input = reader.getInput();
if(input.contains("shutdown")) {
finished = true;
}
if (input.contains("load")) {
System.out.println();
instruct.readAndFill();
System.out.println();
}
if (input.contains("write")) {
String key = input.get(1);
String value = "";
for(int i=2; i<input.size(); i++) {
value = value + " " + input.get(i);
}
instruct.mapWrite(key, value);
}
}
instructorGoodBye();
}
Sorry if i wasn't clear enough, or if my code is not up to scratch i have only been learning java for about 2 months now.
basically if the user types in write key value on one line it is fine but if they hit return after write then the error happens.
So, fundamentally what you are missing is error checking. Your program is taking input from a user, and assuming it is valid. This is always a bad idea.
Instead, you should validate what you get from the user. One way you can do this, for your "write" block, is to make sure the elements you expect to be there, are actually there.
To start, I would rewrite your loop as follows:
while(!finished) {
List<String> input = reader.getInput();
if(input.size() == 0) {
throw new IllegalArgumentException("Must specify command, one of 'shutdown', 'load', 'write'");
}
final String command = input.remove(0).toLowerCase();
// TODO: Make sure command is one of the valid commands!
Note the changes:
Assigning to List instead of ArrayList is just a good general practice.
Checking the input to make sure it has more than zero elements
Taking the first element, since we don't want to have to do List.contains(). Consider the input garbage garbage garbage write, clearly we don't want this to invoke the "write" command, it should be considered invalid input.
Finally, we use this to rewrite the conditions on executing our commands:
if(command.equals("write")) {
// Make sure the user put the right stuff in here
// Since we removed the command from the input already, just make sure what is left is
if(input.size() <= 1) {
throw new IllegalArgumentException("Must specify correct data");
}
String key = input.remove(0);
String value = String.join(" ", input); // Java 8
instruct.mapWrite(key, value);
}
You are getting the error for below part of the code..
if (input.contains("write")) {
String key = input.get(1);// here is the problem..
String value = "";
for(int i=2; i<input.size(); i++) {
value = value + " " + input.get(i);
}
instruct.mapWrite(key, value);
}
in the line 2 of this code snippet. you are accessing a value by using the index. Now just imagine you just enter a single word in the console. so the arraylist you will get from the getInput() method will have the size of 1. So.. in the arraylist the word will be placed on 0th position.(that is the first position) but you are accessing the value on second position.. Thats gives you a index out of bond exception..
basically the fix was simpler than throwing a new exception and using a try and catch block. All I had to do was slightly change the logic and just use and if else statement.
if (input.contains("write")) {
if(input.size() >=2) {
String key = input.get(1);
String value = "";
for(int i=2; i<input.size(); i++) {
value = value + " " + input.get(i);
}
mapWrite(key, value);
} else {
System.out.println("Please type in the key & value after write all on line");
}
}
From what I have learned from java so far, is that the best solutions are normally always normally the simplest. Thanks for all the help, everyone who commented and tried to help me basically helped me come up with the idea.
Related
I am writing a program in java that will generate a set of random characters using numbers and letters, output them one by one, clearing the console after each character, append the character to a string, and ask the user to repeat the sequence.
My problem here is that if the program says, 'a' and asks for input, even if 'a' is entered, it returns incorrect. Here is the code of the generating and testing of the strings:
public void generateSeq() {
try {
Random rand = new Random();
for (int i = 0; i < numChars; i++) {
Robot bot = new Robot();
c = characters.charAt(rand.nextInt(characters.length()));
System.out.print(c);
Thread.sleep(1000);
bot.keyPress(KeyEvent.VK_CONTROL);
bot.keyPress(KeyEvent.VK_L);
bot.keyRelease(KeyEvent.VK_CONTROL);
bot.keyRelease(KeyEvent.VK_L);
full = full + String.valueOf(c);
}
} catch (InterruptedException e) {
System.out.print("Error 1. Email me # xxx#gmail.com.");
} catch (AWTException e) {
System.out.print("Error 2. Email me # xxx#gmail.com.");
}
testSeq();
}
And here is the testing method:
public void testSeq() {
Scanner sc = new Scanner(System.in);
System.out.print("Your attempt: ");
user = sc.nextLine();
if (user == null ? full == null : user.equals(full)) {
System.out.println("Correct! Trying next combo....");
numChars++;
generateSeq();
} else {
System.out.println("Incorrect! Restarting game...");
start();
}
}
In the beginning, when full is null, you attempt to add the first character to it. But this is String Conversion, which converts a null to the String "null", and your full variable now starts with "null".
Initialize it to the empty string ("") first, at the top of generateSeq.
There is nothing wrong with your use of the ternary operator, but now the strings won't be null; they would be empty at worst. Calling equals by itself is now sufficient.
if (user.equals(full))
In addition, you may want to generate your Random object once, as an instance variable, instead of creating a new Random object every time you call generateSeq.
The code appears to be fine and it works.
Do you print what contains user and full when you compare it?
if (user == null ? full == null : user.equals(full)) {
System.out.println("Correct! Trying next combo....");
numChars++;
generateSeq();
} else {
System.out.println("--user:" + user);
System.out.println("--full:" + full);
System.out.println("Incorrect! Restarting game...");
}
Language: Java.
Aim:
Boolean Array gridA[] should become true on whatever index is read from input (i.e. if input is "init_start 2 4 5 init_end" then gridA[] indexes 2,4 and 5 should become true). That much I managed to get working but I have two problems:
input:
init_start int int int int int (...) int init_end
for example: init_start 2 6 12 init_end
Problems:
any integer from input that exceeds the value of (instance variable) int L (which determines the index-length of the array) should be ignored, to prevent integers from outside the domain of Array gridA[] from having influence.
Using if(scanner.nextInt != L){} didn't seem to work.
I also need this method, or the body of the method to start when input begins with "init_start" and stop when input ends with "init_end".
How do write code so that it can read both String and integers from the same input?
I meant to do this using
if(scanner.Next=="init_start") followed by
a = scanner.NextInt; which, as I suspected, didn't work.
Attempts at solving:
After googling I tried putting String initialInputStart in a Scanner:
localScanner(initialInputStart);
but I failed to get that working. Other information I found suggested I'd close and reopen the scanner but I need the information to be read from a single line of input so I doubt that will help.
code:
java.util.Arrays.fill(gridA,false);
java.util.Arrays.fill(gridB,false);
String initialInput;
String initialInputStart;
int a;
int i;//only for testing
i = 0;//only for testing
System.out.println("type integers"); //only for testing
while( scanner.hasNextInt() && i<5){ //I can't find a way to make loop stop without missing input so I'm using i temporarily
a = scanner.nextInt();
gridA[a] = true;
System.out.print(a);
System.out.print(gridA[a]+" ");
i++;
}//end while
I wrote a little program which pretty much does what you described as your aim; I read line by line and split each into tokens I further process. The tokens describe what the data means/what state we are in. The actual data is parsed in the default: case in the switch(token) block and branches in behaviour from state to state (which is merely visible here as we only have two states: "init" and "not init", beside the keywords):
public static void main(String[] args) {
int L = 13; // not sure if this is needed
boolean[] gridA = new boolean[L];
Reader source;
/**
* from file:
* source = new FileReader("grid.csv");
*/
/**
* from classpath resource:
* source = new InputStreamReader(MyClass.class.getResourceAsStream("grid.csv"));
*/
/**
* from string:
* source = new StringReader("init_start 2 6 12 init_end");
*/
/**
* from std-in:
* source = new InputStreamReader(System.in);
*/
try(BufferedReader stream = new BufferedReader(source)) {
boolean init = false;
// loop
input_loop:
while(true) {
// read next line
String line = stream.readLine();
if(line == null) {
// end of stream reached
break;
}
if(line.trim().isEmpty()) {
// ignore empty lines
continue;
}
String[] tokens = line.split(" ");
for (String token : tokens) {
switch (token) {
// evaluate keywords
case "init_start":
init = true;
break;
case "init_end":
init = false;
break;
// for input from console
case "exit":
break input_loop;
default:
// parse input, based on state (expand "init" to an enum for more states)
if(init) {
// read init input
int index = Integer.parseInt(token);
if(index >= 0 && index < gridA.length) {
gridA[index] = true;
} else {
throw new RuntimeException("illegal grid index: " + index);
}
} else {
// read undefined input
throw new RuntimeException("unrecognized token: " + token);
}
break;
}
}
}
} catch(IOException ex) {
throw new RuntimeException("an i/o exception has occurred", ex);
}
System.out.println(Arrays.toString(gridA));
}
" How do write code so that it can read both String and integers from the same input?"
do you want to have an Input like this: "123, foo"
if thats the case use:
String input = scanner.nextLine();
String[] parts = input.split(",");//" " to split it at an empty space
String part1 = parts[0]; // 123
int Number = Integer.parseInt(part1) // you could inline it, but i chose this version for better refference
String part2 = parts[1]; //foo
if your Input looks like this "123 or foo"
you have to read the input as String and check the String afterwards if its a Number:
String input = scanner.nextLine();
if (text.contains("[a-zA-Z]+") == false){ //looks if the input does NOT contain any characters
int nummber = Integer.parseInt(input);
} else{
String text = input;
}
afterward you can compare your text:
For the first mentioned case:
if("init_start".equals(parts[1])){ //*
yourMethod();
}
For the other case:
if("init_start".equals(text)){ //*
yourMethod();
}
*Also:
"I meant to do this using if(scanner.Next=="init_start")"
*Very important! To compare Objects, such as String use .equals(). "==" only works on primitive types
Edit: I've read your example. You could go with a combination of my solutions. split the string at space(" ") and check parts[x] if it is an integer. But i wouldnt recommend this method! Why dont you split your input in three parts: init_start would start your function. After that your method would expect an input of Integers like "int int int" after you inserted the Integers your function could automatically stop or wait for the input "init_stop". That seems to me more reasonable. If you want to go with the single line solution you can evaluate the number of your int's by get tingparts[].lenght()-2
use this implementation:
public static void main(String args[]){
try{
Scanner in = new Scanner(System.in);
System.out.println("Enter a line");
String dat = in.readLine();
System.out.println(dat);
}
catch(IOException e){
System.out.println("IO ERROR !!!");
System.exit(-1);
}
}
this is my first post so forgive me if i have posted incorrectly. I have a task that i need to complete but i cant get it to work properly. the compiler that i use is bluej. what i need to do is to use scanner to read a text file and compare a user input to the text file. if the input string compares then it should print out that ""The word is on the text file". Unfortunately i cant get this to work. My code reads the file because it prints out to the console but no comparison it s happening. please have a look at my code and give me some pointers. i have been trying to use .equals():
private boolean searchFromRecord(String recordName, String word) throws IOException
{
// Please write your code after this line
File file = new File(recordName);
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
for(int i = 0; scanner.hasNextLine(); i++){
String compare = scanner.nextLine();
IO.outputln("word#" + i + ":" + compare);
}
scanner.close();
if (scanner.equals(word)){
return true;
} else{
return false;
}
}
return true;
}
this is what i get output in the console:
Input a word: IRON
AA 888
word#0:BULLET
word#1:1
word#2:AE 1688
word#3:CHEERS
word#4:GAMES
word#5:IRON MAN
word#6:WOLF
word#7:Testing
word#8:Wonderful
The word "IRON" is not in the record.
Here are some problems, along with why they are problems & a suggestion on how they could be fixed:
Problem: closing a scanner within the a loop that uses it will cause an exception. Reason: after we go through the loop once, the scanner will be closed. when we loop through again, an error will occur since the loop uses the scanner, which means the scanner should be "open". Possible solution: move scanner.close() to after the while loop.
Problem: we shouldn't return true at the end of this method. Reason: I'm guessing that this method is supposed to return true if the word is found, and false otherwise. Now, the only way to get to this return statement is if our word doesn't exist in the recordFile; it should return false. Possible solution: return false at the end of the method instead.
Problem: the first line in recordFile will never be checked for equality with word Reason: each method call of scanner.nextLine() will return each line from the recordFile as a String once and only once. In your code, it is called once in the beginning of the while loop's body, but not used to compare with word, then after, it is used in the for loop for comparison Possible solution: remove the line: System.out.println(scanner.nextLine());.
Problem: scanner.equals(word) will probably always return false. Reason: scanner is a Scanner, and word is a String, they should never be equal. Possible solution: replace scanner.equals(word) with compare.equals(word)
Problem: word is not actually compared with each compare. Reason: it is outside the for loop. Possible solution: move the if else block into the end of the for loop's body.
I don't think the while loop is really needed. I strongly recommend that the while loop, is removed, but keep the body.
Problem: Moving the if else block into the for loop, and above the scanner.close() means that the scanner.close() will never be run. Reason: once a return statement is executed, the flow of control immediatly exits the method, and returns to where the method was invoked which makes code after return statements useless. Possible solution: instead of returning right away, declare some sort of boolean variable that will store the return value. have the return value be modified throughout the method, then return the variable at the very end, after scaner.close()
There are many many other ways to fix each of these problems other than the ones suggested here.
I hope you find this helpful! :)
your code, refactored to implement the suggested solutions above:
private boolean searchFromRecord(String recordName, String word) throws IOException {
// Please write your code after this line
Boolean wordFound = false; // indicates if word exists in recordFile.
File file = new File(recordName); // file at path "recordName"
Scanner scanner = new Scanner(file); // reads records from "file"
// iterate through the recordFile, to see if "word" already exists
// within recordFile.
for(int i = 0; scanner.hasNextLine(); i++) {
// read the record from the file
String compare = scanner.nextLine();
IO.outputln("word#" + i + ":" + compare);
// compare the record with our word
if (compare.equals(word)){
wordFound = true;
break; // bail out of loop, our work here is done
}
}
// clean up, and return...
scanner.close();
return wordFound;
}
First, scanner is not a String and it will not equal a String. Second, you are dropping lines - scanner.nextLine() gets the next line, and you print it (but don't save it or compare it). I think you wanted something more like this,
// eats and tosses input.
// System.out.println(scanner.nextLine());
String line = scanner.nextLine();
for(int i = 0; scanner.hasNextLine(); i++){
String compare = scanner.nextLine();
IO.outputln("word#" + i + ": " + compare + " to line: " + line);
if (line.contains(compare)){ // "IRON MAN" starts with "IRON", it doesn't equal IRON.
return true;
}
}
scanner.close();
return false; // <-- default.
Another flavor is to read the whole file into a String variable and look for specified String inside the String.
Code:
File file = new File("C:\\Users\\KICK\\Documents\\NetBeansProjects"
+ "\\SearchWordinFile\\src\\searchwordinfile\\words.txt");
String s="";
try(Scanner input = new Scanner(file)){
input.useDelimiter("\\A");
if (input.hasNext()) {
s = input.next();
}
}catch(Exception e){
System.out.println(e);
}
if(s.contains("IRON"))
System.out.println("I found IRON");
}
Output:
I found IRON
My File content
BULLET
1
AE 1688
CHEERS
GAMES
IRON MAN
WOLF
Testing
Wonderful
I've got a problem here that's been giving me some real trouble and I really cant even get an idea of what to do. here's the assignment and my code so far.
Create a system using an ArrayList which stores and manipulates names.
Using standard input constantly prompt user for the following ..
Enter command or quit: (if they enter quit -- quit program)
Commands:
add <name>: add the String <name> to ArrayList;
change <name> <newName>: change all items in ArrayList which
have <name> to <newName>;
delete <name>: delete all items in Arraylist which are <name>;
print: print the ArrayList;
amount: display the amount of items in ArrayList.
System must work... and have proper error messages..
import java.util.*;
public class NameManipulation {
static Scanner console = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("enter a command, or quit!");
ArrayList<String> names = new ArrayList<String>();
String command = console.next();
int size = names.size();
for (String x = null; size; x++) {
if (command == "add") {
String assignment = console.next();
names.add(assignment);
}
if (command == "change") {
String newname = console.next();
names.set(names.size, newname);
}
if (command == "delete") {
String delete = console.next();
if (delete == names)
;
names.remove();
}
if (command == "print") {
System.out.println(names);
}
if (command == "amount") {
amount = (names.size - 1);
System.out.println(amount);
}
if (command == "quit") {
System.out.println("You just quit!");
break;
} else
System.out.println("command not found!");
System.out.println(names);
}
}
}
Don't use == (in Java that tests reference equality); you want to test for object value equality (and I suggest case-insensitivity) so you want to use String.equalsIgnoreCase and you should probably use else if for the other tests - for one example,
if(command.equalsIgnoreCase("add")) {
String assignment = console.next();
names.add(assignment);
} else if // ...
Also, this is just wrong;
for (String x = null; size; x++) // null++ is going to give you a bad time.
I think you wanted
for (int x = 0; x < size; x++)
Just looking at this it seems like it has a lot of problems...
In the for loop you're initializing a String to null and then trying to increment it (x++). I don't think that's legal syntax. Also, your for loop condition is set to size, which will initially be equal to 0. I'd have to test it, but the 0 may evaluate to false, which means the loop would never execute.
You don't want a for loop anyway, probably a do-while loop that runs until the command is equal to "quit" do{}while(!command.equals("quit"));
You should be using .equals() instead of '==' as was mentioned by Elliot Frisch. Also ignoring case is good, and you should be using else ifs.
In the change command you should be parsing out two parameters -- both the name to replace and the new name, and then perform the replacement. Right now you have the first parameter as names.size, which I think will be outside the bounds of the list (names.size() - 1 should be the last element). Instead you should get the index of the name you're replacing.
Depending on Java's toString implementation of ArrayList it may print out names nicely or it might be something like "#ArrayList Object" - I think Java has a nice ArrayList toString method though so that may work.
On the print amount, you should be using names.size() instead of names.size() - 1 (because names.size() - 1 will give you one less item than what is actually in the list)
you could try and use a switch block that could stream line your control statements. As stated above learn when to use == and when to use the .equals(). One compares a reference (==) the other compares the memory location, the important thing to take away from this, is that a String is an object and when you create a new String, it compares the address rather than a value (forgive me if i am wrong).
switch(command){
case "add": names.add(assignment);
break;
case "change": ..... etc.
}
If I were trying to accomplish this task I would use a List, not an ArrayList. I hope this method helps! This is C# code. I don't know the exact Java syntax but it seemed as if a lot of it was similar. I hope this methodology helps!
static void Main(string[] args)
{
string statement = "";
bool executed_command_properly;
while (statement != "quit")
{
executed_command_properly = false;
statement = Console.ReadLine();
string[] my_statement_elements = statement.Split(' ');
string command = my_statement_elements[0];
//could possibly use an array for inputs
string input1 = my_statement_elements[1];
string input2 = my_statement_elements[2];
switch(command)
{
case "add":
// do stuff
executed_command_properly = true;
break;
//other cases
}
if (executed_command_properly != true)
{
//error messages
}
}
}
This question already exists:
Closed 10 years ago.
Possible Duplicate:
Scanner issue when using nextLine after nextInt
I am creating a client program that needs to read both a String and an integer from my server. Depending on what integer it receives it adds some labels to the GUI. So far, my program reads the integer but skips the String. The following output is the output of my program when I try to write the integers to the program:
Server writes: 1
Server writes: 1
System prints: 1
System prints: j1
System prints: Name
The problem is that I am unable to write a String because it skips the String. How can I avoid this problem (note that I have also tried a for loop)
My code is as following:
int times = client.reciveCommando();
int o = 0;
System.out.println(times);
while (o != times) {
int j = client.reciveCommando();
System.out.println("j"+ j);
String name = client.reciveString();
System.out.println("Name " +name);
createUser(j, name);
o++;
}
The createUser method:
private void createUser(int j, String reciveChat) {
if (j == 1) {
chatPerson1.setVisible(true);
lbl_Chatperson1_userName.setVisible(true);
lbl_Chatperson1_userName.setText(reciveChat);
} else if (j == 2) {
lbl_chatPerson2.setVisible(true);
lbl_userName2.setVisible(true);
lbl_userName2.setText(reciveChat);
} else {
chatPerson3.setVisible(true);
lbl_userName3.setVisible(true);
lbl_userName3.setText(reciveChat);
}
}
The client.reciveCommando method:
public int reciveCommando() throws IOException{
Integer i = input.nextInt();
return i;
}
The client.reciveString method:
public String reciveString(){
String x = input.nextLine();
return x;
}
Hope someone is able to help me with this :)
Thank you in advance.
I don't see anywhere in the loop code where you are incrementing o or changing the value of times. So either the loop is being skipped altogether (ie: times = 0) or some other place in the code is modifying either the loop variable (o) or the loop condition (times) - very bad coding in either case.
Your loop variable/increment rules should be very clear in reading the loop and easily discernible what the start/stop conditions are without needing to read other methods/etc which may modify the values during loop iteration.
My immediate guess is that times = 0, or you would be in an endless loop.
i found the solution to my question it turned out to be quite simple!
first of all let me explain what i ment.
When i my program ran the while loop it basicly skipped the line where it should have recived an input from the server. i found that the reason it did that was that the input.nextLine(); was empty which makes sence when you read the api for input.nextLine();
Advances this scanner past the current line and returns the input that was skipped. This method returns the rest of the current line, excluding any line separator at the end. The position is set to the beginning of the next line.
Since this method continues to search through the input looking for a line separator, it may buffer all of the input searching for the line to skip if no line separators are present.
Returns:
the line that was skipped
since the line that i tried to get was an empty line it would skip and set name to " ".
here is the full complete code for my program and it currently works:
The while loop:
while (o != times) {
int j = client.reciveCommando();
System.out.println("j"+ j);
String name = client.reciveString();
System.out.println("Name " +name);
createUser(j, name);
o++;
}
The client.reciveString();
public String reciveString(){
String x = input.next();
return x;
}
The createUser();
private void createUser(int j, String reciveChat) {
if (j == 1) {
chatPerson1.setVisible(true);
lbl_Chatperson1_userName.setVisible(true);
lbl_Chatperson1_userName.setText(reciveChat);
}else if (j == 2) {
lbl_chatPerson2.setVisible(true);
lbl_userName2.setVisible(true);
lbl_userName2.setText(reciveChat);
}else if (j == 3){
chatPerson3.setVisible(true);
lbl_userName3.setVisible(true);
lbl_userName3.setText(reciveChat);}
Thank you for all of your responses and i will be sure to vote you up :)