Разделить текст с помощью strtok без удаления разделителя C ++ - PullRequest
1 голос
/ 30 июля 2010

Как разделить текст на токены, используя strtok, не удаляя разделитель? Я хочу просто расколоться на их месте.

Ответы [ 5 ]

2 голосов
/ 30 июля 2010

Вы не можете.strtok выполняет разбиение, заменяя разделитель на «\ 0».Без этого разделения не произошло бы.

Однако вы могли бы создать функцию, которая бы выполняла расщепление, как это делает strtok, но найдя, где должна быть разбита строка, и (например) выделив хранилище.и копирование символов до разделителя в это хранилище.strcspn или strpbrk, вероятно, было бы полезным началом для этого.

1 голос
/ 30 июля 2010

Просто не используйте strtok.

Используйте оператор потока C ++.
Функцию getline () можно использовать с дополнительным параметром, который определяет маркер конца строки.

#include <string>
#include <sstream>
#include <vector>

int main()
{
    std::string         text("This is text; split by; the semicolon; that we will split into bits.");
    std::stringstream   textstr(text);

    std::string               line;
    std::vector<std::string>  data;
    while(std::getline(textstr,line,';'))
    {
        data.push_back(line);
    }
}

Проделав чуть больше работы, мы даже можем заставить алгоритмы STL оплачивать свою работу, нам просто нужно определить, как токен передается в потоковом режиме. Для этого просто определите класс токена (или структуру), а затем определите оператор >>, который читает до разделителя токена.

#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <algorithm>
#include <iostream>

struct Token
{
    std::string data;
    operator std::string() const { return data;}
};
std::istream& operator>>(std::istream& stream,Token& data)
{
    return std::getline(stream,data.data,';');
}

int main()
{
    std::string         text("This is text; split by; the semicolon; that we will split into bits.");
    std::stringstream   textstr(text);

    std::vector<std::string>  data;

    // This statement does the work of the loop from the last example.
    std::copy(std::istream_iterator<Token>(textstr),
              std::istream_iterator<Token>(),
              std::back_inserter(data)
             );

    // This just prints out the vector to the std::cout just to illustrate it worked.
    std::copy(data.begin(),data.end(),std::ostream_iterator<std::string>(std::cout,"\n"));
}
1 голос
/ 30 июля 2010

Можете ли вы использовать повышение? boost :: алгоритма :: split делает именно то, что вы хотите.

Можно, конечно, написать самому; это не похоже на сложность разбиения: (Примечание: я на самом деле не проверял это)

std::wstring source(L"Test\nString");
std::vector<std::wstring> result;
std::wstring::iterator start, end;
start = source.begin();
end = std::find(source.begin(), source.end(), L'\n');
for(; end != source.end(); start = end, end = std::find(end, source.end(), L'\n'))
    result.push_back(std::wstring(start, end));
result.push_back(std::wstring(start, end));
0 голосов
/ 30 июля 2010

Если ваша реализация libc имеет это, взгляните на strsep (3)

0 голосов
/ 30 июля 2010

Вы не можете.Поведение strtok заключается в том, что он заменяет разделитель символом NUL.Это поведение не настраивается.Чтобы вернуть каждую подстроку, включая разделитель, вам нужно будет найти функцию, отличную от strtok, или объединить strtok с некоторыми вашими собственными обработками.

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