Разделить строку на слова несколькими разделителями - PullRequest
30 голосов
/ 01 октября 2011

У меня есть некоторый текст (значимый текст или арифметическое выражение), и я хочу разбить его на слова.
Если бы у меня был один разделитель, я бы использовал:

std::stringstream stringStream(inputString);
std::string word;
while(std::getline(stringStream, word, delimiter)) 
{
    wordVector.push_back(word);
}

Как я могуразбить строку на токены с несколькими разделителями?

Ответы [ 4 ]

41 голосов
/ 01 октября 2011

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

std::stringstream stringStream(inputString);
std::string line;
while(std::getline(stringStream, line)) 
{
    std::size_t prev = 0, pos;
    while ((pos = line.find_first_of(" ';", prev)) != std::string::npos)
    {
        if (pos > prev)
            wordVector.push_back(line.substr(prev, pos-prev));
        prev = pos+1;
    }
    if (prev < line.length())
        wordVector.push_back(line.substr(prev, std::string::npos));
}
18 голосов
/ 03 июня 2013

Если у вас есть повышение, вы можете использовать:

#include <boost/algorithm/string.hpp>
std::string inputString("One!Two,Three:Four");
std::string delimiters("|,:");
std::vector<std::string> parts;
boost::split(parts, inputString, boost::is_any_of(delimiters));
4 голосов
/ 04 апреля 2017

Я не знаю, почему никто не указал ручной путь, но вот он:

const std::string delims(";,:. \n\t");
inline bool isDelim(char c) {
    for (int i = 0; i < delims.size(); ++i)
        if (delims[i] == c)
            return true;
    return false;
}

и в функции:

std::stringstream stringStream(inputString);
std::string word; char c;

while (stringStream) {
    word.clear();

    // Read word
    while (!isDelim((c = stringStream.get()))) 
        word.push_back(c);
    if (c != EOF)
        stringStream.unget();

    wordVector.push_back(word);

    // Read delims
    while (isDelim((c = stringStream.get())));
    if (c != EOF)
        stringStream.unget();
}

Таким образом, вы можете сделать что-то полезное с разделителями, если хотите.

0 голосов
/ 22 декабря 2016

Если вам интересно, как сделать это самостоятельно, не используя boost.

Предполагая, что строка разделителя может быть очень длинной - скажем, M, проверка каждого символа в вашей строке, если это разделитель, будет стоить O (M) каждый, так что в цикле для всех символов в вашей исходной строке Пусть, скажем, в длину N, есть O (M * N).

Я бы использовал словарь (например, карту - от «разделителя» до «логическое значение» - но здесь я бы использовал простой логический массив, который имеет значение true в значении index = ascii для каждого разделителя).

Теперь перебираем строку и проверяем, является ли символ разделителем O (1), что в итоге дает нам O (N) в целом.

Вот мой пример кода:

const int dictSize = 256;    

vector<string> tokenizeMyString(const string &s, const string &del)
{
    static bool dict[dictSize] = { false};

    vector<string> res;
    for (int i = 0; i < del.size(); ++i) {      
        dict[del[i]] = true;
    }

    string token("");
    for (auto &i : s) {
        if (dict[i]) {
            if (!token.empty()) {
                res.push_back(token);
                token.clear();
            }           
        }
        else {
            token += i;
        }
    }
    if (!token.empty()) {
        res.push_back(token);
    }
    return res;
}


int main()
{
    string delString = "MyDog:Odie, MyCat:Garfield  MyNumber:1001001";
//the delimiters are " " (space) and "," (comma) 
    vector<string> res = tokenizeMyString(delString, " ,");

    for (auto &i : res) {

        cout << "token: " << i << endl;
    }
return 0;
}

Примечание: tokenizeMyString возвращает вектор по значению и сначала создает его в стеке, поэтому здесь мы используем мощь компилятора >>> RVO - оптимизация возвращаемого значения :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...