简体   繁体   中英

Java: Array Index Out of Bounds Exception 2

I'm writing a simple Java program that asks the user to input a string, and then counts and displays the number of times each letter in the alphabet appears in that string. When I compile, I get this error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -25
at StringLetters.countLetters(StringLetters.java:43)
at StringLetters.main(StringLetters.java:23)

I have looked at other solutions to problems similar to mine, but none of them helped. Does anyone have any ideas? Thank you.

    import java.util.Scanner;

    public class StringLetters
    { 
    public static void main(String[]args) 
    { 
        Scanner scan = new Scanner(System.in);
        System.out.println("Please enter a string of words.");
        String s = scan.nextLine();

        int[] counts = countLetters(s.toUpperCase());

        for(int i = 0; i < counts.length; i++)
        {
            if (counts[i] != 0) 
            {
                System.out.println((char)('a' + i) + " appears " + counts[i] + ((counts[i] == 1) ? "time" : " times"));
            }
        }
    }


    public static int[] countLetters(String s)
    {
        int[] counts = new int[26];

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

        return counts;
    }

}

Well, obviously the index in counts[s.charAt(i) - 'a'] gets above 25. It looks like you are assuming all your inputs would be lower case letters, even though you are passing to your countLetters method an upper case String ( countLetters(s.toUpperCase()); ).

You should probably change it to counts[s.charAt(i) - 'A'] . Of course, that would only work for capital letters, but that's what you are currently passing to this method.

In your argument String which you pass to the counting method, you have letters which are not lowercase English letters and that breaks your code.

In fact none of them are lowercase because you're calling s.toUpperCase() and it seems you meant to call s.toLowerCase() . Also, you need to filter out punctuation and any non-letter characters. You're already doing it here: if (Character.isLetter(s.charAt(i))) .

So just change s.toUpperCase() to s.toLowerCase() and you'll be fine.

First, your issue - how do you deal with capital letters?

Obviously in your use case you do countLetters(s.toUpperCase()) then you do - 'a' . This gives very odd results:

(int)'A' - (int)'a' = -25
(int)'Z' - (int)'a' = -7

An easier way to do this is using a Map . With Java 8:

    final Map<Character, Integer> counts = input.toUpperCase().chars().
            collect(HashMap::new, (m, l) -> m.merge((char) l, 1, Integer::sum), Map::putAll);

isLetter can return true in many case (have a look on its javadoc). In particular for uppercase character (peter>petrov is right, you probably don't want to convert to upper cases...)

I advice to implement a more basic test:

        Char c = s.charAt(i);
        if('a' <= c && c <= 'z')
        {
            counts[c - 'a']++;
        }
        else if('A' <= c && c <= 'Z')
        {
            counts[c - 'A']++;
        }

How do you account for capital letters? Seems like a good use for HashMap. Capital letters have a lower ASCII value than lower case letters. It looks like your index out of bounds is caused by a capital letter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM