Почему я получаю java.lang.Ошибка StringIndexOutOfBoundsException при запуске?

#java #string #exception #indexoutofboundsexception

#java #строка #исключение #исключение indexoutofboundsexception

Вопрос:

Я изучаю Java, и у нас есть проект по созданию программы, переводящей текст в ASCII и обратно.

Мой основной метод до сих пор

     public static void main(String[] args) {
        Scanner s = new Scanner(System.in);
        char decisionOne;
        System.out.println("Are we making a new message or decrypting an old one?");
        decisionOne = s.nextLine().charAt(0);
        switch(decisionOne) {
        case 'd':
            decrypt();
            System.exit(0);
            break;
        case 'D':
            decrypt();
            System.exit(0);
            break;
        case 'E':
            encrypt();
            System.exit(0);
            break;
        case 'e':
            encrypt();
            System.exit(0);
            break;
        }
        while (!(decisionOne == 'd') amp;amp; !(decisionOne == 'D') amp;amp; !(decisionOne == 'e') amp;amp; !(decisionOne == 'E')) {
            System.out.println("Hey! Choose one of them.");
            decisionOne = s.nextLine().charAt(0);
            switch(decisionOne) {
            case 'd':
                decrypt();
                System.exit(0);
                break;
            case 'D':
                decrypt();
                System.exit(0);
                break;
            case 'E':
                encrypt();
                System.exit(0);
                break;
            case 'e':
                encrypt();
                System.exit(0);
                break;
            }
        }
        

    }

 

и мой метод шифрования в ASCII

         Scanner s = new Scanner(System.in);
        System.out.println("What is your message?");
        String message = s.nextLine();
        char m;
        int length = message.length();
        int tracker = 0;
        int ascii;
        while (length >= 0 ) {
            
            m = message.charAt(tracker);
            length--;
            ascii = (int)m;
            System.out.print(ascii   " ");
            tracker   ;
        }
        
    }
 

Я просмотрел другие вопросы, но ни один из них, похоже, не отвечает на то, что здесь происходит. При запуске я получаю правильный вывод, поэтому, если я ввел

11

Я бы получил

49 49 Исключение в потоке «main» java.lang.StringIndexOutOfBoundsException: строковый индекс вне диапазона: 2

Что я могу сделать, чтобы исправить это?

Комментарии:

1. Вы узнали об отладчике Java? Или модульные тесты?

2. Метод string#length() возвращает буквальное числовое значение. Если вы собираетесь использовать его значение для методов, для которых требуется значение индекса, такое как String#charAt(), тогда используйте: int length = message.length() - 1;

Ответ №1:

Измените свой код в методе encrypt с while(length >= 0) на while(length - 1 >= 0) . Также закройте объект scanner после его использования, поскольку это приведет к утечке памяти.

Метод length() возвращает длину строки, например String message = "Hello"; length = message.length(); , длина будет равна 5. Но при использовании его в цикле while вы должны использовать message .length() — 1, потому что в Java индексация начинается с 0, а не с 1.

Я переработал ваш метод encypt и метод main, а также я чувствую, что нет необходимости использовать операторы switch. Замените их операторами if else, чтобы уменьшить избыточный код.

Если вы считаете это решение полезным, пожалуйста, поддержите решение, спасибо.

 public static void encrypt() {
        Scanner s = new Scanner(System.in);
            System.out.println("What is your message?");
            String message = s.nextLine();
            char m;
            int length = message.length();
            int tracker = 0;
            int ascii;
            while (length - 1 >= 0 ) {
                
                m = message.charAt(tracker);
                length--;
                ascii = (int)m;
                System.out.print(ascii   " ");
                tracker  ;
            }
            s.close();
        }

public static void main(String[] args) {
            Scanner s = new Scanner(System.in);
            char decisionOne;
            System.out.println("Are we making a new message [e (or) E] or decrypting an old one [d (or) D] ?");
            decisionOne = s.nextLine().charAt(0);
            if (decisionOne == 'd' || decisionOne == 'D') {
                decrypt();
                System.exit(0);
            }
            else if (decisionOne == 'e' || decisionOne == 'E') {
                encrypt();
                System.exit(0);
            }

            while (!(decisionOne == 'd') amp;amp; !(decisionOne == 'D') amp;amp; !(decisionOne == 'e') amp;amp; !(decisionOne == 'E')) {
                System.out.println("Hey! Choose one of them.");
                decisionOne = s.nextLine().charAt(0);
                if (decisionOne == 'd' || decisionOne == 'D') {
                    decrypt();
                    System.exit(0);
                }
                else if (decisionOne == 'e' || decisionOne == 'E') {
                    encrypt();
                    System.exit(0);
                }
            }
            s.close();
        }
 

Комментарии:

1. Входной поток будет закрыт после вызова encrypt , поэтому не будет необходимости снова закрывать его из основного метода. Почему бы просто не передать сканер в качестве параметра?

2. Да. Это сделало бы это, я не думал об этом. Я только что отладил ошибки, которые были запрошены. В любом случае этот код может быть переработан дальше.

3. Какие могут быть другие способы реорганизовать это?

Ответ №2:

Я вставил это в ваш метод шифрования и..

 m = message.charAt(tracker);
        System.out.print(length   " ");
        length--;
        ascii = (int)m;
        System.out.print(ascii   " ");
        tracker   ;
        System.out.print(length   " " tracker " ");
 

результат, который я получил, это thisss…

2 49 1 1 1 49 0 2

вы видите ваш tracker=2 в последнем, который не привязан к вашей строке сообщения, поэтому вы получаете исключение, либо вы можете обработать исключение, либо улучшить свой код… личный опыт — используйте цикл for, если вы новичок, это даст вам больше ясности в том, как работает код

Ответ №3:

Вы хотите while (length > 0) или while (tracker < length)

Или вы можете просто сделать for (Character m: message.toCharArray()) и отказаться от метода length, tracker и charAt