Reputation: 33
I was trying to write a java program where every digit of an input integer is printed in words.
For example: input 123
should produce an output "one two three"
.
I wrote the following program that takes an integer value, then converts it into a string. I then iterated over the characters of the string and converted them to integer values, which I later used as indices for the array.
But I'm getting ArrayIndexOutOfBoundsException
.
Index 49 out of bounds for length 10
My code:
public class DigitsAsWords {
static void Print_Digits(int N){
String arr[] = {"zero","one", "two", "three", "four","five", "six", "seven", "eight", "nine"};
String st = Integer.toString(N);
System.out.println(st);
char s;
int a;
for (int i=0; i<st.length(); i++){
s = st.charAt(i);
a = Integer.valueOf(s);
System.out.print(arr[a]+" ");
}
}
public static void main (String args[]){
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
Print_Digits(a);
}
}
Upvotes: 2
Views: 1067
Reputation: 28968
Firstly, lean about the primitive data types in Java.
If your background is JavaScript, which has no char
type, you might have been thinking that char
is a "kind of" string, but it's not.
char
- is a 16-bit numeric primitive data type, which has a minimum value of '\u0000' (or 0
) and a maximum value of '\uffff' (or 65,535
) which was meant to represent Unicode-characters. But in the earlier days of Java the Unicode standard has been changed, and char
type appeared to be broken, to fix this code points were introduced in the language.
In this statement a = Integer.valueOf(s);
character s
is being promoted into int
type and method valueOf()
creates an unnecessary instance of Integer
which is being immediately thrown away, and you end up with a
having a value in the range from 48
(0
) to 57
(9
), which is greater than array's length. Therefore, you're getting a justifiable ArrayIndexOutOfBoundsException
.
Also, there are few more issues.
Compiler will not complain that you're creating a new array for each method call but this approach is wrong, the string array should be static
, i.e. it should reside on a class level:
public static final String[] DIGITS = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
Another important issue which might seem unimportant is that the names you're using both uninformative (like arr
) and they violate the Java naming convention (like Print_Digits
).
Also, C-style of array declarationString arr[]
is not considered to be a good practice in Java because it mixes the data type and the variable name.
And here is a couple of solutions for this problem.
The first one is somewhat close to code provided by OP:
public static void printDigits1(int num) {
String numericString = String.valueOf(num);
for (int i = 0; i < numericString.length(); i++) {
String digit = DIGITS[Character.getNumericValue(numericString.charAt(i))];
System.out.print(digit + " ");
}
}
We can also address this problem without using strings at all:
public static void printDigits2(int num) {
if (num == 0) {
System.out.println(DIGITS[0]);
return;
}
int len = (int) Math.ceil(Math.log10(num));
String[] result = new String[len];
for (int cur = num, i = len - 1; cur > 0; cur /= 10, i--) {
result[i] = DIGITS[cur % 10];
}
System.out.println(String.join(" ", result));
}
And here's a concise solution using Stream API:
public static void printDigits3(int num) {
String result = String.valueOf(num).chars()
.map(Character::getNumericValue)
.mapToObj(i -> DIGITS[i])
.collect(Collectors.joining(" "));
System.out.println(result);
}
main()
public static void main(String[] args) {
printDigits1(59);
System.out.println();
printDigits2(128);
printDigits3(789);
}
Output:
five nine
one two eight
seven eight nine
Upvotes: 0
Reputation:
you are getting an error here
a = Integer.valueOf(s);
it converts char to their respective Unicode value. Instead of this code, you can use the below function.
Character.getNumericValue();
Refer this link -> Char to Int
You can also do
String c=String.valueOf(s);
int foo = Integer.parseInt(c);
Refer -> How do I convert a String to an int in Java?
Upvotes: 1
Reputation: 1493
Here's the problem:
There are two Integer.valueOf() methods:
Integer.valueOf(int)
Integer.valueOf(String)
When you call valueOf on a character such as '5', the Integer.valueOf(int)
is called. The '5'
is casted to int which is 53 which is the ascii code for the character '5'
.
Your code:
for (int i=0; i<st.length(); i++){
s = st.charAt(i);
a = Integer.valueOf(s); <=== a is the ascii code
System.out.print(arr[a]+" "); <==will cause index out of bound.
}
Possible fixes:
for (int i=0; i<st.length(); i++){
s = st.charAt(i);
a = Integer.valueOf(s-'0');
System.out.print(arr[a]+" ");
}
Upvotes: 3
Reputation: 424973
Change:
a = Integer.valueOf(s);
To:
a = s - '0';
Subtracting '0'
returns the int value of a digit character.
Upvotes: 1
Reputation: 2660
This is the place your code is failing at:
a = Integer.valueOf(s);
Instead of converting '1'
to 1
as you were expecting, it converts '1'
into the ascii equivalent, 49.
To avoid this:
a = Character.getNumericValue(s);
This will convert '1'
to 1
, and so on.
Upvotes: 6