Receiving an error while executing method substring in Java - java

I have to do a String exercise where I have to enter a date like dd/mm/yyyy. Everything works fine except if I enter a space as the input, it prints this error:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: begin 0, end 2, length 1
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3720)
at java.base/java.lang.String.substring(String.java:1909)
at ex5.main(ex5.java:17)
This is my code:
import cs1.*;
public class ex5
{
public static void main(String[] args)
{
String data = "18/08/2011";
//asking for the data
System.out.printf("DATA: ");
data = Keyboard.readString();
//system.out
System.out.printf("DIA: %s %n", data.substring(0, 2));
System.out.printf("MES: %s %n", data.substring(3, 5));
System.out.printf("ANY: %s", data.substring(6, 10));
}
}

My suggestion is that you test whether your input string has length 10. If it is shorter or longer, you know that it cannot have the expected format, so trying your substring calls will make no sense and may cause your program to crash as you have observed.
You need to call data.length(). This method will return the length of the string as an int, for example 10 for 18/08/2011 and 1 for a space. And you need to use an if statement to control that you only call substring() if the returned length is equal to 10. You will probably want an else part in which you issue a friendly message to the user about why your are not printing day, month and year.
This is a very good exercise as it may help you learn something we all have to learn: To validate, to check our input in order to determine whether it fulfils the requirements for the input and whether there is good reason to believe that it is wrong. The clear and strong recommendation is that you always do this.
Please realize that the user may enter any characters and any number of characters when your program asks for a date. Possible inputs include 18/8/2011 (one digit month and therefore too short), 18 d’agost de 2011 (too long) and any nonsense they can dream up. Make your program react as sensibly as possible in each case.
I would like to add that for production code one would use a DateTimeFormatter from the standard library for validating the input and parsing it into a date (a LocalDate).

Related

How to solve memory exceeding error in Java ; Related to Strings

I wanted to make a program that outputs a string repeated a given number of times (separated by a space) using String.repeat, but have been running into a java.lang.OutOfMemoryError when the string is repeated too many times. How can I determine the maximum number of times a string can be repeated without causing an out of memory error?
I search online for the maximum length of a string and came up with 2147483647. In my code, I divide this maximum length by the length of the string to repeat. I wanted it to round off automatically, so I used the int data type. I expected my program to be able to print the word, but instead of printing the result it still generates an out of memory error. Is the maximum string length correct? If not, what is the maximum string length?
import java.util.*;
public class Darshit {
public static void main(String[] Darshit1) {
Scanner Darshit = new Scanner(System.in);
System.out.println("WELCOME TO WORD RE-PRINTER!");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("Enter the text");
String b = Darshit.nextLine();
int len = b.length()+1;
int e = 2147483647/len;
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("How many times you want to repeat the text");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("Note ~>");
System.out.println("You can only print the word upto " + e + " times!");
int a = Darshit.nextInt();
String c = " ";
String d = b + c;
System.out.println(d.repeat(a));
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
System.out.println("Thank you for using it");
System.out.println("Made by Darshit Sharma");
System.out.println("8th-C");
System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
}
}
Generally speaking, there are two approaches to handling errors:
test beforehand whether performing an operation will cause error and not perform the operation if it will (defensive programming)
trap errors if they happen (exception handling)
Different platforms have different conventions about which approach is preferred in which context (assuming exception handling is even supported). In this case, however, there is no reliable way to test whether there will be an error caused by repeating the string too many times.
In many situations, handling an OutOfMemoryError won't lead anywhere, as there isn't a way to recover and get the application back to a valid state, mainly because if the application is running low on memory, it probably won't be able to do anything useful. It might be able to log or print a message explaining why it's crashing, so the program could catch & rethrow, but usually not much more than that. In this case, your program has enough memory for most of its tasks (just not enough for the primary task of allocating the repeated string) and is simple enough that you can handle it simply: print a message explaining what happened. After that, the application is already close to exiting, so no other handling should be needed.
try {
System.out.println(d.repeat(a));
} catch (java.lang.OutOfMemoryError oome) {
System.err.println("I ran out of memory trying to repeat the string. You asked for too many repetitions.");
}

Design Pattern in Java for Getting Input and Acting on it

