编写不区分大小写的字符串类
Posted
技术标签:
【中文标题】编写不区分大小写的字符串类【英文标题】:writing a case insenstive string class 【发布时间】:2014-08-19 15:40:04 【问题描述】:我正在阅读 Herb Sutter 的书Exceptional C++,在第二项中您需要编写一个不区分大小写的字符串类 ci_string,其行为如下:
#include <assert.h>
ci_string s("AbCdE");
// case insensitive
//
assert(s == "abcde");
assert(s == "ABCDE");
// still case-preserving, of course
//
assert(strcmp(s.c_str(), "AbCdE") == 0);
assert(strcmp(s.c_str(), "abcde") != 0);
我的想法是让这个类与std::string
相同,并且只覆盖operator==
:
#include <string>
#include <cctype>
using namespace std;
struct ci_string : string
bool operator==(const ci_string& lhs)
if (this->length() != lhs.length())
return false;
for (size_type i = 0; i != this->length(); ++i)
if (tolower((*this)[i]) != tolower(lhs[i]))
return false;
return true;
;
但是,如果将它与第一个代码结合使用,则此代码不会编译,因为没有合适的 ci_string
构造函数用于 const char[]
作为“AbCdE”,尽管父类有一个。
解决这个问题的最优雅的方法是什么?我希望代码尽可能短,不需要重写字符串的构造函数和成员函数,如c_str()
等。
【问题讨论】:
您可以使用basic_string
和 char_traits
进行不敏感比较。
你看过书中的实际解决方案了吗?或阅读here
我还没有查看解决方案。
继承不应该像struct ci_string : public string
吗?除此之外,继承可能是完全错误的方法。
@πάνταῥεῖ 不,除非你想变得冗长。如果有的话,最好说struct ci_string : private std::string
,因为在这种情况下,公共继承不是一个好主意。
【参考方案1】:
解决问题的更优雅的方法是使用char_traits
,如答案所示。
但为了避免使用您的方法的样板代码,您可以在子类中使用using string::string;
“复制”父构造函数。
【讨论】:
如果我尝试将using string::string;
放在子类中,我得到的是:error C2039: 'string' : is not a member of 'std::basic_string<char,std::char_traits<char>,std::allocator<char>>'
嗯,它确实适用于我的编译器。也许尝试使用 std::string
是 typedef 的实际类型:using basic_string<char>::basic_string;
现在是error C2886: 'basic_string<char,std::char_traits<char>,std::allocator<char>>' : symbol cannot be used in a member using-declaration
这个特性是在 c++11 中引入的。您的编译器似乎还不支持它。您必须为std::string
的每个构造函数定义一个构造函数并将它们委托给父级。
我不确定我是否理解。如果您定义了一个不区分大小写的字符特征(可能是从std::char_traits<char>
派生并覆盖了需要更改的少数函数),则没有需要复制的构造函数;你还在使用std::basic_string
。 (另一方面,您将需要实现<<
和>>
运算符和getline
;标准版本要求流和字符串使用相同的char_traits
。)
以上是关于编写不区分大小写的字符串类的主要内容,如果未能解决你的问题,请参考以下文章
编写不区分大小写的Cypher查询以匹配Neo4j中字符串的开头