Discussions
Categories
- 197.1K All Categories
- 2.5K Data
- 546 Big Data Appliance
- 1.9K Data Science
- 450.7K Databases
- 221.9K General Database Discussions
- 3.8K Java and JavaScript in the Database
- 31 Multilingual Engine
- 552 MySQL Community Space
- 479 NoSQL Database
- 7.9K Oracle Database Express Edition (XE)
- 3.1K ORDS, SODA & JSON in the Database
- 555 SQLcl
- 4K SQL Developer Data Modeler
- 187.2K SQL & PL/SQL
- 21.3K SQL Developer
- 296.3K Development
- 17 Developer Projects
- 139 Programming Languages
- 293K Development Tools
- 110 DevOps
- 3.1K QA/Testing
- 646.1K Java
- 28 Java Learning Subscription
- 37K Database Connectivity
- 158 Java Community Process
- 105 Java 25
- 22.1K Java APIs
- 138.2K Java Development Tools
- 165.3K Java EE (Java Enterprise Edition)
- 19 Java Essentials
- 162 Java 8 Questions
- 86K Java Programming
- 81 Java Puzzle Ball
- 65.1K New To Java
- 1.7K Training / Learning / Certification
- 13.8K Java HotSpot Virtual Machine
- 94.3K Java SE
- 13.8K Java Security
- 204 Java User Groups
- 24 JavaScript - Nashorn
- Programs
- 466 LiveLabs
- 39 Workshops
- 10.2K Software
- 6.7K Berkeley DB Family
- 3.5K JHeadstart
- 5.7K Other Languages
- 2.3K Chinese
- 175 Deutsche Oracle Community
- 1.1K Español
- 1.9K Japanese
- 233 Portuguese
How do I charAt In a Input with a variable length, without getting the StringIndexOutOfBoundsExcepti

Hello. I've been trying to make a timer in an applet, by making it
1. You input the Hours:Minutes:Seconds
2. The program will separate them into different ints.
3. It will subtract 1 from the "Sec" Int every second, and when Sec runs out it will subtract from Min, And when it ends it will subtract from Hour, and at last, Play a sound.
But, because not always you will have Hours or Minutes on the timer, when I try to use charAt to extract the digits (on the second step) some times it throws a StringIndexOutOfBoundsException.
I'm probably doing the unefficient way, and I'm certain that I have more than 1 mistake in my code.
I am not asking someone to spoonfeed the code. But I would really appreciate if someone could enlighten on what I'm doing wrong here.
Thanks in advance.
(Also, this code is uncompilable. But I will ask about that in another discussion.)
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) {
int HMS = Integer.parseInt(jTextField1.getText());
String HourMinSec = Integer.toString(HMS);
if(HourMinSec.regionMatches(0,"00000",0,5)){
int Sec = (int) HourMinSec.charAt(0);
int Min = 0;
int Hour = 0;
} else
{ if (HourMinSec.regionMatches(0,"0000",0,4)){
int Sec = (int) HourMinSec.charAt(0) * 10 + (int) HourMinSec.charAt(1);
int Min = 0;
int Hour = 0;} else{
if (HourMinSec.regionMatches(0,"000",0,4)){
int Sec = (int) HourMinSec.charAt(1) * 10 + (int) HourMinSec.charAt(2);
int Min = (int) HourMinSec.charAt(0);
int Hour = 0;}
else {
if(HourMinSec.regionMatches(0,"00",0,2)){
int Sec = (int) HourMinSec.charAt(2) * 10 + (int) HourMinSec.charAt(3);
int Min = (int) HourMinSec.charAt(0) * 10 + (int) HourMinSec.charAt(1);
int Hour = 0;
} else {
if(HourMinSec.regionMatches(0,"0",0,1)){
int Sec = (int) HourMinSec.charAt(3) * 10 + (int) HourMinSec.charAt(4);
int Min = (int) HourMinSec.charAt(1) * 10 + (int) HourMinSec.charAt(2);
int Hour =(int) HourMinSec.charAt(0);
} else {
int Sec = (int) HourMinSec.charAt(4) * 10 + (int) HourMinSec.charAt(5);
int Min = (int) HourMinSec.charAt(2) * 10 + (int) HourMinSec.charAt(3);
int Hour =(int) HourMinSec.charAt(0) * 10 + (int) HourMinSec.charAt(1);}}}}
while(Sec != 0 || Min != 0 || Hour != 0){
Thread.sleep(9);
Sec -= 1;
if(Sec == 0){
Min -= 1;
Sec = 60;}
if(Min == 0){
Hour -= 1;
Min = 59;
}
jTextField1.setText(Hour + ":" + Min + ":" + Sec);
}
}
Best Answer
-
1. For StringIndexOutOfBoundsException:
int HMS = Integer.parseInt(jTextField1.getText()); //line A
String HourMinSec = Integer.toString(HMS); //line Bline A converts the user input to an int that gets rid of all leading zeros if any in the input. ie.,
"00005" --> 5
then, in line B, the conveted int is turned into a string and passed to the rest of the method.
so, the conditions are checking for "5"
so, all your subsequent checks for regionmatches fail to match any because line A parseInt() call got rid of all leading zeros. I have removed the code within the blocks to highlight the issue area.
if (HourMinSec.regionMatches(0, "00000", 0, 5)) { } else { if (HourMinSec.regionMatches(0, "0000", 0, 4)) { } else { if (HourMinSec.regionMatches(0, "000", 0, 4)) { } else { if (HourMinSec.regionMatches(0, "00", 0, 2)) { } else { if (HourMinSec.regionMatches(0, "0", 0, 1)) { } else { // for all your input, you are ending up here Sec = (int) HourMinSec.charAt(4) * 10 + (int) HourMinSec.charAt(5);
To prevent the StringIndexOutOfBoundsException, your input should at least have 6 digits after the leading zeros - remember index starts at 0, so charAt(5) will need six characters to match.
2. The local variables Sec, Min and Hour are defined in each IF block. they are local to that block and do not have visibility outside that block. Define the variables once at the top.
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) { int Sec = 0; int Min = 0; int Hour = 0;
3. int conversion from charAt() call does not return what you think it returns. (edited)
'0' --> 48'1' --> 49...'9' --> 57
4. IF -- ELSE -- IF
Your code block can be simplified
from
if (HourMinSec.regionMatches(0, "00000", 0, 5)) { } else { if (HourMinSec.regionMatches(0, "0000", 0, 4)) { } else { if (HourMinSec.regionMatches(0, "000", 0, 4)) {
to
if (HourMinSec.regionMatches(0, "00000", 0, 5))
{
//...
}
else if (HourMinSec.regionMatches(0, "0000", 0, 4))
{
//...
}
else if (HourMinSec.regionMatches(0, "000", 0, 4))
{
Answers
-
To answer your question first, you can do a int l = HourMinSec.length() to get the length of the String, and when you do a charAt() make sure that that number is not bigger than the length of the String, ie the variable l is less than 3, then don't do charAt(3).
A hint for later on, use the Calendar class.
-
1. For StringIndexOutOfBoundsException:
int HMS = Integer.parseInt(jTextField1.getText()); //line A
String HourMinSec = Integer.toString(HMS); //line Bline A converts the user input to an int that gets rid of all leading zeros if any in the input. ie.,
"00005" --> 5
then, in line B, the conveted int is turned into a string and passed to the rest of the method.
so, the conditions are checking for "5"
so, all your subsequent checks for regionmatches fail to match any because line A parseInt() call got rid of all leading zeros. I have removed the code within the blocks to highlight the issue area.
if (HourMinSec.regionMatches(0, "00000", 0, 5)) { } else { if (HourMinSec.regionMatches(0, "0000", 0, 4)) { } else { if (HourMinSec.regionMatches(0, "000", 0, 4)) { } else { if (HourMinSec.regionMatches(0, "00", 0, 2)) { } else { if (HourMinSec.regionMatches(0, "0", 0, 1)) { } else { // for all your input, you are ending up here Sec = (int) HourMinSec.charAt(4) * 10 + (int) HourMinSec.charAt(5);
To prevent the StringIndexOutOfBoundsException, your input should at least have 6 digits after the leading zeros - remember index starts at 0, so charAt(5) will need six characters to match.
2. The local variables Sec, Min and Hour are defined in each IF block. they are local to that block and do not have visibility outside that block. Define the variables once at the top.
private void jTextField1ActionPerformed(java.awt.event.ActionEvent evt) { int Sec = 0; int Min = 0; int Hour = 0;
3. int conversion from charAt() call does not return what you think it returns. (edited)
'0' --> 48'1' --> 49...'9' --> 57
4. IF -- ELSE -- IF
Your code block can be simplified
from
if (HourMinSec.regionMatches(0, "00000", 0, 5)) { } else { if (HourMinSec.regionMatches(0, "0000", 0, 4)) { } else { if (HourMinSec.regionMatches(0, "000", 0, 4)) {
to
if (HourMinSec.regionMatches(0, "00000", 0, 5))
{
//...
}
else if (HourMinSec.regionMatches(0, "0000", 0, 4))
{
//...
}
else if (HourMinSec.regionMatches(0, "000", 0, 4))
{ -
Forgot to add:
For item #2: Remove the repeated definitions of Local variables (Sec, Min and Hour).
if(HourMinSec.regionMatches(0,"00000",0,5)){ int Sec = (int) HourMinSec.charAt(0); int Min = 0; int Hour = 0; } else
On a general note, why don't you want to request the user input as the more commonly known format hh:mi:ss. this would make your task easier.
I would suggest that you comment out the sleep() and run the block with System.out.println() version while fixing it.
while (Sec != 0 || Min != 0 || Hour != 0)
{
//Thread.sleep(9);
Sec -= 1;
if (Sec == 0)
{
Min -= 1;
Sec = 60;
}
if (Min == 0)
{
Hour -= 1;
Min = 59;
} //jTextField1.setText(Hour + ":" + Min + ":" + Sec);
System.out.println(Hour + ":" + Min + ":" + Sec);
} -
You seem to be trying to write code BEFORE you have defined and documented all of the requirements.
And you then should be writing pseudo-code that says, in English, what each step does.
Next you walk through each step manually and verify that it does what you think it does.
The BIGGEST problem with your code and process is you are making it WAY TOO COMPLICATED
Hello. I've been trying to make a timer in an applet, by making it1. You input the Hours:Minutes:Seconds2. The program will separate them into different ints.
Get the user input the SIMPLE way. Create a drop-down for hours, another for minutes and another for seconds. That way the only choices the user has is 1-24 for hour, 0-59 for minutes and 0-59 for seconds.
Convert the strings for hour, minute and second to 'int'.
Then use simple nested loops:
for (hour ...) { for (minute ...) { for (second ...) { sleep for one second display the hour:minute:second } }}
The ONLY real code you need is the sleep one second and the display.
The outer FOR loop automatically counts down the hours ('for (hour = startHour; hour >= 0; hour --')).
The 'minute' FOR loop automatically counts down the minutes.
The 'second' for loop automatically counts down the seconds.
The above is pretty TRIVIAL.
Suggestion: ALWAYS do things the simplest, possible way until you have something that actually works properly. Then you can clutter it up, if necessary, with other stuff.
-
nNem really helped me to understand why my code wasn't working, and rp0428 gave me a really good solution.
And I would never know about the calendar class if it wasn't handat.
Big thanks to all of you.