I'm trying to make a tic-tac-toe game and I'm encountering a lot of copy-paste work for inputs. I'm trying to figure out what design pattern and implementation works for prompting the user, collecting their input, comparing it and then acting by assigning a value. Right now my code looks like this.
public void promptPlayerCount(BufferedReader in) throws IOException {
String input;
// initial prompt
System.out.println("How many players?");
input = "try again";
while (input.equals("try again")) {
input = in.readLine();
// extract data and check it
switch (Integer.parseInt(input)) {
case 1:
// assignment
playerCount = 1;
break;
case 2:
playerCount = 2;
break;
default:
input = "try again";
// clarified instructions
System.out.println("please enter 1 or 2");
}
}
}
There's a part of me that thinks I could make a function (maybe a factory?) that allows me to generate a function by passing the constructing function the details of the initial prompt, the extraction method, the assignment action and the clarification message.
Would this be best done with lambda functions?
Text input is hard, especially if you can't trust your user (like in a game). Your parseInt will throw a nasty exception right off if your value isn't an integer.
Also standard in is not friendly. I assume this is for an assignment so I won't fault you for using it, but in anything where you don't HAVE to use stdin, don't. The problem is that it's amazingly difficult to get Java to respond to anything less than an entire line with an enter at the end.
When dealing with user input I almost always trim it (Just because they love to insert random white spaces at the beginnings and end) and check to see if it's empty. This could probably be put into a function that also either shows an error or exits the program on "Empty" and otherwise returns a string.
If you often want int values, write a second function that calls the first. Have the second function return an int, but have it catch the exception if the text is invalid and prompt the user again. You could even have this function take a "Range" of integers as a parameter and provide a prompt. So what you have above could look like this:
playerCount = getUserInput("Please enter the number of users", 1, 2);
The rest is wrapped in simple non-redundant functions.
Won't write the code for you because A) it's probably a homework assignment and the fun part is actually coding it and B) someone else probably will provide a full solution with code before I'm done typing this :(
Good luck.

Showing real numbers with thousands separator while typing

I'm trying to develop a calculator app in Java. My problem is this:
When I type the digit 1 I see 1, But if I type 1.00 I only see 1.
I wish my user to see 1,234.00 if he types 1,234.00, and not just 1234.
Here's part of my code:
NumberFormat MyNumberForamt = new DecimalFormat("#,###.#####");
String finale = MyNumberForamt.format(Double.parseDouble(Ex1));
resultField.setText(finale);
What can I do?
Note: I am talking about showing the number as the user type it, not at the end of it.
Did you read the docs for DecimalFormat?
....
0 Number Yes Digit
# Number Yes Digit, zero shows as absent
....
Seems like you want to use the format:
new DecimalFormat("#,###.00");

Java: invoking methods in main program, but getting an error

I'm just learning Java and am practicing creating methods and then invoking them in my main program. To practice this I created a simple program that's supposed to gather data from a prospective horse rider.
Here is the main application:
public class CompleteApp {
public static void main(String[] args) {
TaskOne weight1 = new TaskOne();
TaskTwo nameagehealth1 = new TaskTwo();
TaskThree phoneaddress1 = new TaskThree();
if (weight1.Weight() < 250) {
nameagehealth1.NameAgeHealth();
phoneaddress1.AddressPhone();
}
else {
System.out.println("Thanks for checking!");
}
}
}
I've created three separate classes to do different tasks. Here is the class that's having prompting the error:
import java.util.Scanner;
public class TaskThree {
static void AddressPhone() {
Scanner input = new Scanner(System.in);
System.out.println("Please tell me your address: ");
String address = input.nextLine();
System.out.println("Please tell me your phone number: ");
int phone = input.nextInt();
System.out.println("You said your address is " + address + " and your phone is " + phone + ".");
System.out.println("Thank you for the information, we'll be in touch soon to schedule your ride.");
}
}
The error:
Exception in thread "main" java.util.InputMismatchException: For input string: "3037201234"
at java.util.Scanner.nextInt(Scanner.java:2123)
at java.util.Scanner.nextInt(Scanner.java:2076)
at TaskThree.AddressPhone(TaskThree.java:10)
at CompleteApp.main(CompleteApp.java:13)
It seems to indicate that the error is in the phone number and that is being read as a String, yet I made it an integer. I'm not sure where I'm going wrong here. Also, how would I handle it if a user entered their phone number like this: 303-720-1234 vs 3037201234?
Thanks so much for the help!
Since it can't be stored as an int due to the length as Sibbo mentioned, and you're concerned about formatting then you should store it as a String. If you have to do any type of checking to make sure the user inputs data in the correct format (either 1234567890 or 123-456-7890) then you should look into regular expressions. If you run a regular expression on your string then you will be able to get a boolean result to tell you whether or not it is valid.
Why not represent the phone number as a String and use scanner.next()? As mentioned before, when a phonenumber start with a 0 this zero would be removed if you use anything other than String, so I think it's the best way to go.
From your comments, I read that parsing it to a Long works for you. I would strongly recommend using a String though, for several reasons:
Phone numbers with leading zeroes (like international phone numbers). Integers and Longs 'trim' leading zeroes, rendering your phone numbers useless.
If you want to do some extra stuff when presenting your phone numbers (like adding dashes or anything), you will have to parse your Integer/Long back to a String and do your representation magic anyway.
As you just found out, not every phone number can be stored in a 32-bit Integer, but you already worked around that using a Long.
There are probably more reasons for this, but these 2 come to mind.
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). Your input value is out of the range of int.
You should store phone number as String rather than int. If you want to handle numbers like 303-720-1234, parse it as string, remove the - character and then use it.
The input 3037201234 is too large to be represented as an int, so it cannot be parsed as an int.
Integers in Java range from −2,147,483,648 to 2,147,483,647.
Instead of using int for variable phone declare it as long and instead of input.nextInt() use method input.nextLong(). I think this will solve your problem.

