Как в строке определить количество слов длины k без использования циклов?

352
05 декабря 2017, 21:32

Дана строка, где слова разделены пробелами и двоеточиями. Нужно посчитать количество слов длиной меньше k и вернуть контейнер этих слов. Циклами пользоваться запрещено, разрешены только STL алгоритмы и контейнеры. Нет даже представления, как это всё можно сделать. Мне бы хотя бы идею.

Answer 1

Вот поиск символьной комбинации в стандартном потоке ввода, не через циклы while, а с использованием предиката и алгоритма std::find_if. Предлагаю такой вариант решения:

std::find_if(std::istream_iterator<std::string>(std::cin),
             std::istream_iterator<std::string>(),
             Predicate());

где Predicate() вызов конструктора класса Predicate с определенным оператором ().

Предикат Вы можете реализовать для проверки того, является ли считанный объект словом, а не двоеточием (хотя из вопроса не до конца ясно, как именно разделены слова, приведите конкретный пример), и, если является словом, то проверить его длину. Смотрите класс string и функцию-член length(), например.

Пример реализации класса Predicate:

// глобальными эти переменные не стоит делать, хотя бы в namespace надо их засунуть
std::uint64_t counter = 0;            // счетчик всех слов в вводимом тексте
std::map<std::string, int> container; // ключ - слово, значение - кол-во копий
class Predicate
{
    Predicate() {}
    void operator()(const std::string & str) // предполагается ввод word : word : word и т.д.
    {
        if (str != “:” && str.length() < k)
        {
            ++counter;
            ++container[str];
        }
    }
};

Еще дам пример использования std::istream_iterator. Считывание данных с итератором:

if (iit != eos) str = *iit;
++iit;

где iit - это std::istream_iterator<string>, а eos - итератор того же типа, означающий конец ввода. Вы легко сможете найти в интеренете информацию по использованным в моем ответе возможностям C++, см. этот сайт и этот сайт.

Answer 2

Первое, что приходит в голову по вашей задаче:

#include <iostream>
#include <algorithm>
#include <string>
#include <list>
std::list<std::string> result;
std::string str;
int size = /*Необходимая длина*/
struct Func 
{
    Func() {}
    void operator()(char & letter) 
    {
        if (!str.empty())
        {
            if (letter == ':' || letter == ' ')
            {
                size_t pos = str.find_first_of(":");
                std::string temp = str.substr(0, pos);
                if (temp.length() < size) { result.push_back(temp); }
                str.erase(0, pos + 1);
            }
            else if (str.find_first_of(":") == std::string::npos)
            {
                std::string temp = str.substr(0, str.length());
                if (temp.length() < size) { result.push_back(temp); }
                str.clear();
            }
        }
    }
};
int main()
{
    std::getline(std::cin, str);
    std::for_each(str.begin(), str.end(), Func());
    /*Далее работа с контейнером result*/
}
Answer 3

Вот такой кусок кода вызовет объект f со всеми словами из строки s

std::for_each(std::istream_iterator<std::string>(std::istringstream(s)), std::istream_iterator<std::string>(), f);

Проблемы две: 1. Слова выделяются по стандартным пробельным символам, поэтому проще всего перед вызовом заменить в строке двоеточия на пробелы. 2. f не просто функция, а должна "куда-то" вернуть контейнер и количество, поэтому придется сделать класс, инициализирующийся ссылкой на контейнер, с членом operator ()( std::string &s), который проверит длину строки и пополнит контейнер.

Answer 4

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

READ ALSO
Приведение типа

Приведение типа

В чем отличие этих двух способов приведения?

273
Сформировать строку для cURL из аргументов

Сформировать строку для cURL из аргументов

Строка для curl -> char* Делаю так:

220
Создание процесса

Создание процесса

Под Windows есть функция создания нового процесса CreateProcess которая создает процесс в новом окне, и в нее можно передать флаг CREATE_NO_WINDOW, что бы это...

211
QLineEdit. Ввод с виртуальной клавиатуры

QLineEdit. Ввод с виртуальной клавиатуры

При использовании QLineEdit в приложении под андоид (Qt 57, Android 6

220