数组索引越界错误,即使索引在数组长度范围内



我试图编写一个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()方法:

  1. Integer.valueOf(int)

  2. 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.
}

可能的修复:

  1. 计算字符的数字(首选)。例如:'5' - '0' = 5.
  2. 将字符转换为字符串。
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

在线演示的链接

相关内容

  • 没有找到相关文章

最新更新