我试图编写一个java程序,其中输入整数的每一位数字都以单词的形式打印出来。
例如:输入123
应该产生输出"one two three"
。
我编写了下面的程序,它接受一个整数值,然后将其转换为字符串。然后遍历字符串中的字符并将其转换为整数值,稍后将其用作数组的索引。
但我得到ArrayIndexOutOfBoundsException
。
Index 49 out of bounds for length 10
我的代码:
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);
}
}
这是你的代码失败的地方:
a = Integer.valueOf(s);
它没有将'1'
转换为1
,而是将'1'
转换为等效的ascii 49。
要避免这种情况:
a = Character.getNumericValue(s);
这将把'1'
转换为1
,以此类推。
问题来了:
有两个Integer.valueOf()方法:
-
Integer.valueOf(int)
-
Integer.valueOf(String)
当您在字符上调用valueOf时,例如'5',将调用Integer.valueOf(int)
。'5'
被强制转换为int,即53,这是字符'5'
的ascii码。
代码:
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.
}
可能的修复:
- 计算字符的数字(首选)。例如:'5' - '0' = 5.
- 将字符转换为字符串。
for (int i=0; i<st.length(); i++){
s = st.charAt(i);
a = Integer.valueOf(s-'0');
System.out.print(arr[a]+" ");
}
变化:
a = Integer.valueOf(s);
:
a = s - '0';
减去'0'
返回数字字符的int值。
这里出现错误
a = Integer.valueOf(s);
将char转换为它们各自的Unicode值。您可以使用下面的函数来代替这段代码:
Character.getNumericValue();
参考此链接->Char to Int
你也可以做
String c=String.valueOf(s);
int foo = Integer.parseInt(c);
引用→如何在Java中将字符串转换为int ?
首先,了解Java中的基本数据类型。
如果你的背景是JavaScript,它没有char
类型,你可能一直认为char
是一种"字符串,但它是而不是.
char
-是一个16位数字基本数据类型,其最小值为'u0000'(或0
),最大值为'uffff'(或65,535
),用于表示unicode字符。但是在Java的早期,Unicode标准已经改变了,char
类型似乎被破坏了,为了修复这个代码点,在语言中引入了代码点。
在此语句中,a = Integer.valueOf(s);
字符s
被提升为int
类型,方法valueOf()
创建了一个不必要的Integer
实例,该实例立即被丢弃,并且您最终得到a
的值范围从48
(0
)到57
(9
),该值大于数组的长度。因此,您将得到一个合理的ArrayIndexOutOfBoundsException
。
还有一些问题。
编译器不会抱怨你为每个方法调用创建一个新的数组,但这种方法是错误的,字符串数组应该是static
,即它应该驻留在类级别:
public static final String[] DIGITS = {"zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
另一个看似不重要的重要问题是,您使用的名称既不具有信息性(如arr
),又违反了Java命名约定(如Print_Digits
)。
同样,数组声明String arr[]
的c风格是而不是在Java中被认为是一个很好的实践,因为它混合了数据类型和变量名。
这是这个问题的解决方案。
第一个有点接近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 + " ");
}
}
我们也可以完全不使用字符串来解决这个问题:
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));
}
这里有一个使用流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);
}
输出:
five nine
one two eight
seven eight nine
在线演示的链接