首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >basic_string的前导/尾随空格不敏感性状

basic_string的前导/尾随空格不敏感性状
EN

Stack Overflow用户
提问于 2018-10-28 10:00:08
回答 2查看 65关注 0票数 3

我正在进行大量的解析/处理,其中给出了前导/尾随空格和不区分大小写。因此,我为std::basic_string(见下文)创建了一个基本的char特性,以节省一些工作。

这个特性不起作用,问题是basic_string的比较调用特征比较,如果求值为0,则返回大小的差异。在basic_string.h中,它表示比较的结果为非零返回,否则首先排序较短的。看起来他们明确不希望我这样做.

如果性状的比较结果为0,那么为什么会有额外的“较短排序”呢?还有,有什么解决办法吗?还是我必须自己拉绳子?

代码语言:javascript
复制
#include <cstring>
#include <iostream>

namespace csi{
template<typename T>
struct char_traits : std::char_traits<T>
{
    static int compare(T const*s1, T const*s2, size_t n){
        size_t n1(n);
        while(n1>0&&std::isspace(*s1))
            ++s1, --n1;
        while(n1>0&&std::isspace(s1[n1-1]))
            --n1;
        size_t n2(n);
        while(n2>0&&std::isspace(*s2))
            ++s2, --n2;
        while(n2>0&&std::isspace(s2[n2-1]))
            --n2;
        return strncasecmp(static_cast<char const*>(s1),
                           static_cast<char const*>(s2),
                           std::min(n1,n2));
    }
};
using string = std::basic_string<char,char_traits<char>>;
}

int main()
{
    using namespace csi;
    string s1 = "hello";
    string s2 = " HElLo ";
    std::cout << std::boolalpha
              << "s1==s2" << " " << (s1==s2) << std::endl;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-28 11:57:47

将具有多个可能的表示形式的数据转换为“标准”或“正常”形式的数据称为规范化。对于文本,它通常意味着删除重音,大小写,修整空格字符和/或格式字符。

如果在每个比较过程中在引擎盖下进行规范化,那么它是脆弱的。例如,如何对s1s2进行正确的测试?此外,它是不灵活的,例如,您不能显示其结果或缓存它的下一个比较。因此,作为显式规范化步骤,这样做既健壮又有效。

如果性状的比较结果为0,那么为什么会有额外的“较短排序”呢?

特征比较只需要比较n字符,那么当您比较"hellow""hello"时,它应该返回什么?它应该返回0。如果你以某种方式忽略了这个n,你就处于缺陷状态,因为这些特征应该与不以零结尾的std::string_view一起工作。如果删除大小比较,那么"hellow""hello"将比较您可能不想要的相等值。

票数 0
EN

Stack Overflow用户

发布于 2018-10-28 11:10:54

如果性状的比较结果为0,那么为什么会有额外的“较短排序”呢?

basic_string::compare()就是这样的已定义

还有,有什么解决办法吗?还是我必须自己拉绳子?

您的自定义char_traits似乎必须实现:

  • length(),返回字符串修整部分的长度,以及
  • move()copy(),用于复制该裁剪部件

然而,有一个潜在的问题,不能解决使用自定义的特点。basic_string有像basic_string(const CharT* s, size_type count, Allocator& alloc)这样的构造函数,或者像assigncompare这样的方法重载,它们使用C字符串及其长度--在这些情况下,Traits::length()不会被调用。如果有人使用这些方法之一,则该字符串可能包含尾随空格或尝试访问源字符串末尾以外的字符。

要解决这个问题,可以这样做:

代码语言:javascript
复制
class TrimmedString
{
public:
    // expose only "safe" methods:
    void assign(const char* s) { m_str.assign(s); }

private:
    std::basic_sttring<char, CustomTraits> m_str;
};

或者这个(可能更简单):

代码语言:javascript
复制
class TrimmedString : private std::basic_string<char, CustomTraits>
{
public:
    using BaseClass = std::basic_string<char, CustomTraits>; // for readability

    // make "safe" method public
    using BaseClass::length;
    using BaseClass::size;
    // etc.

    // wrappers for methods with "unsafe" overloads
    void assign(const char* s) { BaseClass::assign(s); }
};
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53030287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档