【问题标题】:Why do we use string.charAt(index)-'a' in java?为什么我们在 java 中使用 string.charAt(index)-'a'?
【发布时间】:2019-02-06 21:13:07
【问题描述】:
public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    String s = br.readLine();
    int[] arr = new int[26];
    for(int i=0;i<s.length();i++)
        arr[s.charAt(i)-'a']++;
    
    int odds = 0;
    for(int i=0;i<26;i++)
        if(arr[i]%2!=0)
            odds++;
    
    if(odds%2==1 || odds==0)
        System.out.println("First");
    else
        System.out.println("Second");

}

我看到了这段代码,发现这部分令人困惑。那么你能告诉我我们为什么要使用它吗?'a'arr[s.charAt(i)-'a']++; 中的意义是什么?

【问题讨论】:

  • 'a'char 文字。 char 是一个整数类型,因此使用 char 的算术定义明确并产生一个整数结果。
  • @JohnBollinger 但这没有任何意义,除非您了解 ASCII/Unicode 并且所有小写字母都是连续的。
  • @JohnBollinger 先生,能否请您详细说明这个 'a' 的用法,我没看懂。
  • 是的。 'a' 对应于 java 中的整数 97。因此,当您调用 charAt(i) 并从中减去整数 97 时,您实际上只是在取整数。字符的整数值有据可查。

标签: java arrays character non-ascii-characters


【解决方案1】:

此代码为字母表中的每个字母创建一个类似于直方图的计数器。尝试打印一个字符,例如'a',如下所示:

System.out.println((int)'a'); // Output: 97

每个char 都有一个对应的 Unicode 值,介于 0 和 65,535 之间。减去'a'(或97)会将字母表中的每个字母缩放到与arr 数组中的“桶”相对应的0-26 范围内。这是一个例子:

System.out.println('z' - 'a'); // Output: 25 (the last bucket in the array)
System.out.println('a' - 'a'); // Output: 0 (the first bucket in the array)

代码中的第二个循环检查每个计数的奇偶性以确定哪些是奇数。最后,最后的打印条件检查是否出现奇数个字母的总数。如果这个总数是0 或本身是奇数,则打印"First",否则打印"Second"

使用az 之外的任何字符或大写字母尝试此代码。它会崩溃,因为字符的 ASCII 表示超出了数组的大小,您最终会得到 IndexOutOfBoundsException

这是一个示例程序,展示了如何构建直方图并通过加法将其输出转换回字母:

class Main {
    public static void main(String[] args) {
        String s = "snuffleupagus";
        int[] arr = new int[26];

        for (int i = 0; i < s.length(); i++) {
            arr[s.charAt(i)-'a']++;
        }

        for (int i = 0; i < arr.length; i++) {
            System.out.println((char)(i + 'a') + ": " + arr[i]);
        }
    }
}

输出:

a: 1
b: 0
c: 0
d: 0
e: 1
f: 2
g: 1
h: 0
i: 0
j: 0
k: 0
l: 1
m: 0
n: 1
o: 0
p: 1
q: 0
r: 0
s: 2
t: 0
u: 3
v: 0
w: 0
x: 0
y: 0
z: 0

【讨论】:

  • 关于编码的小修正。 ASCII 在 0-127 范围内并在 ASCII 0-255 中扩展。关键是 char 是 unicode 标准,而不是 ascii。
  • 谢谢,我觉得这个答案让我失望了:stackoverflow.com/questions/21208308/…
  • Java 的 Stringchar 与 ASCII 或任何未指定为“扩展 ASCII”的字符集无关。
  • 非常感谢您的回答。
【解决方案2】:

arr 由一个大小为 26 的 int 数组组成,这也是英文字母表中的字母数。该循环所做的只是计算字母的频率,通过它们在字母表中的索引表示,arr[0]'a'arr[1]'b',等等。

它的技术细节可以简单地解释。 s.charAt(i) 在指定位置 i 返回一个 char 实例。 char 在 Java 中也可以表示为一个字节。然后减法从i 处的当前字符中获取 'a' 的 ASCII 值(表示为byte)。所以你最终得到的是'a' - 'a' == 0'b' - 'a' == 1等等。

请注意,这可能不是计算字符数的最佳方法,因为字符串可以包含的不仅仅是小写字母,例如大写字母和更多符号。

【讨论】:

  • 非常感谢,先生,您的回答。
  • 欢迎来到 StackOverflow :)
猜你喜欢
  • 2017-10-13
  • 2010-10-28
  • 2018-12-08
  • 2011-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-23
  • 1970-01-01
相关资源
最近更新 更多