代码之家  ›  专栏  ›  技术社区  ›  smerlin

ctype、字符串和容器

  •  2
  • smerlin  · 技术社区  · 14 年前

    ctype facet函数( is , scan_is , scan_not 仅支持纯字符指针,而不支持基于迭代器的容器,如std::string甚至std::vector。。。 然后可以写:

    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 回复  |  直到 7 年前
        1
  •  2
  •   Mike Seymour    14 年前

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

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

    &foo.back()+1 &foo[0] + foo.size() 比…更易读 &foo[foo.size()-1]+1 . 也不需要将字符串复制到向量中即可使用 scan_is scan_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