ctype 和字符串和容器

发布于 2024-09-10 07:29:51 字数 1795 浏览 2 评论 0原文

ctype 方面函数(isscan_isscan_not 仅支持普通 char 指针,而不支持基于迭代器的容器(如 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 算法,但我已经 原因

Is there any reason that the ctype facet functions (is,scan_is,scan_not only support plain char pointer, and not iterator based containers, like std::string or even a std::vector...
then one could write:

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"

Would be cool if anyone has some insight why the standard committee made those design decisions ?

And is there a better (=less verbose) way to make use of the ctype functions with iterator-based containers ?

The STL/Boost solution would be kinda OK, if it wouldnt need that

Additionally i found that there is no copy_if algorithm in the standard library, but i already the reason for this.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

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

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

顺便说一句,您可能会发现 &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

The main reason is that the Standard Library wasn't developed as a single coherent whole, but incorporates several libraries that were popular at the time.

Iterators were a concept from the "Standard Template Library", which was the basis for the standard Containers, Iterators and Algorithms libraries. The Strings and Localization libraries came from other sources, which did not use iterators. Because iterators are so useful, it was deemed worth the effort of retrofitting them to these libraries, but not to completely change the libraries' interfaces to use iterators everywhere.

By the way, you might find &foo.back()+1 or &foo[0] + foo.size() to be more readable than &foo[foo.size()-1]+1. You also don't need to copy the string into a vector to use scan_is and scan_not; something like this should do the job:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文