Анализ строки символов для (ABC) ^n с использованием стеков

#java #string

#java #строка

Вопрос:

У меня есть строка символов с As, Bs и Cs, которые мне нужно проанализировать для языка (ABC) ^ n, где n> 0. Если эта строка «ABCABCABC», это правда, если это «ABAB» или «AB», это не правда. Я продолжаю получать строковый индекс сообщения об ошибке за пределы, когда он считывает строку «AB», а затем останавливает программу. Вот код, который у меня есть:

 public boolean isABC(String line) throws StackException{
    MyStack Stack = new MyStack();

    // initialize loop counters
    int i = 0;
    int n = line.length();
    char ch = line.charAt(i);

    // Push all 'A's to L6Stack 
    while (i < line.length()){
        if(line.charAt(i) == 'A'){
            L6Stack.push(ch);
            i  ;
            if(line.charAt(i)=='B'){
                L6Stack.push(ch);
                i  ;
                if(line.charAt(i) =='C'){
                    L6Stack.push(ch);
                    i  ;
                }else
                    break;
            }else
                break;
        }else
            break;
    }
    if (i == n ){
        return true; 
    }else
        return false;
}
  

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

1. По какой-либо причине вы не используете регулярное выражение?

2. Да, регулярное выражение будет хорошим вариантом для решения таких проблем ……..Почему бы вам не использовать его????

3. Что произойдет, если первый символ не равен A?

4. Вы должны научиться отлаживать свой код. Есть несколько ошибок. Первый — получить доступ line.charAt(i) перед переходом в цикл while. Символа может вообще не быть, и переменная может даже быть null . Второй — всегда читать фрагменты из трех символов, не проверяя, достаточно ли длинная строка; таким образом, IOOBE.

5. если вы передали AB сначала A, так что это будет делать i , второй B, так что это будет делать i далее, вы все еще ничего не пытаетесь прочитать charAt (i) для C, поэтому индексируйте из связанного исполнения

Ответ №1:

Ваш код пытается продвинуть 3 символа, прежде чем проверять, может ли он сделать это, не выходя за рамки. Вы можете исправить это, заменив все i на if (i==n) return false; i . Однако вы также можете переписать все это, чтобы быть намного чище:

Попробуйте это:

 public boolean isABC(String line) {
  int total = line.length();
  int position = 0;
  char prev = 'C';
  while (position < total) {
      char c = line.get(position  );
      switch (c) {
          case 'A': if (prev != 'C') return false; break;
          case 'B': if (prev != 'A') return false; break;
          case 'C': if (prev != 'B') return false; break;
      }
      prev = c;
  }
  return prev == 'C';
}
  

Вы также могли бы добавить их все в стек, а затем pop() в стек (так char c = stack.pop() , изменив логику), но это действительно не обязательно для этого конкретного выражения.


Редактировать: добавлен вариант на основе стека:

 public boolean isABC(String line) {
  // fill stack
  Stack<Character> stack = new Stack<Character>();
  for (int i=0; i<line.length(); i  ) {
      stack.push(line[i]);
  }

  // reverse operations while popping from stack
  char prev = 'A';
  while ( ! stack.isEmpty()) {
      char c = stack.pop();
      switch (c) {
          case 'A': if (prev != 'B') return false; break;
          case 'B': if (prev != 'C') return false; break;
          case 'C': if (prev != 'A') return false; break;
      }
      prev = c;
  }
  return prev == 'A';
}
  

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

1. Мы должны использовать стеки, вот почему. 🙁

2. Добавлен вариант на основе стека. По сути, это то же самое, но теперь вы смотрите на символы, начинающиеся с конца, а не с начала. Первый цикл используется для заполнения стека.

3. Хорошо, это имеет больше смысла. Спасибо!

Ответ №2:

Если длина строки равна двум («AB»), то когда вы доберетесь до

 if(line.charAt(i) =='C')
  

значение i будет 2 . Строка длиной два содержит символы только в позициях 0 и 1 . Если вы используете charAt(2) , вы пытаетесь прочитать дальше конца строки, что приводит к исключению.

Прямо сейчас вы получите сообщение об ошибке всякий раз, когда длина входной строки не кратна 3 символам.

Ответ №3:

Я не собираюсь исправлять вашу логику, но я попытаюсь объяснить, почему вы получаете исключение SIOOB. Смотрите встроенные комментарии.

Допустим, строка = «AB»; так length = 2 и i = 0

 while (i < line.length()){//this condition returns true.
        if(line.charAt(i) == 'A'){// you are trying to access 0th Element.
            L6Stack.push(ch);
            i  ;// i is 1 now.
            if(line.charAt(i)=='B'){// trying to access 1st element.
                L6Stack.push(ch);
                i  ;//i is 2 now.
                if(line.charAt(i) =='C'){// trying to access 2st element. which would give you exception because there is no 2nd element.
                    L6Stack.push(ch);
                    i  ;
                }else
                    break;
            }else
                break;
        }else
            break;
    }