Программа подсчета слов

Последнее обновление: 02.03.2023

В качестве практики работы со строками напишем небольшую программу для подсчета слов.

#include <iostream>
#include <vector>
#include <string>

int main()
{
    std::string text; // Исходный текст
    std::cout << "Enter some text: ";
    std::getline(std::cin, text);
    const std::string separators{ " ,;:.\"!?'*\n" }; // разделители слов
    std::vector<std::string> words; // вектор для хранения слов
    size_t start { text.find_first_not_of(separators) }; // начальный индекс первого слова
    while (start != std::string::npos) // проходим, пока в строке не окажется других символов, кроме separators
    {
        size_t end = text.find_first_of(separators, start + 1); // находим, где кончается слово
        if (end == std::string::npos) // если НЕ найден ни один из символов-разделителей
            end = text.length();        // устанавливаем переменную end на конец текста
        words.push_back(text.substr(start, end - start)); // добавляем в вектор слово
        start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start
    }
    // выводим количество слов
    std::cout << "\nText contains " << words.size() << " words:" << std::endl;
    // выводим все слова на консоль
    for (const auto& word : words)
    {
        std::cout << word << std::endl;
    }
}

Вначале определяется переменная text, которая будет содержать введенную с консоли строку:

std::string text; // Исходный текст
std::cout >> "Enter some text: ";
std::getline(std::cin, text);

Определяем строку разделителей, такие как знаки пунктуации, пробелы, символ перевода строки, которые не являются словами:

const std::string separators{ " ,;:.\"!?'*\n" }; // разделители слов

Стоит отметить, что символ перевода строки здесь определен больше для демонстрации, поскольку при вводе выше через std::getline ввода строки будет завершен, когда мы нажмем на Enter. Соответственно введенная строка никогда не будет содержать символ \n. Однако если мы изменим символ, до которого идет ввод строки через std::getline, или в качестве источника ввода будет использовать, например, текст из файла, тогда символ перевода строки тоже будет играть определенную роль.

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

std::vector<std::string> words; // вектор для хранения слов

Перед обработкой введенного текста фиксируем индекс первого символа первого слова в тексте. Для этого применяется функция find_first_not_of(), которая возвращает первый индекс любого символа, который не входит в строку separators:

size_t start { text.find_first_not_of(separators) }; // начальный индекс первого слова

Далее в цикле while смотрим, является ли полученный индекс действительным индексом:

while (start != std::string::npos)

Например, если в строке одни только символы из набора separators, тогда функция find_first_not_of() возвратит значение std::string::npos, что будет означать, что в тексте больше нет непунктационных знаков.

И если start указывает на действительный индекс начала слова, то находим индекс после последнего символа слова, который помещаем в переменную end:

size_t end = text.find_first_of(separators, start + 1); // находим, где закончилось слово

Для нахождения позиции окончания слова используем функцию find_first_of(), которая возвращает первую позицию любого символа из separators, начиная с индекса start+1

Причем может быть, что функция find_first_of() не найдет ни одного символа из separators (например, слово является поседним в тексте, и после него нет никаких знаков пунктуации или пробелов), в этом случае конечный индекс равен длине текста.

if (end == std::string::npos) // если НЕ найден ни один из символов-разделителей
    end = text.length();        // устанавливаем переменную end на конец текста

После того, как мы нашли начальный индексы слова и его конец, то с помощью функци substr() получаем подстроку между этими индексами, добавляем слово в вектор, переустанавливаем start на начальный индекс следующего слова и повторяем действия цикла:

words.push_back(text.substr(start, end - start)); // добавляем в вектор слово
start = text.find_first_not_of(separators, end + 1); // находим начальный индекс следующего слова и переустанавливаем start

В конце выводим количество найденных слов и сами слова.

Пример работы программы:

Enter some text: When in Rome, do as the Romans do.

Text contains 8 words:
When
in
Rome
do
as
the
Romans
do
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850