2009-11-28 128 views
1

我有一个Java问题:我正在编写一个程序来读取一个字符串并显示该字符串中的字符数。我找到了一些示例代码,但我不太了解最后一部分 - 任何人都可以帮忙吗?显示字符串中的字符数

int[] count = countLetters(line.toLowerCase()); 

for (int i=0; i<count.length; i++) 
{ 
    if ((i + 1) % 10 == 0) 
      System.out.println((char) ('a' + i)+ " " + count[i]); 
    else 
     System.out.print((char) ('a' + i)+ " " + count[i]+ " "); 
} 

public static int[] countLetters(String line) 
{ 
    int[] count = new int[26]; 

    for (int i = 0; i<line.length(); i++) 
    { 
     if (Character.isLetter(line.charAt(i))) 
      count[(int)(line.charAt(i) - 'a')]++; 
    } 

    return count; 
} 
+0

除非您有严格的要求和严格的输入检查,否则只要您输入大量字母,数字,非US-ASCII字母,空格等各种字符,此代码就会中断...基本上任何不在“a”和“z”。 – Bombe 2009-11-28 20:08:27

回答

2

你的最后一个循环是:

对于每一个我们测试它是否是一个字母,如果是,我们增加相对于字符计数器字符。这意味着'a'是0,'b'是1 ...(换句话说,'a'是'a' - 'a'是0,'b'是'b' - 'a',它是1 ...)。

这是计算字符串中字符出现次数的常用方法。

1

您发布的代码不是计算字符串的长度,而是计算出小写字符串中出现的字母的数量。

Character.isLetter(line.charAt(i)) 

检索到的字符在i位置,并返回true如果它是一个字母。

count[(int)(line.charAt(i) - 'a')]++; 

在指数character - 'a'加计数,这是026

函数的结果是一个包含每个字母计数的26个整数的数组。

for循环在计数阵列结束打印输出每第10个计数,并使用

(char) ('a' + i) 

来打印计数属于信。

0

我猜你正在计算字母的出现次数,而不是字符('5'也是一个字符)。

最后一部分:

for (int i = 0; i<line.length(); i++) 
{ 
    if (Character.isLetter(line.charAt(i))) 
     count[(int)(line.charAt(i) - 'a')]++; 
} 

它遍历每个字符的输入线和检查它是否是一个字母。如果是,则增加该信件的计数。计数保存在一个由26个整数组成的数组中(对于拉丁字母表中的26个字母)。字母'a'的计数保持在索引0处,字母'b'在1处,'z'在25处。为了得到索引,代码从字母值中减去值'a'(每个字符不仅是字符/字形,也是数字值)。所以如果这个字母是'a',它就会减去'a'的值,它应该是0等等。

0

在方法countLetters中,for循环遍历该行中的所有字符。 if检查以确保它是一个字母,否则将被忽略。

line.charAt()在位置i产生单个字符。这种类型是char

现在深入Java内部,char只是一个对应于字符代码的数字。小写'a'的字符代码为97,'b'为98,依此类推。 (int)强制从char转换为int。所以我们取字符代码,假设它是一个'b',所以代码是98,我们减去'a'的代码,即97,所以我们得到偏移量1(从字母表开始)。对于字母表中的任何字母,偏移量将介于0和25(含)之间。

因此,我们使用该偏移量作为索引进入数组count并使用++来增加它。然后,程序顶部的循环可以打印出计数。

顶部的循环使用反向“技巧”将这些从0到25的偏移量转换回从a到z的字母。

0

'最后部分',循环的实现真的很难理解。关闭混淆;)这里的计数方法的重构(一分为二的方法,一般一个为所有字符,并就只是小型大写字母特殊:

public static int[] countAllASCII(String line) { 
    int[] count = new int[256]; 
    char[] chars = line.toCharArray(); 

    for (char c : chars) { 
    int index = (int) c; 
    if (index < 256) { 
     count[index]++; 
    } 
    } 

    return count; 
} 

public static int[] countLetters(String line) { 
    int[] countAll = countAll(line);   
    int[] result = new int[26];  
    System.arraycopy(countAll, (int) 'a', result, 0, 26); 

    return result; 
} 

总体思路:在countAll方法只是计数所有的字符。是的,数组更大,但是在这些维度中,没有人关心今天优点:我不必测试每个char。第二种方法只是将感兴趣的区域复制到新的(结果)数组中并返回它。

编辑

我已经改变了我的代码少解除好友关系以及评论。无论如何,谢谢Bombe。

+0

使用非US-ASCII字符将会失败。欢迎在1996年。哦,等等,这是2009年,你仍然认为一个字符只有8位宽...... – Bombe 2009-11-28 20:05:05