Как я могу разделить строку с помощью C ++, а затем выбрать последнюю часть этого? - PullRequest
0 голосов
/ 25 ноября 2018

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

std::string s = ">=scott>=tiger>=mushroom>=>=abcd>=";
std::string delimiter = ">=";

size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
    token = s.substr(0, pos);
    std::cout << token << std::endl;
    s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;

Я хочу вычислить номер строки и напечатать последнюю часть этогоМне нужно напечатать такую ​​строку: 3 abcd

1 Ответ

0 голосов
/ 25 ноября 2018

Редактировать : я добавил минимальное решение.


Минимальное решение

Предполагая, что я правильно понимаю проблему,Я бы сделал так, чтобы определить правильную функцию расщепления.Поскольку в вашем определении split кажется, что разделенные пустые строки игнорируются, я ожидаю, что следующая функция разделения решает текущую проблему.Эта функция считает количество непустых строк и, наконец, создает последнюю непустую строку:

std::pair<std::size_t, std::string> 
check(const std::string& str, const std::string& delimiter)
{    
    std::size_t count = 0;
    auto begin = str.begin();
    auto end   = str.begin();

    for(auto it = str.begin();
        it != str.cend();
        it += ((it == str.cend()) ? 0 : delimiter.length()) )
    {
        const auto preit = it;
        it = std::search(preit, str.cend(), delimiter.cbegin(), delimiter.cend());

        if(it != preit)
        {
            ++count;
            begin = preit;
            end   = it;
        }
    }

    return { count, std::string(begin, end) };
}

Используя эту функцию разделения следующим образом, мы можем получить желаемый результат 3 abcd.

ДЕМО здесь.

std::string s = ">=scott>=tiger>=mushroom>=>=abcd>=";
std::string delimiter = ">=";

const auto result = check(s, delimiter);
if(result.first != 0){
    std::cout << (result.first - 1) << " " << result.second << std::endl;    
}

Общие функции разделения

Если другое непустое разделениеСтроки также необходимы, желательно реализовать более общую функцию расщепления.Кроме того, поскольку общие функции расщепления были бы полезны в других задачах, и поэтому я думаю, что это хорошая возможность сделать это.Создавая строки в секции if вышеуказанной функции check и возвращая ее в std::vector, мы получаем более общую функцию расщепления:

std::vector<std::string> 
split(const std::string& str, const std::string& delimiter)
{    
    std::vector<std::string> strings;

    for(auto it = str.begin();
        it != str.cend();
        it += ((it == str.cend()) ? 0 : delimiter.length()) )
    {
        const auto preit = it;
        it = std::search(preit, str.cend(), delimiter.cbegin(), delimiter.cend());

        if(it != preit){
            strings.emplace_back(preit, it);
        }
    }

    return strings;
}

Используя эту функцию расщепления следующим образом, мы снова получаемжелаемый вывод 3 abcd.

DEMO здесь.

std::string s = ">=scott>=tiger>=mushroom>=>=abcd>=";
std::string delimiter = ">=";

const auto strings = split(s, delimiter);

if(!strings.empty()){
    std::cout << (strings.size() - 1) << " " << strings.back() << std::endl;
}

C ++ 17 и std::string_view

Кроме того, в C ++ 17 и более, std::string_view также доступна.Когда создается std::string_view, нет необходимости копировать данные, и это обеспечит эффективный метод.Таким образом, здесь я также предлагаю переносимую и универсальную функцию разделения для std::string и std::string_view.Используя почти одинаковые ctors std::string и std::string_view, то есть

basic_string(const charT* s, size_type n,
             const Allocator& a = Allocator());          

и

constexpr basic_string_view(const charT* str, size_type len);

и определяяСледующая функция шаблона с универсальной ссылкой

template<typename C>
auto split(C&& str, const std::string& delimiter)
{    
    std::vector<typename std::remove_reference<C>::type> strings;

    for (auto p = str.data(), end = p + str.length(); 
         p != end;
         p += ((p==end) ? 0 : delimiter.length()) ) 
    {
        const auto pre = p;
        p = std::search(pre, end, delimiter.cbegin(), delimiter.cend());

        if (p != pre)
        {
            strings.emplace_back(pre, p - pre);
        }
    }    

    return strings;
}

, мы можем разделить s на delimiter различными способами следующим образом.

DEMO здесь.

// std::string_view
const auto strings = split<std::string_view>(s, delimiter);

// std::string(s: lvalue reference)
const auto strings = split(s, delimiter);  

// std::string(s: rvalue)
const auto strings = split(std::move(s), delimiter);
...