Почему неправильно работает конечный автомат?

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

import java.util.ArrayList;
import java.util.List;

public class WordCounterMachine {
  private State state = State.OUTSIDE;
  List<String> words = new ArrayList();
  
  public void count(String line) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < line.length(); i++) {
      char c = line.charAt(i);
      switch (state) {
        case OUTSIDE:
          if (c != ' ' || c != '\n') state = State.INSIDE;
          break;
        case INSIDE:
          if (c != ' ' || c != '\n') sb.append(c);
          else {
            words.add(sb.toString());
            sb.setLength(0);
            state = State.OUTSIDE;
          }
          break;
      }
    }
  }
  
  static enum State {
    INSIDE, OUTSIDE
  }
}
import com.example.WordCounterMachine;
import java.util.Scanner;

public class Main {

  public static void main(String[] args) {
    Scanner scn = new Scanner(System.in);
    String ln = scn.nextLine();
    WordCounterMachine wc = new WordCounterMachine();
    wc.count(ln);
    System.out.println(wc.words.size());
  }
}

Ответы (1 шт):

Автор решения: Stanislav Volodarskiy
  1. Ошибка в условии c != ' ' || c != '\n' - оно всегда истинно. Должно быть c != ' ' && c != '\n'.

  2. Первые буквы слов теряются. Как только вы переключаетесь в состояние INSIDE следует записать букву.

  3. Последнее слово теряется. После конца цикла его надо добавить.

  4. new ArrayList() - так делать не надо. new ArrayList<String>() или new ArrayList<>().

Ваш код в одном файле, ошибки исправлены, добавлена печать слов:

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

class WordCounterMachine {
  private State state = State.OUTSIDE;
  List<String> words = new ArrayList<String>();
  
  public void count(String line) {
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < line.length(); i++) {
      char c = line.charAt(i);
      switch (state) {
        case OUTSIDE:
          if (c != ' ' && c != '\n') {
            state = State.INSIDE;
            sb.append(c); 
          }
          break;
        case INSIDE:
          if (c != ' ' && c != '\n') sb.append(c);
          else {
            words.add(sb.toString());
            sb.setLength(0);
            state = State.OUTSIDE;
          }
          break;
      }
    }
    if (sb.length() > 0) {
        words.add(sb.toString());
    }
  }
  
  static enum State {
    INSIDE, OUTSIDE
  }
}

public class Temp {
  public static void main(String[] args) {
    Scanner scn = new Scanner(System.in);
    String ln = scn.nextLine();
    WordCounterMachine wc = new WordCounterMachine();
    wc.count(ln);
    System.out.println(wc.words.size());
    for (String w : wc.words) {
      System.out.println(w);
    }
  }
}

P.S. Проверку на непробел лучше делать так !Character.isSpace(c).

P.P.S. Гоняйте программу по шагам в отладчике. Многие вещи сразу становятся видны.

→ Ссылка