我正在进行大量的解析/处理,其中给出了前导/尾随空格和不区分大小写。因此,我为std::basic_string(见下文)创建了一个基本的char特性,以节省一些工作。
这个特性不起作用,问题是basic_string的比较调用特征比较,如果求值为0,则返回大小的差异。在basic_string.h中,它表示比较的结果为非零返回,否则首先排序较短的。看起来他们明确不希望我这样做.
如果性状的比较结果为0,那么为什么会有额外的“较短排序”呢?还有,有什么解决办法吗?还是我必须自己拉绳子?
#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;
}发布于 2018-10-28 11:57:47
将具有多个可能的表示形式的数据转换为“标准”或“正常”形式的数据称为规范化。对于文本,它通常意味着删除重音,大小写,修整空格字符和/或格式字符。
如果在每个比较过程中在引擎盖下进行规范化,那么它是脆弱的。例如,如何对s1和s2进行正确的测试?此外,它是不灵活的,例如,您不能显示其结果或缓存它的下一个比较。因此,作为显式规范化步骤,这样做既健壮又有效。
如果性状的比较结果为0,那么为什么会有额外的“较短排序”呢?
特征比较只需要比较n字符,那么当您比较"hellow"和"hello"时,它应该返回什么?它应该返回0。如果你以某种方式忽略了这个n,你就处于缺陷状态,因为这些特征应该与不以零结尾的std::string_view一起工作。如果删除大小比较,那么"hellow"和"hello"将比较您可能不想要的相等值。
发布于 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)这样的构造函数,或者像assign或compare这样的方法重载,它们使用C字符串及其长度--在这些情况下,Traits::length()不会被调用。如果有人使用这些方法之一,则该字符串可能包含尾随空格或尝试访问源字符串末尾以外的字符。
要解决这个问题,可以这样做:
class TrimmedString
{
public:
// expose only "safe" methods:
void assign(const char* s) { m_str.assign(s); }
private:
std::basic_sttring<char, CustomTraits> m_str;
};或者这个(可能更简单):
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); }
};https://stackoverflow.com/questions/53030287
复制相似问题