Как посчитать слова в Java без регулярных выражений?

Рейтинг: 2Ответов: 3Опубликовано: 22.07.2023

Подскажите пожалуйста, как посчитать слова в строке в Java?

Как я понимаю, программа должна считывать символы в цикле for, потом доходить до пробела и считать его как окончание слова. Но как тогда посчитать последнее слово?

Слова надо считывать с помощью метода .length, так? Но как тогда "объяснить в коде", что пробел это уже другое слово и у него своя длина?

И по условию мне нужно не просто считать слова, но ещё и пронумеровать их и вывести в строку, и как это сделать в System.out.print(); я пока что тоже не могу понять.

Могу представить, как отдельно вывести строку и количество слов, но как их "перемешать" я совершенно не понимаю.

Ответы

▲ 3Принят

Метод String::indexOf ищет только некоторый заранее определённый символ, а не символы определённого класса.
Например, ко множеству пробельных символов относится не только пробел ' ', но и масса других:

  • горизонтальные пробельные символы: [ \t\xA0\u1680\u180e\u2000-\u200a\u202f\u205f\u3000]
  • вертикальные пробельные символы: [\n\x0B\f\r\x85\u2028\u2029]

Поэтому использовать String::indexOf имеет смысл только для некоторых входных строк, для которых заранее известно, что все слова разделены только пробелами.

В целом же основной алгоритм поиска слов (или их количества) без привлечения "тяжёлых" способов типа регулярных выражений / Stream API может выглядеть так:

  • инициализировать счётчик слов или список найденных слов, создать буфер для "накопления" слова
  • сделать внешний цикл for с переменными для текущего индекса символа в строке и количества символов входной строки str, соответственно, обращаясь к символам строки при помощи String::charAt(int index) (или более "продвинутые" юникодовские кодовые точки String::codePointAt(int index))
  • в первом вложенном цикле "пропустить" все символы, НЕ относящиеся к словам, например, при помощи метода Character.isAlphabetic или Character.isLetterOrDigit и логического отрицания ! или же используя Character.isWhitespace
  • очистить буфер
  • в следующем вложенном цикле добавить в буфер все символы, относящиеся к словам при помощи соответствующего метода Character.isAlphabetic или Character.isLetterOrDigit и т.п.
  • после окончания второго вложенного цикла, если буфер непустой, инкрементировать счётчик слов, вывести текущее слово при необходимости или добавить найденное слово в список-результат
  • по окончании внешнего цикла вывести/вернуть итоговый результат

В обоих вложенных циклах следует проверять условия выхода за границы строки.


Реализация вышеописанного алгоритма достаточно тривиальна и соответствующий код НЕ приводится намеренно.


Пример поиска слов в строке при помощи класса Scanner:

public static List<String> getWordsSc(String str) {
    Scanner sc = new Scanner(str);
    List<String> result = new ArrayList<>();
    while (sc.hasNext()) {
        result.add(sc.next());
    }
    
    return result;
}    

Однако по умолчанию сканер будет разделять строку только по пробельным символам, то есть при наличии знаков пунктуации они будут "входить" в слова.

▲ 0

Не все понятно из вопроса, исхожу из того, что у Вас есть строка, вы ее видите и нужно посчитать слова (вообще вариантов это сделать много, можно и стримы использовать, но так как Вы начинающий разработчик, предлагаю способ, который проще для понимания):

//Ваша строка
String s = "Вместе весело шагать по просторам\n" +
            "По просторам, по просторам\n" +
            "И, конечно, напевать лучше хором\n" +
            "Лучше хором, лучше хором";
//убираем из строки знак переноса строки и запятые
String onlyWord = s.replace(",","").replace("\n"," ");
//делим строку на слова по пробелу и записываем их в массив
String [] arrWord = onlyWord.split(" ");
//размер массива равен количеству слов, выводим соответствующее сообщение
System.out.println("В строке " + arrWord.length + " слов(а)");
//в цикле выводим все слова под их порядковыми номерами
for (int i = 0; i < arrWord.length; i++) {
System.out.print("Слово №" + (i+1) + ": " + arrWord[i]+", ");
}

У меня получился такой результат

В строке 18 слов(а)
Слово №1: Вместе, Слово №2: весело, Слово №3: шагать, Слово №4: по, Слово №5: просторам, Слово №6: По, Слово №7: просторам, Слово №8: по, Слово №9: просторам, Слово №10: И, Слово №11: конечно, Слово №12: напевать, Слово №13: лучше, Слово №14: хором, Слово №15: Лучше, Слово №16: хором, Слово №17: лучше, Слово №18: хором, 

По поводу того, что вы не проходили метод split: в классе String не менее 50 методов, split один из них. Не думаю, что вы проходили бы все 50 методов. Вероятнее всего Вам дали домашнее задание с тем уклоном, чтобы Вы самостоятельно ознакомились с методами класса, которые не разбирали на занятии.

▲ 0

Пример со split не совсем корректен, так как не учитывает все разделители и несколько разделителей подряд, зачем-то меняет переносы строк на пробелы.

split может принимать в себя регулярное выражение и мы можем написать просто

s.split("\\s+").length