What is the proper syntax of Java's lastIndexOf and indexOf when validating data?

e have a date form that can accept 2 or 4 digit years. I am not trying to code for exceptions...just instances where the year is either 2 or 4 digits long. I'm using lastIndexOf to find the last instance of "/", and if the third character after the slash is numeric, I assume a 4-digit year. Otherwise it's a two digit year.
I've already tested and validated that this is the only line giving me an issue right now,
if (inputLine.lastIndexOf.isNumeric("/"))+3 {
year = inputLine.trim().substring(inputLine.lastIndexOf("/")+1,input.lastIndexOf("/")+4).trim);
else year = "0000";
I keep getting compilation errors. For the lines in which I'm adding to the index Value, I've got a bad operand for the binary operator. Additionally, the variable lastIndexOf can't be found.
I'm calling the list below at the head of the program, and as far as I can tell from the java documentation, io and lang pull in the appropriate methods and classes.
import java.util.*;
import java.io.*;
import java.nio.file.*;
import java.lang.*;
For the if statement, although my parens are balanced, I don't know if adding the additional characters (e.g., index value + 3) is being done within the right level of the nested parens. That being said, I've tried top add those integers pretty much to no avail.
if (inputLine.lastIndexOf.isNumeric("/"))+3 {
year = inputLine.trim().substring(inputLine.lastIndexOf("/")+1,input.lastIndexOf("/")+4).trim);
else year = "00/00/0000";
I'm wondering a couple thigs: First, can I do this in a single statement, or is it better to define the index in one statement, then define index+offset-value in a subsequent statement?
When I'm using multiple methods and classes operating on a single field (e.g., .trim().substring.Indexof() etc., what is the order in which Java parses those? I'd like to undestand how these statements are being parsed so I've got a better understanding of the best way to manipulate the variables and test the output.
You are using the +3 incorrectly. You're putting it outside of the if(condition) statement, somewhere where it doesn't make any syntactic sense - it's gobbledygook in your code.
Also, if you're trying to test if the result of inputline.lastIndexOf('/') is numeric, it won't mean anything. If the specified character does not occur, lastIndexOf won't throw an exception; it will just return -1. You want to test if the result is greater than/equal to zero.
You can't use trim() and then use an index from the original string. You need to trim() the string and then use an index from the trimmed string (otherwise the index could be completely incorrect)
Perhaps using SimpleDataFormat with a dd/MM/yyyy format or using split would be a better choice.
String[] parts = inputLine.trim().split("/");
String day = parts[0], month = parts[1], year = parts[2];
To use trim() and lastIndexOf()
String trimmed = inputLine.trim();
int last = trimmed.lastIndexOf("/");
year = trimmed.substring(last+1);
Regarding the last part of your question
When you do method chaining like .trim().substring.Indexof() each method is invoked in left-to-right order. So:
String myString = " string ";
int index = myString.trim.substring(3).indexOf('n');
is the comparable to:
String myString = " string ";
String trimmedString = myString.trim(); // "string"
String subString = trimmedString.substring(3) // "ing"
int index = subString.indexOf('n'); // 1

Categories