ctype和字符串和容器

时间:2010-07-19 11:18:21

标签: c++ containers ctype

ctype facet函数是否有任何原因(isscan_isscan_not仅支持普通字符指针,而不支持基于迭代器的容器,如std :: string甚至是的std ::矢量... 然后可以写:

const ctype<char>& myctype = use_facet<std::ctype<char> >(locale(""));
string foo_str = "hi there here is a number: 748574 and text again";
vector<char> foo(foo_str.begin(),foo_str.end());

//then one could write

vector<char>::iterator num_begin_it = myctype.scan_is( ctype<char>::digit, foo.begin(), foo.end() );
vector<char> foo_num_1( foo, num_begin_it, myctype.scan_not(ctype<char>::digit, num_begin_it, foo.end() );

//instead of:
const char* num_begin_pc = myctype.scan_is(ctype<char>::digit, &foo[0], &foo[foo.size()-1]+1); // &foo[foo.size()-1]+1) instead of foo.end() is not quite readable.
vector<char> foo_num_2(num_begin_pc, myctype.scan_not(ctype<char>::digit, num_begin_pc, &foo[foo.size()-1]+1));

//appendix:
//STL/Boost solution, even more verbose:

function<bool(char)> is_digit_func =
    bind(
        mem_fn(static_cast<bool (ctype<char>::*)(ctype<char>::mask,char) const>(&ctype<char>::is)),
        &myctype,
        ctype<char>::digit,
        _1
    );
vector<char>::iterator num_begin_0x = find_if(foo.begin(), foo.end(),is_digit_func);
vector<char> foo_num_3(num_begin_0x,find_if(num_begin_0x, foo.end(),not1(is_digit_func)));

// all 3 foo_num_X will now contain "748574"

如果有人对标准委员会制定这些设计决策的原因有所了解,那会很酷吗?

是否有更好的(=更简洁的)方法来使用基于迭代器的容器的ctype函数?

STL / Boost解决方案有点好,如果它不需要

此外,我发现标准库中没有copy_if算法,但我已经是reason for this

1 个答案:

答案 0 :(得分:2)

主要原因是标准库不是作为一个连贯的整体开发的,而是包含了当时流行的几个库。

迭代器是“标准模板库”中的一个概念,它是标准容器,迭代器和算法库的基础。字符串和本地化库来自其他来源,它们没有使用迭代器。因为迭代器是如此有用,所以认为值得将它们改装到这些库中,但不是完全改变库的接口以在任何地方使用迭代器。

顺便说一下,您可能会发现&foo.back()+1&foo[0] + foo.size()&foo[foo.size()-1]+1更具可读性。您也不需要将字符串复制到矢量中以使用scan_isscan_not;这样的事情应该做的工作:

const char* str_begin = foo_str.c_str();
const char* str_end   = str_begin + foo_str.length();
const char* num_begin = myctype.scan_is(ctype<char>::digit, str_begin, str_end);
const char* num_end   = myctype.scan_not(ctype<char>::digit, num_begin, str_end);
std::string number(num_begin, num_end); // or `vector` if you really want