Как отфильтровать символы из строки с помощью C ++ / Boost - PullRequest
3 голосов
/ 08 июля 2010

Кажется, это такой простой вопрос, поэтому я прошу прощения, если на него уже где-то ответили (мой поиск ничего не дал).

Я просто хочу отфильтровать строковый объект, чтобы он содержал только буквы, цифры и пробелы.

Вот что я попробовал:

#include "boost/algorithm/string/erase.hpp"
#include "boost/algorithm/string/classification.hpp"

std::wstring oldStr = "Bla=bla =&*\nSampleSampleSample ";
std::wstring newStr = boost::erase_all_copy(oldStr, !(boost::is_alnum() || 
                                                      boost::is_space()));

Но компилятору это совсем не нравится - кажется, что я могу поместить строку только во второй аргумент erase_all_copy, а не в этот is_alnum() материал.

Есть ли какое-то очевидное решение, которое я здесь упускаю?

Ответы [ 3 ]

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

С помощью алгоритмов std и Boost.Bind:

std::wstring s = ...
std::wstring new_s;
std::locale loc;
std::remove_copy_if(s.begin(), s.end(), std::back_inserter(new_s), 
    !(boost::bind(&std::isalnum<wchar_t>, _1, loc)||
      boost::bind(&std::isspace<wchar_t>, _1, loc)
));
1 голос
/ 08 июля 2010

Прошло много лет с тех пор, как я использовал boost, но, возможно, вы могли бы использовать erase_all_regex_copy () вместо erase_all_copy ()?Это может быть небольшим падением производительности, но это может быть вашим единственным выбором, кроме итерации по каждому элементу и проверки вручную.Если вы не знакомы с регулярными выражениями, то выражение, которое вы бы использовали в этом случае, было бы что-то вроде "[^ a-zA-Z0-9] +".

Для полноты картины, некоторые примерыкод:

#include "boost/regex.hpp"
#include "boost/algorithm/string/regex.hpp"

std::wstring oldStr = "Bla=bla =&*\nSampleSampleSample ";
std::wstring newStr = boost::erase_all_regex_copy(oldStr, boost::regex("[^a-zA-Z0-9 ]+"));
0 голосов
/ 14 января 2019

Для тех, кто не так мудр, вот функции ANSI и UNICODE, основанные на ответе Эрика Маленфанта:

std::string CleanString(const std::string& Input)
{
    std::string clean_string;
    std::locale loc;

    try {
        std::remove_copy_if(Input.begin(), Input.end(), std::back_inserter(clean_string),
            !(boost::bind(&std::isalnum<unsigned char>, _1, loc) || boost::bind(&std::isspace<unsigned char>, _1, loc)
        ));
    }
    catch (const std::bad_alloc& e) {
        std::cout << "Allocation failed: " << e.what() << '\n';
    }

    return clean_string;
}

std::wstring CleanString(const std::wstring& Input)
{
    std::wstring clean_string;
    std::locale loc;

    try {
        std::remove_copy_if(Input.begin(), Input.end(), std::back_inserter(clean_string),
            !(boost::bind(&std::isalnum<wchar_t>, _1, loc) ||
              boost::bind(&std::isspace<wchar_t>, _1, loc)
        ));
    } catch (const std::bad_alloc& e) {
        std::cout << "Allocation failed: " << e.what() << '\n';
    }
    return clean_string;
}

Демонстрация в сети: https://wandbox.org/permlink/MFTwXV4ZCi9nsdlC

Полный тестовый код для Linux:

#include <iostream>
#include <algorithm>
#include <cctype>
#include <boost/bind.hpp>

// Note on Linux we use char and not unsigned char!
std::string CleanString(const std::string& Input)
{
    std::string clean_string;
    std::locale loc;

    try {
        std::remove_copy_if(Input.begin(), Input.end(), std::back_inserter(clean_string),
            !(boost::bind(&std::isalnum<char>, _1, loc) || boost::bind(&std::isspace<char>, _1, loc)
        ));
    }
    catch (const std::bad_alloc& e) {
        std::cout << "Allocation failed: " << e.what() << '\n';
    } 
    catch (...)
    {
    }

    return clean_string;
}

std::wstring CleanString(const std::wstring& Input)
{
    std::wstring clean_string;
    std::locale loc;

    try {
        std::remove_copy_if(Input.begin(), Input.end(), std::back_inserter(clean_string),
            !(boost::bind(&std::isalnum<wchar_t>, _1, loc) ||
              boost::bind(&std::isspace<wchar_t>, _1, loc)
        ));
    } 
    catch (const std::bad_alloc& e) {
        std::cout << "Allocation failed: " << e.what() << '\n';
    }
    catch (...)
    {
    }

    return clean_string;
}

int main()
{
    std::string test_1 = "Bla=bla =&*\n Sample Sample Sample !$%^&*@~";

    std::string new_test_1 = CleanString(test_1);

    if (!new_test_1.empty())
    {
        std::cout << "ANSI: " << new_test_1 << std::endl;
    }

    std::wstring test_uc_1 = L"!$%^&*@~ test &*";

    std::wstring new_test_uc_1 = CleanString(test_uc_1);

    if (!new_test_uc_1.empty())
    {
        std::wcout << L"UNICODE: " << new_test_uc_1 << std::endl;
    }

    return 0;
}

Благодаря Эрику Маленфанту.

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